Omit email, cache keypair

This commit is contained in:
Wildan M 2021-09-21 18:01:03 +07:00
commit d09a2d8cb5
3 changed files with 25 additions and 29 deletions

View file

@ -28,29 +28,20 @@ To forward from `www.old.com` to `old.com`, add these records to your DNS:
``` ```
www.old.com IN CNAME r.forwarddomain.net www.old.com IN CNAME r.forwarddomain.net
_.www.old.com IN TXT forward-domain=https://old.com/* _.www.old.com IN TXT forward-domain=https://old.com/*
_.www.old.com IN TXT forward-domain-cert-maintainer=<your email address>
``` ```
> IMPORTANT: replace `<your email address>` with your email address!
Because CNAME can't be used in apex domains, you can use A/AAAA records.<br> Because CNAME can't be used in apex domains, you can use A/AAAA records.<br>
To forward from `old.com` to `new.net`, add these records to your DNS: To forward from `old.com` to `new.net`, add these records to your DNS:
``` ```
old.com IN A 167.172.5.31 old.com IN A 167.172.5.31
_.old.com IN TXT forward-domain=https://new.net/* _.old.com IN TXT forward-domain=https://new.net/*
_.old.com IN TXT forward-domain-cert-maintainer=<your email address>
``` ```
> BETA service notice: IP addresses may change anytime. > BETA service notice: IP addresses may change anytime.
## FAQ ## FAQ
### Why email address?
This is required in order to sign HTTPS certificates.<br>
You can omit it but HTTPS redirects will not work.
### Is it really free? ### Is it really free?
Forwarding domains should be easy to setup.<br> Forwarding domains should be easy to setup.<br>

View file

@ -91,14 +91,14 @@ class Client {
* Generate a certificate from Let's Encrypt for your domain. * Generate a certificate from Let's Encrypt for your domain.
* *
* @param {String} domain - the domain you want a certificate for * @param {String} domain - the domain you want a certificate for
* @param {String} email - the email used to register the certificate
* *
* @return {Promise} * @return {Promise}
*/ */
async generateCertificate(domain, email) { async generateCertificate(domain) {
await this.directory() await this.directory()
await this.newNonce() await this.newNonce()
await this.newAccount(email) if (!this.myAccountUrl)
await this.newAccount()
const { const {
authzUrls, authzUrls,
@ -113,7 +113,7 @@ class Client {
const { const {
certificate, certificate,
privateKeyData privateKeyData
} = await this.finalizeOrder(finalizeUrl, domain, email) } = await this.finalizeOrder(finalizeUrl, domain)
return { return {
certificate, certificate,
@ -228,7 +228,7 @@ class Client {
return res.data return res.data
} }
async finalizeOrder(finalizeUrl, domain, email) { async finalizeOrder(finalizeUrl, domain) {
const { const {
privateKey privateKey
} = await generateKeyPair(common.CERTIFICATE_KEY_ALGORITHM) } = await generateKeyPair(common.CERTIFICATE_KEY_ALGORITHM)
@ -240,7 +240,6 @@ class Client {
} = await createCsr({ } = await createCsr({
clientKey, clientKey,
commonName: domain, commonName: domain,
email
}) })
// "The CSR is sent in the base64url-encoded version of the DER format. // "The CSR is sent in the base64url-encoded version of the DER format.
@ -304,7 +303,6 @@ class Client {
nonce: this.replayNonce, nonce: this.replayNonce,
url: this.newAccountUrl url: this.newAccountUrl
}, { }, {
contact: emails.map(email => 'mailto:' + email),
termsOfServiceAgreed: true termsOfServiceAgreed: true
}) })

View file

@ -7,10 +7,12 @@ const {
ensureDir, ensureDir,
findTxtRecord findTxtRecord
} = require('./util'); } = require('./util');
const { default: AwaitLock } = require('await-lock'); const {
const record_email_prefix = 'forward-domain-cert-maintainer='; default: AwaitLock
const client = new certnode.Client(); } = require('await-lock');
const certsDir = path.join(__dirname, '../.certs'); const certsDir = path.join(__dirname, '../.certs');
const accountDir = path.join(__dirname, '../.certs/account');
const client = new certnode.Client();
/** /**
* @type {Object<string, {cert: any, key: any, expire: number}>} * @type {Object<string, {cert: any, key: any, expire: number}>}
@ -22,13 +24,6 @@ function getCertCachePath(host) {
return path.join(certsDir, hash.substr(0, 2), hash.substr(2), host); return path.join(certsDir, hash.substr(0, 2), hash.substr(2), host);
} }
/**
* @param {string} host
*/
async function findMaintainerEmail(host) {
return await findTxtRecord(host, record_email_prefix);
}
/** /**
* @param {string} host * @param {string} host
*/ */
@ -56,7 +51,7 @@ async function buildCache(host) {
const { const {
certificate, certificate,
privateKeyData privateKeyData
} = await client.generateCertificate(host, await findMaintainerEmail(host)); } = await client.generateCertificate(host);
await fs.promises.writeFile(certP, certificate); await fs.promises.writeFile(certP, certificate);
await certnode.writeKeyToFile(keyP, privateKeyData, ''); await certnode.writeKeyToFile(keyP, privateKeyData, '');
const expire = (Date.now() + 45 * 86400 * 1000); const expire = (Date.now() + 45 * 86400 * 1000);
@ -88,7 +83,11 @@ async function getKeyCert(servername) {
let lock = new AwaitLock(); let lock = new AwaitLock();
const SniListener = async (servername, ctx) => { /**
* @param {string} servername
* @param {(err: any, cb: tls.SecureContext) => void} ctx
*/
async function SniListener(servername, ctx) {
// Had to use lock because the best authenticator // Had to use lock because the best authenticator
// library seems don't yet fully stateless. // library seems don't yet fully stateless.
// Generate fresh account keys for Let's Encrypt // Generate fresh account keys for Let's Encrypt
@ -104,8 +103,16 @@ const SniListener = async (servername, ctx) => {
} }
const SniPrepare = async () => { const SniPrepare = async () => {
await client.generateAccountKeyPair()
await ensureDir(certsDir); await ensureDir(certsDir);
await ensureDir(accountDir);
if (fs.existsSync(path.join(accountDir, 'privateKey.pem')) &&
fs.existsSync(path.join(accountDir, 'publicKey.pem'))) {
await client.importAccountKeyPair(accountDir, '');
} else {
await client.generateAccountKeyPair();
await client.exportAccountKeyPair(accountDir, '');
}
} }
module.exports = { module.exports = {