前言

没有 HTTPS 的网站在 2025 年已经"裸奔"得不能再裸奔:浏览器标"不安全"、备案检查、小程序/H5 全要求 HTTPS。这篇把证书到配置的全流程走通。

一、证书从哪来

类型 说明 适合
DV(域名验证) 只验域名所有权,免费渠道多 个人站/中小业务
OV(组织验证) 验证公司身份,收费 企业官网
EV(扩展验证) 严格审核、地址栏显示公司名,贵 金融/大厂
自签 自己签给自己 仅内网测试

免费 DV 证书渠道:

  • Let’s Encrypt(ACME 自动化,90 天有效期,可自动续期)
  • 腾讯云/阿里云免费证书(每年 20 张,一年期)
  • ZeroSSL

二、证书文件的构成

# 典型的一套(Nginx 需要 fullchain + key)
your.crt / your.pem        # 证书(公钥 + 签发信息)
your.key                   # 私钥(!! 绝不外传, 权限 600)
chain.crt / fullchain.crt # 中间证书链(缺它部分客户端报错)

# 查看证书信息(到期时间/域名/签发者)
openssl x509 -in fullchain.crt -noout -dates -subject -issuer
# notAfter=Jan  1 12:00:00 2026 GMT   ← 到期时间
openssl x509 -in fullchain.crt -noout -ext subjectAltName

到期监控(配合 cron 篇的知识):

echo | openssl s_client -serverName antidebug.cn -connect antidebug.cn:443 2>/dev/null \
  | openssl x509 -noout -enddate

三、Let’s Encrypt 自动化(certbot)

dnf install -y certbot python3-certbot-nginx

# 一条命令: 验证域名 + 改 Nginx 配置 + 自动续期定时器
certbot --nginx -d antidebug.cn -d www.antidebug.cn

# 续期(90天证书, certbot 自动装了 systemd timer)
systemctl list-timers | grep certbot
certbot renew --dry-run        # 演练续期

前提:域名已解析到本机、80 端口可访问(HTTP-01 验证要走它)。

四、Nginx HTTPS 配置模板

# ---- HTTP: 全部跳转 HTTPS ----
server {
    listen 80;
    server_name antidebug.cn www.antidebug.cn;
    return 301 https://antidebug.cn$request_uri;
}

# ---- HTTPS 主站 ----
server {
    listen 443 ssl;
    http2 on;                                  # HTTP/2(多路复用, 提速明显)
    server_name antidebug.cn www.antidebug.cn;

    # ---- 证书 ----
    ssl_certificate     /etc/nginx/certs/antidebug.cn/fullchain.crt;
    ssl_certificate_key /etc/nginx/certs/antidebug.cn/private.key;

    # ---- 协议与加密套件 ----
    ssl_protocols TLSv1.2 TLSv1.3;             # 1.0/1.1 已淘汰
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    # ---- 会话复用(减少握手开销)----
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # ---- 安全头 ----
    add_header Strict-Transport-Security "max-age=31536000" always;
    # 强制浏览器后续一律走 HTTPS(HSTS)

    # ---- OCSP Stapling(客户端不用去问 CA, 加快握手)----
    ssl_stapling on;
    ssl_stapling_verify on;

    root /var/www/blog;
    index index.html;
    location / { try_files $uri $uri/ =404; }

    # TLS 1.3 0-RTT 会重放, 写操作要小心——一般保持默认即可
}
nginx -t && systemctl reload nginx
curl -I https://antidebug.cn/              # 200 ✅

五、验证与评分

# 命令行验证
openssl s_client -connect antidebug.cn:443 -servername antidebug.cn </dev/null 2>/dev/null \
  | openssl x509 -noout -dates -subject

# 协议与套件检查
nmap --script ssl-enum-ciphers -p 443 antidebug.cn

# 在线评分
# SSL Labs: https://www.ssllabs.com/ssltest/  目标 A/A+
# 我的模板实测 A

常见扣分项:

问题 修复
支持 TLS 1.0/1.1 ssl_protocols 只留 1.2/1.3
弱套件(CBC/3DES) 用上面的 ECDHE 套件
无 HSTS add_header Strict-Transport-Security
链不完整 用 fullchain(带中间证书)

六、自签证书(内网/测试)

# 一行生成自签证书(SAN 必须写对, 新浏览器不认 CN)
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
  -keyout self.key -out self.crt \
  -subj "/CN=lab.local" \
  -addext "subjectAltName=DNS:lab.local,DNS:*.lab.local,IP:10.0.0.5"

# Nginx 配置同上; 客户端 curl -k 忽略验证
# 内网正规做法: 自建 CA 签发 + 分发 CA 证书到信任库

七、实战坑列表

现象 原因
浏览器警告"链不完整" 只配了 crt 没配 fullchain
curl 报 certificate verify failed 系统缺中间证书/CA;update-ca-trust
部分安卓老设备握手失败 TLS 版本太新/套件不兼容,酌情放宽
续期了还是旧证书 certbot renew 后没 reload nginx → 加 --deploy-hook "systemctl reload nginx"
443 不通 安全组/防火墙没放行
http2 on 报错 老 nginx 用 listen 443 ssl http2; 旧语法
mixed content 页面里还引用 http:// 资源,全改 https 或用相对协议

八、性能小结

手段 收益
会话缓存/复用 回访用户省一次完整握手
TLS 1.3 握手 1-RTT(0-RTT 可选)
OCSP stapling 客户端少一次查询
HTTP/2 多路复用,页面并发资源加载提速
HTTP/3 (QUIC) 弱网体验更佳(listen 443 quic; 新版本可试)

小结

  • 免费 DV 证书 + certbot 自动续期 = 零成本 HTTPS
  • 模板要点:fullchain、TLS1.2/1.3、HSTS、会话复用、HTTP/2
  • 上线三验证:openssl s_client、nmap ssl-enum、SSL Labs 评分
  • 续期别忘了 deploy-hook reload

本文是「Linux 运维」系列第 12 篇。