perf: 优化证书申请成功率

pull/148/head
xiaojunnuo 2024-08-23 13:15:06 +08:00
parent 453f1baa0b
commit 968c4690a0
8 changed files with 78 additions and 20 deletions

View File

@ -137,7 +137,12 @@ module.exports = async (client, userOpts) => {
} }
else { else {
log(`[auto] [${d}] Running challenge verification`); log(`[auto] [${d}] Running challenge verification`);
await client.verifyChallenge(authz, challenge); try {
await client.verifyChallenge(authz, challenge);
}
catch (e) {
log(`[auto] [${d}] challenge verification threw error: ${e.message}`);
}
} }
/* Complete challenge and wait for valid status */ /* Complete challenge and wait for valid status */
@ -170,11 +175,41 @@ module.exports = async (client, userOpts) => {
throw e; throw e;
} }
}; };
const domainSets = [];
const challengePromises = authorizations.map((authz) => async () => { authorizations.forEach((authz) => {
await challengeFunc(authz); const d = authz.identifier.value;
let setd = false;
// eslint-disable-next-line no-restricted-syntax
for (const group of domainSets) {
if (!group[d]) {
group[d] = authz;
setd = true;
}
}
if (!setd) {
const group = {};
group[d] = authz;
domainSets.push(group);
}
}); });
const allChallengePromises = [];
// eslint-disable-next-line no-restricted-syntax
for (const domainSet of domainSets) {
const challengePromises = [];
// eslint-disable-next-line guard-for-in,no-restricted-syntax
for (const domain in domainSet) {
const authz = domainSet[domain];
challengePromises.push(async () => {
log(`[auto] [${domain}] Starting challenge`);
await challengeFunc(authz);
});
}
allChallengePromises.push(challengePromises);
}
log(`[auto] challengeGroups:${allChallengePromises.length}`);
function runAllPromise(tasks) { function runAllPromise(tasks) {
let promise = Promise.resolve(); let promise = Promise.resolve();
tasks.forEach((task) => { tasks.forEach((task) => {
@ -195,9 +230,15 @@ module.exports = async (client, userOpts) => {
} }
try { try {
log('开始challenge'); log(`开始challenge${allChallengePromises.length}`);
await runPromisePa(challengePromises); let i = 0;
// eslint-disable-next-line no-restricted-syntax
for (const challengePromises of allChallengePromises) {
i += 1;
log(`开始第${i}`);
// eslint-disable-next-line no-await-in-loop
await runPromisePa(challengePromises);
}
log('challenge结束'); log('challenge结束');
// log('[auto] Waiting for challenge valid status'); // log('[auto] Waiting for challenge valid status');

View File

@ -55,7 +55,7 @@ class HttpClient {
*/ */
async request(url, method, opts = {}) { async request(url, method, opts = {}) {
if (this.urlMapping && this.urlMapping.enabled === true && this.urlMapping.mappings) { if (this.urlMapping && this.urlMapping.mappings) {
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
for (const key in this.urlMapping.mappings) { for (const key in this.urlMapping.mappings) {
if (url.includes(key)) { if (url.includes(key)) {

View File

@ -72,7 +72,7 @@ async function spawn(opts: SpawnOption): Promise<string> {
let stderr = ""; let stderr = "";
return safePromise((resolve, reject) => { return safePromise((resolve, reject) => {
const ls = childProcess.spawn(cmd, { const ls = childProcess.spawn(cmd, {
shell: process.platform == "win32", shell: true,
env: { env: {
...process.env, ...process.env,
...opts.env, ...opts.env,

View File

@ -13,7 +13,7 @@ export type CertInfo = {
key: string; key: string;
csr: string; csr: string;
}; };
export type SSLProvider = "letsencrypt" | "buypass" | "zerossl"; export type SSLProvider = "letsencrypt" | "google" | "zerossl";
type AcmeServiceOptions = { type AcmeServiceOptions = {
userContext: IContext; userContext: IContext;
logger: Logger; logger: Logger;
@ -42,10 +42,18 @@ export class AcmeService {
}); });
} }
async getAccountConfig(email: string): Promise<any> { async getAccountConfig(email: string, urlMapping: UrlMapping): Promise<any> {
const conf = (await this.userContext.getObj(this.buildAccountKey(email))) || {}; const conf = (await this.userContext.getObj(this.buildAccountKey(email))) || {};
if (conf.accountUrl?.indexOf("letsencrypt.proxy.handsfree.work")) { if (urlMapping && urlMapping.mappings) {
conf.accountUrl = conf.accountUrl.replace("letsencrypt.proxy.handsfree.work", "acme-v02.api.letsencrypt.org"); for (const key in urlMapping.mappings) {
if (Object.prototype.hasOwnProperty.call(urlMapping.mappings, key)) {
const element = urlMapping.mappings[key];
if (conf.accountUrl?.indexOf(element) > -1) {
//如果用了代理url要替换回去
conf.accountUrl = conf.accountUrl.replace(element, key);
}
}
}
} }
return conf; return conf;
} }
@ -59,7 +67,14 @@ export class AcmeService {
} }
async getAcmeClient(email: string, isTest = false): Promise<acme.Client> { async getAcmeClient(email: string, isTest = false): Promise<acme.Client> {
const conf = await this.getAccountConfig(email); const urlMapping: UrlMapping = {
enabled: false,
mappings: {
"acme-v02.api.letsencrypt.org": "letsencrypt.proxy.handsfree.work",
"dv.acme-v02.api.pki.goog": "google.proxy.handsfree.work",
},
};
const conf = await this.getAccountConfig(email, urlMapping);
if (conf.key == null) { if (conf.key == null) {
conf.key = await this.createNewKey(); conf.key = await this.createNewKey();
await this.saveAccountConfig(email, conf); await this.saveAccountConfig(email, conf);
@ -70,19 +85,15 @@ export class AcmeService {
} else { } else {
directoryUrl = acme.directory[this.sslProvider].production; directoryUrl = acme.directory[this.sslProvider].production;
} }
const urlMapping: UrlMapping = { enabled: false, mappings: {} };
if (this.options.useMappingProxy) { if (this.options.useMappingProxy) {
urlMapping.enabled = true; urlMapping.enabled = true;
urlMapping.mappings = {
"acme-v02.api.letsencrypt.org": "letsencrypt.proxy.handsfree.work",
};
} }
const client = new acme.Client({ const client = new acme.Client({
directoryUrl: directoryUrl, directoryUrl: directoryUrl,
accountKey: conf.key, accountKey: conf.key,
accountUrl: conf.accountUrl, accountUrl: conf.accountUrl,
externalAccountBinding: this.eab, externalAccountBinding: this.eab,
backoffAttempts: 30, backoffAttempts: 15,
backoffMin: 5000, backoffMin: 5000,
backoffMax: 10000, backoffMax: 10000,
urlMapping, urlMapping,

View File

@ -34,7 +34,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
options: [ options: [
{ value: "letsencrypt", label: "Let's Encrypt" }, { value: "letsencrypt", label: "Let's Encrypt" },
// { value: "letsencrypt-proxy", label: "Let's Encrypt代理letsencrypt.org无法访问时使用" }, // { value: "letsencrypt-proxy", label: "Let's Encrypt代理letsencrypt.org无法访问时使用" },
// { value: "buypass", label: "Buypass" }, { value: "google", label: "Google" },
{ value: "zerossl", label: "ZeroSSL" }, { value: "zerossl", label: "ZeroSSL" },
], ],
}, },

View File

@ -55,7 +55,7 @@
<a-input v-model:value="testFormState.receiver" /> <a-input v-model:value="testFormState.receiver" />
</a-form-item> </a-form-item>
<a-form-item :wrapper-col="{ offset: 8, span: 16 }"> <a-form-item :wrapper-col="{ offset: 8, span: 16 }">
<a-button type="primary" html-type="submit">测试</a-button> <a-button type="primary" :loading="testFormState.loading" html-type="submit">测试</a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
</div> </div>

View File

@ -6,3 +6,6 @@ typeorm:
default: default:
logging: false logging: false
plus:
serverBaseUrl: 'https://api.ai.handsfree.work/'

View File

@ -88,6 +88,9 @@ const development = {
system: { system: {
resetAdminPasswd: false, resetAdminPasswd: false,
}, },
plus: {
serverBaseUrl: 'http://127.0.0.1:11007',
},
} as MidwayConfig; } as MidwayConfig;
mergeConfig(development, 'development'); mergeConfig(development, 'development');