mirror of https://github.com/certd/certd
perf: 优化证书申请速度和成功率,反代地址优化,google基本可以稳定请求。增加请求重试。
parent
a705182b85
commit
41d9c3ac83
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
|
@ -0,0 +1,5 @@
|
||||||
|
# 如何强制重新执行任务
|
||||||
|
|
||||||
|
## 强制重新执行任务
|
||||||
|
|
||||||
|

|
|
@ -182,12 +182,19 @@ module.exports = async (client, userOpts) => {
|
||||||
|
|
||||||
authorizations.forEach((authz) => {
|
authorizations.forEach((authz) => {
|
||||||
const d = authz.identifier.value;
|
const d = authz.identifier.value;
|
||||||
|
log(`authorization:domain = ${d}, value = ${JSON.stringify(authz)}`);
|
||||||
|
|
||||||
|
if (authz.status === 'valid') {
|
||||||
|
log(`[auto] [${d}] Authorization already has valid status, no need to complete challenges`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
let setd = false;
|
let setd = false;
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
for (const group of domainSets) {
|
for (const group of domainSets) {
|
||||||
if (!group[d]) {
|
if (!group[d]) {
|
||||||
group[d] = authz;
|
group[d] = authz;
|
||||||
setd = true;
|
setd = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!setd) {
|
if (!setd) {
|
||||||
|
@ -197,6 +204,8 @@ module.exports = async (client, userOpts) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// log(`domainSets:${JSON.stringify(domainSets)}`);
|
||||||
|
|
||||||
const allChallengePromises = [];
|
const allChallengePromises = [];
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
for (const domainSet of domainSets) {
|
for (const domainSet of domainSets) {
|
||||||
|
@ -252,17 +261,34 @@ module.exports = async (client, userOpts) => {
|
||||||
log(`证书申请失败${e.message}`);
|
log(`证书申请失败${e.message}`);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
if (client.opts.sslProvider !== 'google') {
|
||||||
|
// letsencrypt 如果同时检出两个TXT记录,会以第一个为准,就会校验失败,所以需要提前删除
|
||||||
|
log(`清理challenge痕迹,length:${clearTasks.length}`);
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await runAllPromise(clearTasks);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
log('清理challenge失败');
|
||||||
|
log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
log(`清理challenge痕迹,length:${clearTasks.length}`);
|
if (client.opts.sslProvider === 'google') {
|
||||||
try {
|
// google 相同的域名txt记录是一样的,不能提前删除,否则校验失败
|
||||||
|
log(`清理challenge痕迹,length:${clearTasks.length}`);
|
||||||
|
try {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await runAllPromise(clearTasks);
|
await runAllPromise(clearTasks);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log('清理challenge失败');
|
log('清理challenge失败');
|
||||||
log(e);
|
log(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -558,6 +558,7 @@ class AcmeClient {
|
||||||
|
|
||||||
const verifyFn = async (abort) => {
|
const verifyFn = async (abort) => {
|
||||||
if (this.opts.signal && this.opts.signal.aborted) {
|
if (this.opts.signal && this.opts.signal.aborted) {
|
||||||
|
abort();
|
||||||
throw new Error('用户取消');
|
throw new Error('用户取消');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ exports.setLogger = (fn) => {
|
||||||
* @param {string} msg Message
|
* @param {string} msg Message
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.log = (msg) => {
|
exports.log = (...msg) => {
|
||||||
debug(msg);
|
debug(...msg);
|
||||||
logger(msg);
|
logger(...msg);
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,6 +37,7 @@ export type UrlMapping={
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface ClientOptions {
|
export interface ClientOptions {
|
||||||
|
sslProvider:string;
|
||||||
directoryUrl: string;
|
directoryUrl: string;
|
||||||
accountKey: PrivateKeyBuffer | PrivateKeyString;
|
accountKey: PrivateKeyBuffer | PrivateKeyString;
|
||||||
accountUrl?: string;
|
accountUrl?: string;
|
||||||
|
|
|
@ -89,12 +89,15 @@ export class AcmeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAcmeClient(email: string, isTest = false): Promise<acme.Client> {
|
async getAcmeClient(email: string, isTest = false): Promise<acme.Client> {
|
||||||
|
const mappings = {};
|
||||||
|
if (this.sslProvider === "google") {
|
||||||
|
mappings["acme-v02.api.letsencrypt.org"] = this.options.reverseProxy || "le.px.certd.handfree.work";
|
||||||
|
} else if (this.sslProvider === "letsencrypt") {
|
||||||
|
mappings["dv.acme-v02.api.pki.goog"] = this.options.reverseProxy || "gg.px.certd.handfree.work";
|
||||||
|
}
|
||||||
const urlMapping: UrlMapping = {
|
const urlMapping: UrlMapping = {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
mappings: {
|
mappings,
|
||||||
"acme-v02.api.letsencrypt.org": this.options.reverseProxy || "le.px.certd.handfree.work",
|
|
||||||
"dv.acme-v02.api.pki.goog": this.options.reverseProxy || "gg.px.certd.handfree.work",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
const conf = await this.getAccountConfig(email, urlMapping);
|
const conf = await this.getAccountConfig(email, urlMapping);
|
||||||
if (conf.key == null) {
|
if (conf.key == null) {
|
||||||
|
@ -119,6 +122,7 @@ export class AcmeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const client = new acme.Client({
|
const client = new acme.Client({
|
||||||
|
sslProvider: this.sslProvider,
|
||||||
directoryUrl: directoryUrl,
|
directoryUrl: directoryUrl,
|
||||||
accountKey: conf.key,
|
accountKey: conf.key,
|
||||||
accountUrl: conf.accountUrl,
|
accountUrl: conf.accountUrl,
|
||||||
|
@ -172,7 +176,7 @@ export class AcmeService {
|
||||||
this.logger.info(`Would create TXT record "${fullRecord}" with value "${recordValue}"`);
|
this.logger.info(`Would create TXT record "${fullRecord}" with value "${recordValue}"`);
|
||||||
|
|
||||||
let domain = parseDomain(fullDomain);
|
let domain = parseDomain(fullDomain);
|
||||||
this.logger.info("解析到域名domain=", domain);
|
this.logger.info("解析到域名domain=" + domain);
|
||||||
|
|
||||||
if (domainsVerifyPlan) {
|
if (domainsVerifyPlan) {
|
||||||
//按照计划执行
|
//按照计划执行
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
export const headerResource = [
|
export const headerResource = [
|
||||||
{
|
{
|
||||||
title: "文档",
|
title: "文档",
|
||||||
path: "https://certd.docmirror.cn"
|
path: "https://certd.docmirror.cn",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:document-text-outline"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "源码",
|
title: "源码",
|
||||||
|
|
|
@ -170,6 +170,9 @@ h1, h2, h3, h4, h5, h6 {
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.iconify{
|
||||||
|
//font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-box {
|
.icon-box {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|
|
@ -101,8 +101,9 @@
|
||||||
<fs-icon
|
<fs-icon
|
||||||
v-if="!editMode"
|
v-if="!editMode"
|
||||||
class="pointer color-blue ml-2"
|
class="pointer color-blue ml-2"
|
||||||
title="完全重新运行此步骤"
|
style="font-size: 16px"
|
||||||
icon="SyncOutlined"
|
title="强制重新执行此步骤"
|
||||||
|
icon="icon-park-outline:replay-music"
|
||||||
@click="run(item.id)"
|
@click="run(item.id)"
|
||||||
></fs-icon>
|
></fs-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -37,8 +37,12 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
|
||||||
}
|
}
|
||||||
|
|
||||||
async getZoneId(domain: string) {
|
async getZoneId(domain: string) {
|
||||||
|
this.logger.info('获取zoneId:', domain);
|
||||||
const url = `https://api.cloudflare.com/client/v4/zones?name=${domain}`;
|
const url = `https://api.cloudflare.com/client/v4/zones?name=${domain}`;
|
||||||
const res = await this.doRequestApi(url, null, 'get');
|
const res = await this.doRequestApi(url, null, 'get');
|
||||||
|
if (res.result.length === 0) {
|
||||||
|
throw new Error(`未找到域名${domain}的zoneId`);
|
||||||
|
}
|
||||||
return res.result[0].id;
|
return res.result[0].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue