生成TLS证书和密钥
TLS(传输层安全)是实现安全通信的常用协议。获取证书通常有两条路径:用 OpenSSL 自建 CA 签发证书(适用于内网、服务间 mTLS、开发测试),用 Certbot 申请 Let's Encrypt 免费证书(适用于公网站点)。本文记录两者的关键步骤与易踩的坑。
OpenSSL 自建 CA
自建 CA 的本质:先造一个根证书(CA),再用它为服务器/客户端签发证书,从而建立一条可验证的信任链。仅在你能掌控双方信任关系的场景下使用(内网、mTLS、测试);面向公网请直接用下文的 Certbot。
生成 CA 证书和密钥
CA(Certificate Authority)是信任链的根,服务器与客户端都信任它。
# 生成 CA 私钥(RSA 默认 2048 位,可用 -pkeyopt rsa_keygen_bits:4096 加强)
openssl genpkey -algorithm RSA -out ca-key.pem
# 生成自签名 CA 证书(根证书有效期可设长一些)
openssl req -x509 -new -nodes -key ca-key.pem -sha256 -days 3650 \
-out ca-cert.pem -subj "/C=US/ST=State/L=City/O=Organization/OU=Unit/CN=My Root CA"
ca-cert.pem 是根证书(需分发给客户端导入信任),ca-key.pem 是签署其他证书的私钥(务必妥善保管)。
:::tip 为什么用 .pem 后缀?
.pem(Privacy Enhanced Mail)是一种 Base64 编码、带 -----BEGIN/END----- 头尾标识的文本格式。它可读、兼容性好、且能统一存储证书、私钥、公钥和证书链,因此被广泛采用。
:::
生成服务器证书和密钥
服务器证书证明服务器身份,私钥用于密钥协商与加密。关键点:必须填写 SAN(Subject Alternative Name)。 现代浏览器、Go 等客户端已不再读取 CN 字段做主机名校验,缺少 SAN 的证书会直接被拒(如 x509: certificate relies on legacy Common Name field)。
# 1. 生成服务器私钥
openssl genpkey -algorithm RSA -out server-key.pem
# 2. 生成证书签名请求(CSR)
openssl req -new -key server-key.pem -out server.csr -subj "/CN=server.amass.fun"
# 3. 准备 SAN 扩展文件(域名、泛域名、IP 均可按需填写)
cat > server-ext.cnf <<'EOF'
subjectAltName = DNS:server.amass.fun, DNS:*.amass.fun, IP:192.168.1.10
EOF
# 4. 用 CA 签发,并通过 -extfile 注入 SAN
openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial \
-out server-cert.pem -days 365 -sha256 -extfile server-ext.cnf
CSR 由 server-key.pem 生成,再由 CA 签署得到 server-cert.pem,从而保证该证书出自可信 CA。
生成客户端证书和密钥
需要双向认证(mTLS)时,为客户端签发证书。流程与服务器完全一致——本质都是「让 CA 为自己的公钥背书」:
openssl genpkey -algorithm RSA -out client-key.pem
openssl req -new -key client-key.pem -out client.csr -subj "/CN=client.amass.fun"
openssl x509 -req -in client.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial \
-out client-cert.pem -days 365 -sha256
客户端证书一般用于身份认证而非主机名校验,可不带 SAN。
合并证书和私钥
部分服务(如某些负载均衡、邮件服务)要求证书与私钥放在同一文件:
cat server-cert.pem server-key.pem > server-cert-key.pem
# 验证合并结果(能输出证书详情即成功)
openssl x509 -in server-cert-key.pem -text -noout
合并文件包含私钥,须严格控制权限(如
chmod 600),仅在必要环境使用,避免泄露。
小结:信任链
- 信任链:CA 是根,服务器/客户端证书由 CA 签署,双方据此验证对方身份。
- 加密与认证:私钥参与密钥协商,证书用于身份验证,共同保证保密性与完整性。
- 双向认证(可选):启用客户端证书后,服务器与客户端互验,进一步提升安全性。
Certbot(Let's Encrypt)
Certbot 是 Let's Encrypt 官方客户端,可自动签发并续期免费证书,适合公网自建站点。
snap install --classic certbot
申请证书
standalone 模式会自行监听端口完成域名所有权验证(初次签发占用 80 端口),因此需先停掉占用该端口的 Web 服务:
certbot certonly --standalone -d unraid.amass.fun
可用多个
-d把多个域名签进同一份证书;为便于管理,建议一域一证。需要泛域名(*.amass.fun)时 standalone 无法满足,须改用 DNS-01 验证(--manual --preferred-challenges dns或对应 DNS 插件)。
证书生成在 /etc/letsencrypt/live/<域名>/ 下,Nginx 引用 fullchain.pem 与 privkey.pem:
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/unraid.amass.fun/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/unraid.amass.fun/privkey.pem;
}
自动续期
snap 安装的 Certbot 已自带 systemd timer / cron 自动续期,一般无需手写定时任务。若服务(如 OpenResty)需要在续期前后停启端口,推荐用 --deploy-hook(仅在证书真正更新时触发,避免每次都重启):
certbot renew --pre-hook "openresty -p /root/Server -s quit" \
--deploy-hook "openresty -p /root/Server"
如需自定义周期,再用 crontab -e 添加,例如每两个月的 04:35 续期一次:
35 4 * */2 * certbot renew --pre-hook "openresty -p /root/Server -s quit" --post-hook "openresty -p /root/Server"
证书吊销检查:CRL 与 OCSP
CRL(证书吊销列表)和 OCSP(在线证书状态协议)用于判断证书是否已被吊销。
- CRL:CA 周期性发布的吊销名单,客户端下载后比对。覆盖全面,但列表可能很大、有更新延迟。
- OCSP:客户端就单张证书向 OCSP 服务器实时查询状态,更轻量,但依赖服务器可用性,并可能泄露访问行为。
趋势提醒:出于隐私与运维成本考虑,Let's Encrypt 已逐步停止 OCSP 服务、转向 CRL。具体最新状态以官方公告为准。
开发测试环境可禁用吊销检查以简化配置;生产环境应启用,以确保证书仍然可信。