From a3bc10c68cdb4aea319c523ff33500092ec481b1 Mon Sep 17 00:00:00 2001 From: zqlit Date: Tue, 6 Oct 2026 17:07:29 +0800 Subject: [PATCH] =?UTF-8?q?docs(ssl):=20=E6=96=B9=E6=A1=88=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E8=A1=A5=E5=85=85=E7=AC=AC=E5=85=AB=E7=AB=A0=20?= =?UTF-8?q?=E2=80=94=E2=80=94=20=E7=AD=BE=E5=8F=91/=E7=BB=AD=E6=9C=9F?= =?UTF-8?q?=E8=90=BD=E5=9C=B0=E5=AE=9E=E7=8E=B0=E4=B8=8E=E4=B8=8A=E7=BA=BF?= =?UTF-8?q?=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 记录本轮实测结论:免费版 [limits] 会拒绝部署(code 100328)、 多吉云 bind 参数名 id、1Panel v2 与 SSL 大写字段、LiteSSL /v2 目录、 CSR extensionRequest 三层 SEQ 等易误判的坑;含上线 version_id 与 403-vs-404 路由存在性验证方法。 --- 函数版证书管家-方案.md | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/函数版证书管家-方案.md b/函数版证书管家-方案.md index a5e164f8..9fc90ed2 100644 --- a/函数版证书管家-方案.md +++ b/函数版证书管家-方案.md @@ -384,3 +384,76 @@ KV 键位规划: > 而且额外多了「凭据加密存储」和「多吉云自动部署」。 > 唯一少的是 certimate 的「可视化工作流编排」(拖拽节点那种)—— > 本项目只有 3 个固定工作流,用配置表单比拖拽更直接,不构成损失。 + +--- + +## 八、签发/续期落地实现(2026-10-06 完成并上线) + +### 8.1 模块划分(全部纯 WebCrypto,零 npm 依赖) + +| 文件 | 职责 | 参照 certimate | +|---|---|---| +| `src/lib/acme.ts` | ACME v2 客户端:ES256 JWS、RFC7638 thumbprint、EAB、badNonce 重试、DNS-01、手写 DER 的 CSR | `internal/certacme` | +| `src/lib/dnsprovider.ts` | DNS-01 适配:DNSPod(TC3-HMAC-SHA256)、Cloudflare | `pkg/sdk3rd/*` | +| `src/lib/deployer.ts` | 部署适配:多吉云 CDN、1Panel 站点(幂等换证书) | `deployers/*` | +| `src/lib/certissue.ts` | 编排:探针判天数 → 账户注册/复用 → 签发 → 落库 → 逐目标部署 | `workflow` | + +### 8.2 与 certimate 的关键差异:探针优先 + +certimate 每个 workflow 挂 cron,**每天无条件重跑整条流水线**。 +本项目改为:**先探针查证书剩余天数,低于 `RENEW_BEFORE_DAYS`(30 天)才真正签发**。 +好处:省 CA 限速额度(Let's Encrypt / LiteSSL 都有周限额)、DNS 改动更少、日志只有真实动作才有记录。 + +### 8.3 ★ 免费版跑不了签发(重要结论) + +| 项 | 免费版 | 付费版($5/月) | +|---|---|---| +| Worker CPU | **硬顶 10ms** | 默认 30s,可调至 5min | +| `[limits] cpu_ms` 配置 | ★ **直接拒绝部署**(code 100328) | 支持 | +| ACME 签发 | ❌ 跑不起来 | ✅ | + +实测报错: +``` +X [ERROR] A request to the Cloudflare API (.../workers/scripts/artalk-cf/versions) failed. + CPU limits are not supported for the Free plan. [code: 100328] +``` +注意是**整个部署失败**,不是「忽略该字段」——所以 Free plan 下 `[limits]` 必须保持注释。 +(探针 / 环境自检 / 手动查询这些轻量功能在免费版完全可用。) + +HTTP 请求 duration 本身**无硬限制**,签发的耗时主要花在 `sleep` 等 DNS 传播 + 轮询上, +**不计 CPU**——所以升级 Paid 后,这套架构是成立的。 + +### 8.4 实测踩坑(易误判,勿回退) + +- **多吉云 `bind` 参数是 `{id, domain}`**,不是 `cert_id`。用假 id 999999 做对照实验确认: + `cert_id` 回「域名不存在」(参数被无视)、`id` 回「指定证书不存在」(参数生效)。 +- 多吉云上传私钥字段名是 **`private`**(`pri`/`key`/`privateKey` 均报「私钥格式错误」); + 列域名用 `/cdn/domain/list.json`(`/cdn/domain.json` 回 `400 domain 格式错误`)。 +- **LiteSSL ACME 目录必须带 `/v2`**:`https://acme.trustasia.com/acme/v2/directory` + (少 `/v2` 直接 404);`meta.externalAccountRequired: true` 强制 EAB。 +- **1Panel 必须用 `/api/v2/`**。v1 的表现极具欺骗性:**HTTP 200 但正文是 HTML 停用页** + (`Access Temporarily Unavailable`)——看似限流,实为 v1 已停用。 +- **1Panel HTTPS 配置字段是 `SSL`(大写)**,写错不报错,只是 `cur?.ssl?.id === sslId` 永假 + → **每次续期都重绑、短暂 reload nginx**。 +- **CSR 的 `extensionRequest` 只能套三层 SEQ**:`a0 / 30 / 06 09…090e / 31 …` + 多套一层会让 OpenSSL 拿 SAN 的 OID 当 attribute type 查表,报 + `wrong tag ... Field=object, Type=X509_ATTRIBUTE`(这个 bug 会让所有签发失败)。 + +### 8.5 上线记录 + +- Worker version_id `1899e229-ca59-486a-a758-a6e2cbec0919`,路由 `api.200181.xyz` +- cron 三条:`17 3 * * *`(评论 GC)、`0 * * * *`(RSS)、`10 4 * * *`(**证书续期**) +- KV 已写入 8 条:7 条凭据(AES-GCM)+ 1 条 `certkeeper:config`(3 组域名、阈值 30 天、收件人) +- 新路由已注册上线的**铁证**:`GET /api/v2/ssl/renew-check` → **403**(鉴权拦截), + 而瞎编路径 `/api/v2/ssl/__nope` → **404**。403 vs 404 是最干净的「路由存在性」证明。 + +### 8.6 待办 + +- **1Panel API 白名单**:代码侧已按官方 SDK 写好,但线上调用被「Access Temporarily Unavailable」拦。 + 1Panel 开了「安全登录」(入口 `/project`),需在 **面板 → 设置 → API 接口**确认已启用, + 并把 Cloudflare Worker 出口 IP 加入白名单,否则 1panel 部署目标会失败。 + (环境自检 `/ssl/selfcheck` 会如实报出这一点。) +- **Cloudflare DNS 凭据缺口**:现 `cloudflare` token 是 Workers/KV/D1 专用, + `GET /zones` 回 200 + 空数组、`dns_records` 直连 403 → **`200181.xyz` 无法走 DNS-01**。 + 需到 Cloudflare 重新生成含 `Zone → DNS → Edit` 且覆盖 `200181.xyz` 的 token。 +- **真实端到端签发验证**(需 Paid plan + 用户批准):会真写 DNS TXT、消耗一次 CA 配额、重绑站点。