mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-09-20 07:16:05 +08:00
fix(SNI): disable SNI certificate autogeneration by default
This commit is contained in:
parent
ec4a2a25d7
commit
ecbdc9be5f
|
@ -19,7 +19,8 @@ keyExponent = 65537
|
||||||
|
|
||||||
[autogenerate]
|
[autogenerate]
|
||||||
# If enabled then automatically generates TLS certificates based on SNI servernames
|
# If enabled then automatically generates TLS certificates based on SNI servernames
|
||||||
enabled = true
|
enabled = false
|
||||||
|
|
||||||
[autogenerate.cnameMapping]
|
[autogenerate.cnameMapping]
|
||||||
# Sudomain CNAME mapping
|
# Sudomain CNAME mapping
|
||||||
# "abc" = ["def.com"] means that if the SNI servername domain is "abc.{domain}"
|
# "abc" = ["def.com"] means that if the SNI servername domain is "abc.{domain}"
|
||||||
|
@ -27,9 +28,10 @@ enabled = true
|
||||||
# If multiple CNAME targets are defined (eg ["def.com", "bef.com"], then at least 1 must match.
|
# If multiple CNAME targets are defined (eg ["def.com", "bef.com"], then at least 1 must match.
|
||||||
# Additionally, there must be at least 1 email account with "@{domain}" address.
|
# Additionally, there must be at least 1 email account with "@{domain}" address.
|
||||||
# If there is no match, then TLS certificate is not generated.
|
# If there is no match, then TLS certificate is not generated.
|
||||||
imap = ["imap.example.com"]
|
|
||||||
smtp = ["smtp.example.com"]
|
# imap = ["imap.example.com"]
|
||||||
pop3 = ["imap.example.com"]
|
# smtp = ["smtp.example.com"]
|
||||||
|
# pop3 = ["imap.example.com"]
|
||||||
|
|
||||||
[agent]
|
[agent]
|
||||||
# If enabled then starts a HTTP server that listens for ACME verification requests
|
# If enabled then starts a HTTP server that listens for ACME verification requests
|
||||||
|
|
|
@ -631,6 +631,15 @@ indexes:
|
||||||
expires: 1
|
expires: 1
|
||||||
'_acme.lastRenewalCheck': 1
|
'_acme.lastRenewalCheck': 1
|
||||||
|
|
||||||
|
- collection: certs
|
||||||
|
index:
|
||||||
|
name: garbage_check
|
||||||
|
key:
|
||||||
|
acme: 1
|
||||||
|
updated: 1
|
||||||
|
expires: 1
|
||||||
|
autogenerated: 1
|
||||||
|
|
||||||
- collection: audits
|
- collection: audits
|
||||||
index:
|
index:
|
||||||
name: user_expire_time
|
name: user_expire_time
|
||||||
|
|
|
@ -19,7 +19,9 @@ const { promisify } = require('util');
|
||||||
const generateKeyPair = promisify(crypto.generateKeyPair);
|
const generateKeyPair = promisify(crypto.generateKeyPair);
|
||||||
|
|
||||||
const CERT_RENEW_TTL = 30 * 24 * 3600 * 1000;
|
const CERT_RENEW_TTL = 30 * 24 * 3600 * 1000;
|
||||||
const CERT_RENEW_DELAY = 24 * 3600 * 100;
|
const CERT_RENEW_DELAY = 24 * 3600 * 1000;
|
||||||
|
// delete uninitialized certificates after 1 day
|
||||||
|
const CERT_GARBAGE_TTL = 24 * 2300 * 1000;
|
||||||
|
|
||||||
class CertHandler {
|
class CertHandler {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
@ -110,6 +112,22 @@ class CertHandler {
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async clearGarbage() {
|
||||||
|
// delete expired and uninitialized SNI certificates
|
||||||
|
let r = await this.database.collection('certs').deleteMany({
|
||||||
|
acme: true,
|
||||||
|
updated: {
|
||||||
|
$lt: new Date(Date.now() + CERT_GARBAGE_TTL)
|
||||||
|
},
|
||||||
|
$or: [{ expires: { $exists: false } }, { expires: { $lt: new Date() } }],
|
||||||
|
autogenerated: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (r?.deletedCount) {
|
||||||
|
log.verbose('Certs', 'Deleted uninitialized and expired autogenerated certificates. count=%s', r?.deletedCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async getNextRenewal() {
|
async getNextRenewal() {
|
||||||
let r = await this.database.collection('certs').findOneAndUpdate(
|
let r = await this.database.collection('certs').findOneAndUpdate(
|
||||||
{
|
{
|
||||||
|
@ -391,7 +409,14 @@ class CertHandler {
|
||||||
{
|
{
|
||||||
servername
|
servername
|
||||||
},
|
},
|
||||||
{ $set: certData, $inc: { v: 1 }, $setOnInsert: { servername, created: new Date() } },
|
{
|
||||||
|
$set: certData,
|
||||||
|
$inc: { v: 1 },
|
||||||
|
$setOnInsert: {
|
||||||
|
servername,
|
||||||
|
created: new Date()
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
upsert: true,
|
upsert: true,
|
||||||
returnDocument: 'after'
|
returnDocument: 'after'
|
||||||
|
@ -659,11 +684,14 @@ class CertHandler {
|
||||||
// not a FQDN
|
// not a FQDN
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subdomain = domain.substring(0, dotPos).toLowerCase().trim();
|
const subdomain = domain.substring(0, dotPos).toLowerCase().trim();
|
||||||
const maindomain = domain
|
const maindomain = tools.normalizeDomain(domain.substring(dotPos + 1));
|
||||||
.substring(dotPos + 1)
|
|
||||||
.toLowerCase()
|
if (!this.acmeConfig.autogenerate?.cnameMapping?.hasOwnProperty(subdomain)) {
|
||||||
.trim();
|
log.verbose('Certs', 'Skip ACME. reason="unsupported subdomain" action=precheck domain=%s', domain);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let subdomainTargets = [].concat(this.acmeConfig.autogenerate?.cnameMapping?.[subdomain] || []);
|
let subdomainTargets = [].concat(this.acmeConfig.autogenerate?.cnameMapping?.[subdomain] || []);
|
||||||
if (!subdomainTargets.length) {
|
if (!subdomainTargets.length) {
|
||||||
|
|
|
@ -6,6 +6,12 @@ const config = require('wild-config');
|
||||||
let run = async (task, data, options) => {
|
let run = async (task, data, options) => {
|
||||||
const { acquireCert, certHandler } = options;
|
const { acquireCert, certHandler } = options;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await certHandler.clearGarbage();
|
||||||
|
} catch (err) {
|
||||||
|
log.error('Tasks', 'task=acme-update id=%s action=clear-garbage error=%s', task._id, err.message);
|
||||||
|
}
|
||||||
|
|
||||||
let certData;
|
let certData;
|
||||||
while ((certData = await certHandler.getNextRenewal())) {
|
while ((certData = await certHandler.getNextRenewal())) {
|
||||||
let cert = await acquireCert(certData.servername, config.acme, certData, certHandler);
|
let cert = await acquireCert(certData.servername, config.acme, certData, certHandler);
|
||||||
|
|
Loading…
Reference in a new issue