From 86ce00adf92ff98fead87a3eaaa6631036708f47 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 12 Nov 2025 23:56:02 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=94=AF=E6=8C=81=E4=BD=BF=E7=94=A8let?= =?UTF-8?q?encrypt=E6=B5=8B=E8=AF=95=E7=8E=AF=E5=A2=83=E7=94=B3=E8=AF=B7ip?= =?UTF-8?q?=E8=AF=81=E4=B9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- packages/core/acme-client/src/auto.js | 21 ++++++++-- packages/core/basic/src/utils/util.domain.ts | 40 +++++++++++++++---- .../src/plugin/cert-plugin/acme.ts | 32 +++++++-------- 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9a59ecdae..217769ea5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,6 @@ "typescript.tsc.autoDetect": "watch", "git.scanRepositories": [ "./packages/pro" - ] + ], + "editor.defaultFormatter": "dbaeumer.vscode-eslint" } \ No newline at end of file diff --git a/packages/core/acme-client/src/auto.js b/packages/core/acme-client/src/auto.js index e87e288ac..ad3f1d3c4 100644 --- a/packages/core/acme-client/src/auto.js +++ b/packages/core/acme-client/src/auto.js @@ -4,6 +4,9 @@ import { readCsrDomains } from "./crypto/index.js"; import { wait } from "./wait.js"; import { CancelError } from "./error.js"; +import { domainUtils } from '@certd/basic'; + + const defaultOpts = { @@ -65,7 +68,7 @@ export default async (client, userOpts) => { * Parse domains from CSR */ - log("[auto] Parsing domains from Certificate Signing Request "); + log("[auto] Parsing domains from Certificate Signing Request"); const { commonName, altNames } = readCsrDomains(opts.csr); const uniqueDomains = Array.from(new Set([commonName].concat(altNames).filter((d) => d))); @@ -76,9 +79,21 @@ export default async (client, userOpts) => { */ log("[auto] Placing new certificate order with ACME provider"); - const orderPayload = { identifiers: uniqueDomains.map((d) => ({ type: "dns", value: d })) }; - if (opts.profile && client.sslProvider === 'letsencrypt' ){ + + let hasIp = false + const orderPayload = { identifiers: uniqueDomains.map((d) =>{ + // 判断是否为IP(v4或v6),否则按域名处理 + const type = domainUtils.isIp(d) ? 'ip' : 'dns'; + if(type === 'ip'){ + hasIp = true + } + return { type, value: d } + }) }; + if (opts.profile && client.sslProvider.startsWith("letsencrypt") ){ orderPayload.profile = opts.profile; + if(hasIp){ + orderPayload.profile = "shortlived" + } } const order = await client.createOrder(orderPayload); const authorizations = await client.getAuthorizations(order); diff --git a/packages/core/basic/src/utils/util.domain.ts b/packages/core/basic/src/utils/util.domain.ts index 5e1584eeb..ed08f0d22 100644 --- a/packages/core/basic/src/utils/util.domain.ts +++ b/packages/core/basic/src/utils/util.domain.ts @@ -7,29 +7,29 @@ function match(targetDomains: string | string[], inDomains: string[]) { return false; } - if (typeof targetDomains === 'string') { + if (typeof targetDomains === "string") { targetDomains = [targetDomains]; } for (let targetDomain of targetDomains) { let matched = false; - if (targetDomain.startsWith('.')) { - targetDomain = '*' + targetDomain; + if (targetDomain.startsWith(".")) { + targetDomain = "*" + targetDomain; } for (let inDomain of inDomains) { - if (inDomain.startsWith('.')) { - inDomain = '*' + inDomain; + if (inDomain.startsWith(".")) { + inDomain = "*" + inDomain; } if (targetDomain === inDomain) { matched = true; break; } - if (!inDomain.startsWith('*.')) { + if (!inDomain.startsWith("*.")) { //不可能匹配 continue; } //子域名匹配通配符即可 - const firstDotIndex = targetDomain.indexOf('.'); + const firstDotIndex = targetDomain.indexOf("."); const targetDomainSuffix = targetDomain.substring(firstDotIndex + 1); if (targetDomainSuffix === inDomain.substring(2)) { matched = true; @@ -46,6 +46,32 @@ function match(targetDomains: string | string[], inDomains: string[]) { return true; } +function isIpv4(d: string) { + if (!d) { + return false; + } + const isIPv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/; + return isIPv4Regex.test(d); +} + +function isIpv6(d: string) { + if (!d) { + return false; + } + const isIPv6Regex = /^([\da-f]{1,4}:){2,7}[\da-f]{1,4}$/i; + return isIPv6Regex.test(d); +} + +function isIp(d: string) { + if (!d) { + return false; + } + return isIpv4(d) || isIpv6(d); +} + export const domainUtils = { match, + isIpv4, + isIpv6, + isIp, }; diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts index 74322522d..3b7effb8a 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts @@ -364,15 +364,13 @@ export class AcmeService { //兼容老版本 createCsr = acme.forge.createCsr; } - const [key, csr] = await createCsr( - { - commonName, - ...csrInfo, - altNames, - // emailAddress: email, - }, - privateKey - ); + const csrData: any = { + // commonName, + ...csrInfo, + altNames, + // emailAddress: email, + }; + const [key, csr] = await createCsr(csrData, privateKey); if (dnsProvider == null && domainsVerifyPlan == null) { throw new Error("dnsProvider 、 domainsVerifyPlan不能都为空"); @@ -417,7 +415,7 @@ export class AcmeService { } buildCommonNameByDomains(domains: string | string[]): { - commonName: string; + commonName?: string; altNames: string[] | undefined; } { if (typeof domains === "string") { @@ -426,14 +424,14 @@ export class AcmeService { if (domains.length === 0) { throw new Error("domain can not be empty"); } - const commonName = domains[0]; - let altNames: undefined | string[] = undefined; - if (domains.length > 1) { - altNames = _.slice(domains, 1); - } + // const commonName = domains[0]; + // let altNames: undefined | string[] = undefined; + // if (domains.length > 1) { + // altNames = _.slice(domains, 1); + // } return { - commonName, - altNames, + // commonName, + altNames: domains, }; }