SSL证书独立应用
详情介绍
SSL证书 · 使用说明
面向 ZsAdmin 的 SSL 证书自动续签插件:与社区账户体系打通,前台用户登录后可自助申请 Let's Encrypt 证书,HTTP-01 证书到期自动续签;同时提供在线证书检测、域名监控与告警。后台支持证书签发、域名管理、检测日志与定时巡检。
- 插件标识:
ssl - 当前版本:
1.0.00 - 作者:kuakeba.cn
- 前台入口:
/ssl - 用户控制台:
/ssl/console(需登录社区账户) - 后台入口:后台菜单「SSL证书」,默认
/admin/ssl
一、功能说明
前台(/ssl)
- 自动续签落地页:Hero、关键指标、工作原理、安全说明(CNAME 委派对比全局密钥)、套餐与常见问题。
- 在线证书检测:输入域名后与目标完成真实 TLS 握手,展示签发机构、证书主体、生效/到期时间、剩余天数、TLS 协议、加密套件、证书链、签名算法、序列号与 SAN 覆盖情况。
- CNAME 委派自检:检测
_acme-challenge.域名是否存在 CNAME,并比对配置的委派目标是否一致。 - 域名监控:访客可添加域名(默认每浏览器 2 个),添加后立即检测;列表支持刷新与删除,按剩余天数展示进度条,临期/过期/异常状态高亮。
- 用户控制台(/ssl/console):与 community 插件账户打通,未登录跳转社区登录并回跳。登录后可自助申请证书(HTTP-01 / DNS-01)、查看自动续签状态、下载证书链与私钥、续期或删除证书;支持按验证方式筛选、勾选多张批量下载 ZIP(含 IIS 用
.pfx),并展示证书品牌、加密方式、下次续签与最近续签、备注等健康信息。侧栏提供 API Token,用于调用开放接口。 - 未登录时首页监控按浏览器 Cookie 隔离,访客互不可见;登录后自动认领同一浏览器已添加的监控域名,并按会员 ID 跨设备同步。
说明:自动续签是插件主功能。HTTP-01 证书由定时巡检在到期前 30 天自动续签并替换文件;DNS-01 证书(含通配符)续期时需重新添加 TXT 记录。域名监控与在线检测用于观察现有证书状态,属于辅助能力。证书文件保存在 runtime/ssl/certs/,不对外公开。
后台(/admin/ssl)
- 概览:监控总数、有效/临期/过期/异常数量、今日检测与失败数、近 14 天检测趋势图、即将到期列表、最近检测记录。
- 域名监控:搜索、按证书状态/监控状态筛选、添加、编辑、单条检测、全部检测、启停监控、删除。
- 检测日志:按域名、证书状态、成功/失败筛选;支持清理 30 天前日志或清空日志。
- 证书签发:基于 Let's Encrypt ACME v2 自助签发与续期,支持 HTTP-01 自动验证与 DNS-01 手动验证;可下载完整证书链、叶子证书与私钥。
- 定时巡检:通过带密钥的 URL 触发,自动跳过未到巡检间隔的域名,并对临近到期的 HTTP-01 证书自动续期。
说明:前台负责检测、监控与告警;证书签发与续期在后台「证书签发」完成,证书文件保存在 runtime/ssl/certs/,不对外公开。签发要求服务器能访问 Let's Encrypt ACME 接口,且域名可通过 HTTP-01 或 DNS-01 完成验证。
二、安装
- 将
plugins/ssl目录放入站点plugins目录。 - 后台进入「应用中心 → 插件」,找到「SSL证书」点击安装。
- 安装会自动:
- 创建数据表 ssldomain、sslchecklog、sslcertificate、sslapitoken;
- 注册后台菜单与权限节点;
- 复制静态资源到 public/static/ssl;
- 生成定时巡检密钥(可在插件设置中查看/修改)。
- 安装完成后访问
/ssl查看前台。
环境要求:PHP 8.0+,启用 openssl 与 streamsocketclient;域名解析推荐启用 dnsgetrecord(用于 CNAME 自检)。邮件告警依赖服务器的 mail()。
三、插件设置
后台「应用中心 → 插件 → SSL证书 → 设置」:
| 配置项 | 说明 |
|---|---|
| 启用插件 | 关闭后前台 /ssl 返回 404,定时巡检也不会执行 |
| 站点标题 / 副标题 | 前台品牌名与 Hero 描述 |
| SEO 关键词 / 描述 | 前台页面 meta 信息 |
| 主色调 / 强调色 | 前台 CSS 变量,格式 #RRGGBB |
| 临期阈值(天) | 剩余天数 ≤ 该值标记为「临期」并触发告警,默认 15 |
| 检测超时(秒) | TLS 连接超时,默认 8 |
| 巡检间隔(小时) | 定时巡检时距上次检测超过该时长才重新检测,默认 12 |
| 每访客监控数 | 同一浏览器可添加的域名上限,默认 2 |
| 允许前台添加 | 关闭后仅后台可添加域名 |
| 控制台自助签发 | 关闭后前台控制台仅可查看与下载,签发与续期需管理员在后台完成 |
| 每会员证书上限 | 单个社区会员在前台可持有的证书数量,默认 10(1-100) |
| 检测频率(次/分钟) | 同一 IP 每分钟最多发起的在线检测与 CNAME 自检次数,默认 20(1-120) |
| 展示套餐区块 | 关闭后首页隐藏套餐与价格区块,并移除导航中的「套餐」入口 |
| 展示页脚赞助商 | 关闭后页脚不展示赞助商链接 |
| 开放接口 | 开启后会员可用 API Token 调用 /ssl/api/v1 接口;关闭后接口统一返回提示 |
| CNAME 委派目标 | 用于 _acme-challenge 自检比对,默认 ssl.inurl.link |
| ACME 联系邮箱 | Let's Encrypt 账户邮箱,用于到期提醒,可留空 |
| ACME 环境 | 生产环境签发受信任证书;测试环境仅用于调试(浏览器不信任) |
| HTTP-01 根目录 | 自动写入验证文件的站点根目录,相对项目根或绝对路径,默认 public |
| 自动续期 | 巡检时自动续期即将到期的 HTTP-01 证书 |
| 续期阈值(天) | 剩余天数 ≤ 该值时自动续期,默认 30 |
| 启用告警通知 | 关闭后只更新状态,不发送通知 |
| 告警 Webhook | 状态变为临期/过期/异常时 POST JSON |
| 告警邮箱 | 接收告警的邮箱(依赖 mail()) |
| 定时巡检密钥 | 访问巡检 URL 所需密钥,安装时自动生成 |
| 卸载时清除数据 | 开启后卸载插件将删除该插件的 4 张数据表 |
四、定时巡检
后台概览页可直接复制巡检地址,格式:
https://你的域名/ssl/cron/refresh?key=你的巡检密钥参数:
key:必填,与插件设置中的「定时巡检密钥」一致,否则返回 403。force=1:忽略巡检间隔,立即检测所有启用监控的域名(单次最多 60 个)。
返回示例:
{"code":1,"msg":"巡检完成","data":{"total":10,"checked":10,"failed":0,"notified":1,"renew":{"renewed":0,"failed":0,"skipped":0}}}配置方式(任选其一):
- Linux / 宝塔计划任务:每小时访问一次上述 URL。
```bash
0 curl -s "https://example.com/ssl/cron/refresh?key=密钥" >/dev/null
```
- Windows 计划任务:创建每小时执行的任务。
```
powershell -NoProfile -Command "Invoke-WebRequest -UseBasicParsing 'https://example.com/ssl/cron/refresh?key=密钥'"
```
- 宝塔面板:计划任务 → 访问 URL → 每小时执行。
建议巡检频率与「巡检间隔(小时)」保持一致。证书通常 90 天有效,临期阈值 15 天可保证充足的处理时间。
五、告警通知
当域名状态发生变化且变为「临期 / 已过期 / 检测失败」时触发一次通知;恢复正常后静默重置,避免重复轰炸。
Webhook 请求体示例:
{
"event": "ssl_alert",
"domain": "example.com",
"port": 443,
"status": "expiring",
"status_text": "临期",
"days_left": 12,
"not_after": "2026-12-01 08:00:00",
"issuer": "Let's Encrypt",
"error": "",
"checked_at": "2026-11-09 22:30:00"
}邮件标题格式:【SSL证书告警】example.com · 临期。
六、证书自动签发(Let's Encrypt ACME)
后台「SSL证书 → 证书签发」与前台控制台均支持两种验证方式:
- HTTP-01(自动):插件把验证文件写入
HTTP-01 根目录/.well-known/acme-challenge/,要求域名已解析到本站且 80 端口可访问;验证通过后自动提交 CSR 并下载证书。 - DNS-01(手动):页面会给出
_acme-challenge的 TXT 记录名与值,添加后等待生效(通常 1-10 分钟),点击「验证并签发」。通配符域名(*.example.com)只能使用该方式。
6.1 HTTP-01 具体配置
前置条件
- 域名的 A / AAAA 记录指向本服务器公网 IP(
ping 域名或nslookup 域名确认)。 - 公网可访问 80 端口(不能只放行 443);云服务器安全组、系统防火墙、宝塔/面板防火墙都要放行。
- 该域名的站点根目录就是插件配置中「HTTP-01 根目录」指向的目录。
- 若使用 Cloudflare 等 CDN:验证期间建议关闭代理(DNS only)或确保
/.well-known/未被 WAF、强制 HTTPS、页面规则拦截。
插件设置
后台「插件设置 → HTTP-01 根目录」填写站点真实根目录:
- 相对路径:相对项目根目录,默认
public,最终为项目根/public。 - 绝对路径:Windows 例
D:\wwwroot\example\public,Linux 例/www/wwwroot/example/public。 - 该目录下必须能创建
.well-known/acme-challenge/,且 PHP 运行用户有写权限。
Nginx 配置
server {
listen 80;
server_name example.com;
# 让 CA 直接读取验证文件,不要跳转 HTTPS
location ^~ /.well-known/acme-challenge/ {
root /www/wwwroot/example/public;
default_type text/plain;
try_files $uri =404;
}
# 其余请求再跳转 HTTPS
location / {
return 301 https://$host$request_uri;
}
}注意:如果站点已有 return 301 https://... 或面板「强制 HTTPS」,必须把 /.well-known/acme-challenge/ 的 location 放在跳转规则之前,否则 CA 拿到 301 会验证失败。
Apache 配置
<VirtualHost *:80>
ServerName example.com
DocumentRoot "/www/wwwroot/example/public"
<Directory "/www/wwwroot/example/public/.well-known">
Require all granted
Options -Indexes
</Directory>
</VirtualHost>确认 DocumentRoot 指向 public,且 AllowOverride 允许 .htaccess 生效;若 .htaccess 中有全站 HTTPS 跳转,同样需要排除 .well-known。
权限
- Linux:
chown -R www:www public/.well-known && chmod -R 755 public/.well-known(用户组按实际 PHP-FPM 用户调整)。 - Windows:给
IIS_IUSRS或 PHP 运行账户授予public目录「修改」权限。
验证是否就绪
签发前可手动测试(把 test.txt 放入 public/.well-known/acme-challenge/):
curl -I http://example.com/.well-known/acme-challenge/test.txt
# 期望 200,Content-Type 为 text/plain返回 301/403/404 时先修好站点配置再申请,否则 ACME 会报 Invalid response 或 unauthorized。
说明:HTTP-01 不支持通配符;每个需要证书的子域都必须独立解析到本站并单独签发。
6.2 DNS-01 具体配置
第一步:获取记录
在控制台或后台选择「DNS-01」提交后,页面会显示:
- TXT 记录名:
acme-challenge.example.com(通配符 *.example.com 同样是acme-challenge.example.com) - TXT 记录值:一串 base64url 字符(每次申请/续期都会变化)
第二步:在 DNS 服务商添加记录
| 字段 | 填写内容 |
|---|---|
| 记录类型 | TXT |
| 主机记录 | acme-challenge(部分服务商需填完整 acme-challenge.example.com) |
| 记录值 | 页面显示的 TXT 值,整串复制,不要加引号或空格 |
| TTL | 60 ~ 600 秒(越小生效越快) |
同一名称已有多条 TXT 时,保留原有记录并新增,不要覆盖或删除(多域名/多验证可能同时存在)。
第三步:确认生效
nslookup -type=TXT _acme-challenge.example.com 8.8.8.8
# 或
dig +short TXT _acme-challenge.example.com @1.1.1.1返回内容包含页面上的 TXT 值后再继续;未生效时等待 1-10 分钟(受 TTL 与递归缓存影响)。
第四步:验证签发
回到控制台点击「验证并签发」,CA 会直接查询权威 DNS 校验 TXT。验证通过后自动签发;失败时列表会显示具体原因。
常见失败原因
- TXT 值复制不完整、带引号、带换行;
- 添加到了错误的子域(如给
acme-challenge.www.example.com 而不是acme-challenge.example.com); - 该名称已存在 CNAME,与 TXT 冲突(同一名称不能同时存在 CNAME 与 TXT);
- DNS 尚未同步或本地缓存未过期;
- 使用代理/第三方 DNS 面板未真正保存记录。
通配符说明
*.example.com只能使用 DNS-01,且不覆盖example.com本身;需要两者都在证书里时请分别申请。- DNS-01 证书续期时,点「续期」会生成新的 TXT 值,需要重新添加并验证,无法全自动完成。
关于 CNAME 委派
若把 _acme-challenge.example.com CNAME 到证书平台,则由平台写入 TXT;本插件是手动 DNS-01 模式,不会自动修改你的 DNS,也不依赖该委派。前台「CNAME 自检」仅用于检查委派是否已指向配置的目标。
签发成功后可在列表下载完整证书链(Nginx/Apache 使用)、叶子证书与私钥;文件同时保存在 runtime/ssl/certs/<md5>/,不对外公开。
自动续期:开启后,定时巡检会对剩余天数 ≤ 续期阈值的 HTTP-01 证书自动续期;DNS-01 证书需人工添加 TXT,请在列表点击「续期」重新获取记录值。
注意事项:
- 服务器需能访问
https://acme-v02.api.letsencrypt.org;若请求超时,请在服务器或网络层放行,必要时配置出网代理。 - Windows 下 PHP 未设置
OPENSSL_CONF时,插件会自动查找 PHP 目录的extras/ssl/openssl.cnf。 - Let's Encrypt 有签发频率限制,调试请使用「测试环境」,避免触发生产环境限流。
- 私钥仅保存在
runtime目录,请限制目录权限并做好备份。
七、开放接口(API Token)
控制台右侧「API Token」卡片会自动生成会员专属 Token(ssl_ 前缀),用于脚本调用;点「重置」后旧 Token 立即失效。鉴权方式(二选一):
- 请求头:
X-SSL-Token: ssl_xxx - 查询参数:
?token=ssl_xxx
| 接口 | 方法 | 参数 | 说明 |
|---|---|---|---|
/ssl/api/v1/certs | GET | — | 当前会员的证书列表 |
/ssl/api/v1/cert/issue | POST | domain、challenge(http/dns)、email、remark | 申请签发 |
/ssl/api/v1/cert/verify | POST | id | DNS-01 添加 TXT 后验证签发 |
/ssl/api/v1/cert/renew | POST | id | 续期 |
/ssl/api/v1/cert/download | GET | id + type(fullchain/cert/key/pfx) | 下载单个文件 |
/ssl/api/v1/cert/download | GET | type=zip + ids[] | 批量打包下载 |
示例:
# 列表
curl -H "X-SSL-Token: ssl_xxx" https://example.com/ssl/api/v1/certs
# 申请 HTTP-01 证书
curl -X POST -H "X-SSL-Token: ssl_xxx" \
-d "domain=example.com&challenge=http&email=you@example.com&remark=主站" \
https://example.com/ssl/api/v1/cert/issue
# 下载证书链 / PFX
curl -H "X-SSL-Token: ssl_xxx" -o fullchain.pem \
"https://example.com/ssl/api/v1/cert/download?id=1&type=fullchain"
curl -H "X-SSL-Token: ssl_xxx" -o cert.pfx \
"https://example.com/ssl/api/v1/cert/download?id=1&type=pfx"返回与前台接口一致:{"code":1,"msg":"ok","data":{...}},失败时 code=0 并给出原因;Token 无效返回 401。接口只能操作当前会员自己的证书。
八、套餐与定价(展示文案)
前台「套餐」区块按参考站(ssl.inurl.link)的档位展示,文案与权益已按本插件实际能力对齐:
| 套餐 | 价格 | 有效期 | 域名额度 | 续签方式 | 通知方式 | 支持 |
|---|---|---|---|---|---|---|
| 免费版 | ¥0 | 永久 | 2 | 到期手动续签 | 无 | 社区支持 |
| 个人版 | ¥59 | 1 年 | 10 | 到期自动续签 | 邮件 | 人工客服 |
| 专业版 | ¥199 | 1 年 | 30 | 到期自动续签 | 邮件 + Webhook | 优先人工客服 |
| 企业版 | ¥699 | 1 年 | 100 | 到期自动续签 | 邮件 + Webhook | 专属人工客服 |
说明:
- 以上为展示文案,插件本身不包含支付、订单与额度校验;如需真实售卖,请自行接入支付与授权系统,或由运营方人工开通。
- 所有套餐的证书均由 Let's Encrypt 免费签发,价格对应的是平台托管、续签与告警服务,而非证书本身的费用。
- 自动续签=定时巡检在到期前自动重新签发并替换证书;手动续签=在后台「证书签发」列表点击「续期」。
- 未实现的能力(自动部署到宝塔 / CDN、私钥不变续签等)未写入套餐权益,避免与实际功能不符。
九、安全与限制
- 在线检测仅允许公网域名:先解析 A/AAAA 记录,命中内网或保留地址(如 127.0.0.1、10.x、192.168.x、fc00::/7)直接拒绝,避免被利用探测内网。
- 前台接口带简易频率限制:检测默认 20 次/分钟/IP(可在插件设置「检测频率」调整),添加 10 次/5 分钟/IP,证书申请 5 次/5 分钟/IP。
- 前台自助签发、接口调用与每会员证书额度均可在插件设置中关闭或调整。
- 访客监控使用 32 位随机 Cookie 隔离,不展示邮箱等隐私字段。
- 证书读取关闭了信任校验,仅用于展示信息;过期的自签证书同样可以读取详情,状态会标记为「已过期」。
- CNAME 自检依赖服务器 DNS 解析能力;若服务器无法解析外部 DNS,会显示「未检测到 CNAME」。
- 邮件告警依赖服务器
mail()或本地 MTA,未配置时建议使用 Webhook。
十、目录结构
plugins/ssl/
├── SslPlugin.php # 插件入口:安装、配置、菜单、资源同步
├── plugin.json
├── install.sql # 数据表
├── routes.php # 前台 / 后台 / 巡检路由
├── controller/
│ ├── FrontBase.php # 前台基类(配置、视图、频率限制、访客标识)
│ ├── FrontCert.php # 控制台证书接口(列表 / 签发 / 续期 / ZIP / Token)
│ ├── FrontApi.php # 开放接口(Token 鉴权,/ssl/api/v1)
│ ├── Index.php # 落地页、检测、CNAME、监控接口
│ ├── Cron.php # 定时巡检入口(含自动续期)
│ └── admin/ # 概览、域名、证书签发、日志
├── service/
│ ├── CertChecker.php # TLS 证书读取、CNAME 检测、公网校验
│ ├── AcmeClient.php # ACME v2 协议客户端(JWS、订单、挑战、下载)
│ ├── CertService.php # 签发流程、证书落盘、ZIP/PFX 导出、自动续期
│ ├── SslApiToken.php # 会员 API Token 生成与鉴权
│ ├── DomainService.php # 监控域名、检测记录、统计
│ └── Notify.php # Webhook / 邮件告警
├── view/front/ # 前台布局、落地页与用户控制台
├── view/admin/ # 后台页面
└── static/ # ssl.css / ssl.js十一、常见问题
Q:检测提示「域名解析失败」?
确认域名已正确解析、服务器可访问外部 DNS,且目标已开启 HTTPS。
Q:CNAME 自检一直显示未检测到?
确认记录名为 _acme-challenge.你的域名,类型为 CNAME,值为插件设置中的「CNAME 委派目标」;DNS 生效可能需要几分钟。
Q:前台看不到刚添加的域名?
监控列表按浏览器 Cookie 隔离,清除 Cookie 或更换浏览器后会看不到原列表;可让管理员在后台查看。
Q:定时巡检返回 403?
检查 URL 中的 key 是否与插件设置中的「定时巡检密钥」完全一致,或插件是否已启用。
Q:用户控制台需要注册登录吗?
需要。控制台已与 community 插件账户体系打通:未登录会跳转社区登录页并回跳;登录后按会员 ID 展示证书与监控域名,可跨设备同步。未安装 community 插件时自动降级为浏览器访客模式,仅保留监控功能。
Q:前台签发的证书如何自动续签?
使用 HTTP-01 签发的证书由定时巡检在到期前 30 天自动续签并替换本地文件,全程无需操作;DNS-01 证书(含通配符)续期时必须重新添加 TXT 记录,无法全自动完成。定时巡检仍需配置系统计划任务访问 /ssl/cron/refresh?key=密钥。
十二、更新日志
1.0.00:首个正式版本。包含前台落地页与在线证书检测、CNAME 委派自检、访客/会员域名监控、后台概览/域名管理/检测日志、定时巡检与 Webhook/邮件告警;基于 Let's Encrypt ACME v2 的 HTTP-01 / DNS-01 证书签发与自动续期;与 community 社区账户打通的前台控制台(自助签发、续期、删除、下载);证书健康信息(品牌、加密方式、下次续签、最近续签、备注)与按验证方式筛选;批量下载 ZIP(含 IIS 用.pfx)与单独.pfx导出;会员 API Token 与/ssl/api/v1开放接口(列表 / 签发 / 验证 / 续期 / 下载);新增「控制台自助签发」「每会员证书上限」「检测频率」「展示套餐区块」「展示页脚赞助商」「开放接口」等配置项;补充 HTTP-01 / DNS-01 具体配置说明与前台「验证配置」区块;蓝色科技风主题与图标。
更新记录 (1)
-
v1.0.0
2026-11-10
正式发布
微信客服
QQ官方交流群