使用 Trojan、VLESS+TLS、HTTPS 反向代理等方案时,TLS 证书是必需品。证书过期会导致客户端连接失败、浏览器警告、服务中断。本文覆盖证书从签发到续签的完整生命周期,以及自动化管理方案。
一、证书基础知识
1.1 什么是 TLS 证书
TLS 证书是一份由证书颁发机构(CA)签名的数字文件,证明某个域名确实属于某个服务器。客户端(浏览器、代理客户端)通过验证证书来确认"我连接的服务器是合法的"。
1.2 证书的组成
| 文件 | 用途 | 是否需要保密 |
|---|---|---|
| 私钥(.key) | 服务器端解密 TLS 握手 | 必须保密 |
| 证书(.crt / .pem) | 发送给客户端验证身份 | 公开 |
| 证书链(ca_bundle / fullchain) | 包含中间 CA 证书,客户端用来验证根证书 | 公开 |
1.3 常见证书类型
| 类型 | 验证级别 | 费用 | 签发时间 | 适用场景 |
|---|---|---|---|---|
| Let's Encrypt | 域名验证 (DV) | 免费 | 秒级 | 自建代理、个人网站 |
| ZeroSSL | 域名验证 (DV) | 免费(有限额) | 秒级 | 替代 Let's Encrypt |
| Buypass | 域名验证 (DV) | 免费 | 1-2 天 | 180 天有效期 |
| DigiCert / Sectigo | OV / EV | 付费 | 1-3 天 | 企业网站 |
对代理用户来说,Let's Encrypt 是首选:免费、自动化、被所有主流客户端信任。
二、Certbot:最常用的证书工具
Certbot 是 Let's Encrypt 官方推荐的客户端,支持自动签发、续签和 Web 服务器配置。
2.1 安装 Certbot
# Debian / Ubuntu
apt update
apt install certbot -y
# 如果使用 Nginx
apt install python3-certbot-nginx -y
# 如果使用 Apache
apt install python3-certbot-apache -y
# 不使用 Web 服务器( standalone 模式)
# 无需额外插件
2.2 签发证书
方式一:Standalone 模式(独立运行)
Certbot 临时启动一个 Web 服务器完成 ACME 验证。适合不使用 Nginx/Apache 的场景(如纯代理服务器):
# 先停止占用 80 端口的服务
systemctl stop nginx # 如有
# 签发证书
certbot certonly --standalone -d 你的域名.com
# 过程中会提示输入邮箱(用于续签提醒)和同意服务条款
方式二:Webroot 模式(通过现有 Web 服务器)
如果 Nginx 已经在运行,用 webroot 模式不需要停止服务:
# 确保 Nginx 配置中有这个 location 块
# location /.well-known/acme-challenge/ { root /var/www/certbot; }
certbot certonly --webroot -w /var/www/certbot -d 你的域名.com
方式三:DNS 验证(适合没有 Web 服务器的场景)
通过添加 DNS TXT 记录完成验证,不需要开放 80 端口:
# Cloudflare DNS 验证示例
certbot certonly --manual --preferred-challenges dns \
-d 你的域名.com \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini
2.3 证书文件位置
Certbot 签发的证书默认保存在:
/etc/letsencrypt/live/你的域名.com/
├── fullchain.pem # 证书 + 中间证书(完整链)
├── chain.pem # 仅中间证书
├── cert.pem # 仅证书
└── privkey.pem # 私钥
代理程序通常需要 fullchain.pem 和 privkey.pem 两个文件。
三、acme.sh:更灵活的替代方案
acme.sh 是一个纯 Shell 脚本实现的 ACME 客户端,不依赖 Python 或其他运行时,支持更多 DNS 服务商和验证方式。
3.1 安装
curl https://get.acme.sh | sh -s email=你的邮箱@example.com
3.2 签发证书
Webroot 模式:
acme.sh --issue -d 你的域名.com --webroot /var/www/certbot
DNS API 模式(Cloudflare):
# 设置 Cloudflare API 凭据
export CF_Token="你的API_Token"
export CF_Zone_ID="你的Zone_ID"
# 签发
acme.sh --issue -d 你的域名.com --dns dns_cf
DNS API 模式(阿里云):
# 设置阿里云 API 凭据
export Ali_Key="你的AccessKeyId"
export Ali_Secret="你的AccessKeySecret"
# 签发
acme.sh --issue -d 你的域名.com --dns dns_ali
3.3 安装证书到指定路径
acme.sh 签发后会自动安装到 ~/.acme.sh/,你需要手动安装到代理程序目录:
acme.sh --install-cert -d 你的域名.com \
--key-file /etc/xray/cert/private.key \
--fullchain-file /etc/xray/cert/fullchain.pem \
--reloadcmd "systemctl restart xray"
--reloadcmd 会在证书更新后自动执行,实现续签 + 重载的一条龙。
四、证书续签自动化
Let's Encrypt 证书有效期只有 90 天,必须定期续签。好消息是两个工具都支持自动续签。
4.1 Certbot 自动续签
Certbot 安装后会自动创建 systemd timer 或 cron job:
# 查看自动续签定时器
systemctl list-timers | grep certbot
# 手动测试续签
certbot renew --dry-run
# 如果没有自动任务,手动添加 cron
echo "0 3 * * * certbot renew --quiet --post-hook 'systemctl reload nginx'" | crontab -
4.2 acme.sh 自动续签
acme.sh 安装时会自动添加 cron job,每天检查一次:
# 查看 acme.sh 定时任务
crontab -l | grep acme
# 手动续签测试
acme.sh --renew -d 你的域名.com --force
# 查看已安装的证书列表
acme.sh --list
4.3 续签后重载服务
证书更新后需要重载依赖证书的服务,否则新证书不会生效:
# Nginx
systemctl reload nginx
# Xray
systemctl restart xray
# Sing-box
systemctl restart sing-box
# 通用方式(Certbot post-hook)
certbot renew --quiet --post-hook "systemctl restart xray"
五、证书吊销
当你怀疑私钥泄露、域名不再使用、或需要更换证书时,应该吊销旧证书。
5.1 什么时候需要吊销
- 私钥泄露:服务器被入侵、私钥被意外提交到公共仓库。
- 域名转移:域名不再归你所有。
- 更换 CA:从 Let's Encrypt 迁移到其他 CA。
5.2 吊销命令
# Certbot 吊销
certbot revoke --cert-path /etc/letsencrypt/live/你的域名.com/cert.pem
# acme.sh 吊销
acme.sh --revoke -d 你的域名.com
5.3 吊销后重新签发
# 吊销旧证书后,重新签发
certbot certonly --standalone -d 你的域名.com
# 或 acme.sh
acme.sh --issue -d 你的域名.com --webroot /var/www/certbot
六、多域名与通配符证书
6.1 SAN 证书(多域名)
一张证书可以保护多个域名:
# Certbot — 多域名
certbot certonly --standalone \
-d example.com \
-d www.example.com \
-d api.example.com
# acme.sh — 多域名
acme.sh --issue -d example.com -d www.example.com -d api.example.com \
--webroot /var/www/certbot
6.2 通配符证书
通配符证书 *.example.com 可以保护所有子域名。Let's Encrypt 的通配符证书只支持 DNS 验证:
# acme.sh — 通配符证书(Cloudflare DNS)
acme.sh --issue -d "*.example.com" -d example.com --dns dns_cf
多域名 SAN:所有节点共用一个域名的子域名,一张证书覆盖。
通配符:如果你有多个子域名且不想逐个签发,通配符最省心。
七、证书检查与调试
7.1 查看证书信息
# 查看证书详细信息
openssl x509 -in /etc/letsencrypt/live/你的域名.com/cert.pem -text -noout
# 查看证书有效期
openssl x509 -in /etc/letsencrypt/live/你的域名.com/cert.pem -dates -noout
# 输出示例:
# notBefore=Jul 1 00:00:00 2026 GMT
# notAfter=Sep 29 00:00:00 2026 GMT
7.2 远程检查证书
# 检查远程服务器的证书信息
openssl s_client -connect 你的域名.com:443 -servername 你的域名.com </dev/null 2>/dev/null | openssl x509 -dates -noout
# 或使用 curl
curl -vI https://你的域名.com 2>&1 | grep "expire\|subject\|issuer"
7.3 常见证书问题
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 浏览器提示"证书不可信" | 未包含中间证书 | 使用 fullchain.pem 而非 cert.pem |
| 签发失败:DNS 验证超时 | DNS 传播未完成 | 等待 1-2 分钟后重试,或检查 DNS 设置 |
| 签发失败:80 端口被占用 | 其他服务占用了 80 端口 | 停止占用 80 端口的服务后重试 |
| 续签后证书未生效 | 服务未重载 | systemctl restart nginx/xray |
| 提示"rate limit exceeded" | 同一域名签发次数过多 | 等待一周后重试,或使用 staging 环境测试 |
| 私钥与证书不匹配 | 证书和私钥来自不同签发 | 重新签发,确保使用同一对密钥 |
7.4 使用 Staging 环境测试
Let's Encrypt 有签发频率限制。测试时使用 Staging 环境避免触发限制:
# Certbot Staging(测试用,签发的证书不被信任)
certbot certonly --standalone --staging -d 你的域名.com
# acme.sh Staging
acme.sh --issue -d 你的域名.com --staging --webroot /var/www/certbot
# 确认无误后,去掉 --staging 参数正式签发
八、实战:代理服务器证书配置流程
以 Xray + Trojan 为例,走完从签发到使用的完整流程:
准备域名
将域名 A 记录指向 VPS 的 IP 地址。确保 80 端口可从外网访问(用于 ACME 验证)。
签发证书
使用 Certbot standalone 模式签发,或 acme.sh + DNS API 模式签发。
配置代理程序
将 fullchain.pem 和 privkey.pem 的路径填入 Xray/Sing-box 配置文件的 certFile 和 keyFile 字段。
重启服务
重启代理程序使新证书生效。
验证证书
用客户端连接测试,同时用 openssl s_client 确认证书链完整、有效期正确。
确认自动续签
运行 certbot renew --dry-run 或 acme.sh --renew 确认自动续签流程正常。设置 --reloadcmd 确保续签后自动重载服务。