使用 Trojan、VLESS+TLS、HTTPS 反向代理等方案时,TLS 证书是必需品。证书过期会导致客户端连接失败、浏览器警告、服务中断。本文覆盖证书从签发到续签的完整生命周期,以及自动化管理方案。

💡 不是所有代理都需要证书
VLESS-Reality 不需要证书(它伪装成其他网站的 TLS 握手)。需要证书的场景包括:Trojan、VLESS+WS+TLS、VLESS+gRPC+TLS、Cloudflare CDN 回源、网站反向代理等。

一、证书基础知识

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 / SectigoOV / 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
💡 代理服务器推荐 Standalone 模式
大多数代理 VPS 不跑 Web 服务器,用 Standalone 模式最简单。签完证书后把文件复制到代理程序的配置目录即可。

2.3 证书文件位置

Certbot 签发的证书默认保存在:

/etc/letsencrypt/live/你的域名.com/
├── fullchain.pem    # 证书 + 中间证书(完整链)
├── chain.pem        # 仅中间证书
├── cert.pem         # 仅证书
└── privkey.pem      # 私钥

代理程序通常需要 fullchain.pemprivkey.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
⚠️ 吊销 ≠ 删除
吊销是通知 CA 这张证书不再可信,删除只是从本地文件系统移除文件。吊销后即使有人拿到你的私钥和证书,客户端也会拒绝信任该证书。

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 为例,走完从签发到使用的完整流程:

1

准备域名

将域名 A 记录指向 VPS 的 IP 地址。确保 80 端口可从外网访问(用于 ACME 验证)。

2

签发证书

使用 Certbot standalone 模式签发,或 acme.sh + DNS API 模式签发。

3

配置代理程序

fullchain.pemprivkey.pem 的路径填入 Xray/Sing-box 配置文件的 certFilekeyFile 字段。

4

重启服务

重启代理程序使新证书生效。

5

验证证书

用客户端连接测试,同时用 openssl s_client 确认证书链完整、有效期正确。

6

确认自动续签

运行 certbot renew --dry-runacme.sh --renew 确认自动续签流程正常。设置 --reloadcmd 确保续签后自动重载服务。