Let's Encrypt SSL 证书配置完全指南
在当今互联网环境下,HTTPS 已不再是可选项,而是每个网站的标配。Let’s Encrypt 作为免费、自动化、开放的证书颁发机构(CA),让每个站长都能轻松为自己的站点部署 SSL/TLS 证书。本文将详细介绍如何在 Linux 服务器上使用 Let’s Encrypt 配置 SSL 证书。
SSL/TLS 基础概念
什么是 SSL/TLS
SSL(Secure Sockets Layer)及其后继协议 TLS(Transport Layer Security)是互联网上最广泛使用的加密协议。其核心作用包括:
- 加密通信:防止数据在传输过程中被窃听
- 身份验证:确认服务器身份,防止中间人攻击
- 数据完整性:确保数据在传输中未被篡改
证书链结构
一个完整的 SSL 证书链通常包含三级:
- 根证书(Root CA):由受信任的根证书机构签发,内置在操作系统和浏览器中
- 中间证书(Intermediate CA):由根证书签发,用于签发终端证书,起到隔离保护作用
- 终端证书(Leaf Certificate):即我们实际安装在服务器上的证书,绑定到具体域名
Let’s Encrypt 的证书链为:ISRG Root X1 → R3 → 你的域名证书。
Let’s Encrypt 与 ACME 协议
Let’s Encrypt 使用 ACME(Automatic Certificate Management Environment) 协议来自动化证书的申请、续期和撤销流程。
工作流程
1 2 3 4 5 6 7 8 9 10
| sequenceDiagram participant C as Certbot (客户端) participant L as Let's Encrypt (CA) C->>L: 1. 注册账户 C->>L: 2. 提交证书申请 L->>C: 3. 下发挑战(Challenge) C->>C: 4. 完成挑战(HTTP/DNS) L->>C: 5. 验证挑战 L->>C: 6. 签发证书 C->>C: 7. 安装证书到服务器
|
域名验证方式
Let’s Encrypt 提供两种主要的域名验证方式:
| 验证方式 |
描述 |
适用场景 |
优点 |
缺点 |
| HTTP-01 |
在 http://domain/.well-known/acme-challenge/ 放置令牌文件 |
有 Web 服务器运行 |
配置简单,无需 DNS 操作 |
需要 80 端口可访问 |
| DNS-01 |
在域名的 TXT 记录中放置令牌 |
泛域名证书、无 Web 服务器 |
支持泛域名,无需开放 80 端口 |
需要 DNS API 或手动操作 |
| 验证方式 | 描述 | 适用场景 | 优点 | 缺点 |
| HTTP-01 | 在 http://domain/.well-known/acme-challenge/ 放置令牌文件 | 有 Web 服务器运行 | 配置简单,无需 DNS 操作 | 需要 80 端口可访问 |
| DNS-01 | 在域名的 TXT 记录中放置令牌 | 泛域名证书、无 Web 服务器 | 支持泛域名,无需开放 80 端口 | 需要 DNS API 或手动操作 |
Certbot 安装
Certbot 是 Let’s Encrypt 官方推荐的 ACME 客户端,由 EFF(电子前哨基金会)维护。
Ubuntu/Debian
1 2 3 4 5 6 7 8 9 10 11
| sudo apt update sudo apt install snapd sudo snap install core sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
|
CentOS/RHEL
1 2 3 4 5 6 7 8 9 10 11 12
| sudo yum install epel-release
sudo yum install certbot python3-certbot-nginx
sudo yum install snapd sudo systemctl enable --now snapd.socket sudo ln -s /var/lib/snapd/snap /snap sudo snap install --classic certbot sudo ln -s /snap/bin/certbot /usr/bin/certbot
|
验证安装
获取 SSL 证书
方式一:Webroot 模式(推荐)
Webroot 模式不需要停止 Web 服务器,通过在网站根目录下创建验证文件来完成验证,是最常用的方式。
1 2 3 4 5 6 7
| sudo certbot certonly --webroot \ -w /var/www/example.com \ -d example.com \ -d www.example.com \ --email admin@example.com \ --agree-tos \ --non-interactive
|
参数说明:
| 参数 |
含义 |
certonly |
只获取证书,不自动安装 |
--webroot |
使用 Webroot 验证方式 |
-w |
指定网站根目录 |
-d |
指定域名,可重复使用 |
--agree-tos |
同意 Let’s Encrypt 服务条款 |
--non-interactive |
非交互模式,适合脚本 |
方式二:Nginx 插件模式
如果 Nginx 已正常运行,可以使用 Nginx 插件自动配置 SSL:
1 2 3 4 5 6
| sudo certbot --nginx \ -d example.com \ -d www.example.com \ --email admin@example.com \ --agree-tos \ --non-interactive
|
Certbot 会自动修改 Nginx 配置文件,添加 SSL 相关指令。
方式三:Standalone 模式
当需要临时停止 Web 服务器时使用,Certbot 会启动自己的 80 端口服务来完成验证:
1 2 3 4 5 6 7 8 9 10 11
| sudo systemctl stop nginx
sudo certbot certonly --standalone \ -d example.com \ --email admin@example.com \ --agree-tos
sudo systemctl start nginx
|
方式四:DNS-01 模式(泛域名证书)
申请 *.example.com 泛域名证书:
1 2 3 4 5 6 7
| sudo certbot certonly --manual \ --preferred-challenges dns \ -d example.com \ -d "*.example.com" \ --email admin@example.com \ --agree-tos
|
手动模式下,Certbot 会提示你在 DNS 中添加 TXT 记录。也可以使用 DNS 插件实现自动化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| sudo snap install certbot-dns-cloudflare
mkdir -p ~/.secrets/certbot cat > ~/.secrets/certbot/cloudflare.ini << 'EOF' dns_cloudflare_api_token = your_cloudflare_api_token_here EOF chmod 600 ~/.secrets/certbot/cloudflare.ini
sudo certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \ -d example.com \ -d "*.example.com" \ --email admin@example.com \ --agree-tos
|
证书文件说明
申请成功后,证书文件位于 /etc/letsencrypt/live/example.com/ 目录:
1
| ls -la /etc/letsencrypt/live/example.com/
|
1 2 3 4
| cert.pem → 终端证书(服务器证书) chain.pem → 中间证书链 fullchain.pem → 完整证书链(cert.pem + chain.pem,最常用) privkey.pem → 私钥文件(请妥善保管!)
|
安全提示:privkey.pem 是私钥文件,永远不要泄露或提交到版本控制系统中。只有 Web 服务器需要读取它。
Nginx SSL 配置
基础 SSL 配置
1 2 3 4 5 6 7 8 9 10 11 12
| server { listen 443 ssl http2; server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/example.com; index index.html; }
|
安全强化配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| server { listen 443 ssl http2; server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 1.1.1.1 valid=300s; resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; }
|
强制 HTTPS 重定向
1 2 3 4 5
| server { listen 80; server_name example.com www.example.com; return 301 https://$server_name$request_uri; }
|
证书自动续期
Let’s Encrypt 证书有效期为 90 天,建议设置自动续期任务。
测试续期
1 2
| sudo certbot renew --dry-run
|
设置 crontab
添加以下内容:
1 2
| # 每天执行两次续期检查,证书过期前 30 天才会实际续期 0 3,15 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
|
参数说明:
| 参数 |
含义 |
--quiet |
静默模式,仅在出错时输出 |
--post-hook |
续期成功后执行的命令(重载 Nginx 加载新证书) |
--deploy-hook |
仅在部署新证书后执行(比 post-hook 更精确) |
使用 systemd timer(替代 crontab)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| sudo cat > /etc/systemd/system/certbot-renew.service << 'EOF' [Unit] Description=Certbot Renewal
[Service] Type=oneshot ExecStart=/usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx" EOF
sudo cat > /etc/systemd/system/certbot-renew.timer << 'EOF' [Unit] Description=Run certbot renewal twice daily
[Timer] OnCalendar=*-*-* 03:00:00 OnCalendar=*-*-* 15:00:00 RandomizedDelaySec=300 Persistent=true
[Install] WantedBy=timers.target EOF
sudo systemctl daemon-reload sudo systemctl enable --now certbot-renew.timer
sudo systemctl status certbot-renew.timer
|
生成 DH 参数(可选但推荐)
DH(Diffie-Hellman)参数用于提升前向安全性:
1 2 3 4 5
| sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
|
生成后在 Nginx 中引用:ssl_dhparam /etc/ssl/certs/dhparam.pem;
安全评分优化
测试 SSL 配置
1 2 3 4 5
| curl https://example.com -vI
openssl s_client -connect example.com:443 -servername example.com
|
在线测试
推荐使用以下在线工具测试 SSL 配置:
- SSL Labs(ssllabs.com/ssltest)— 业界标准的 SSL 配置评分工具
- SSL Checker(sslchecker.com)— 快速检查证书安装是否正确
- securityheaders.com — 检查安全响应头配置
获取 A+ 评分的检查清单
多域名证书
SAN 证书(Subject Alternative Name)
一张证书同时保护多个域名:
1 2 3 4 5 6
| sudo certbot certonly --webroot \ -w /var/www/example.com -d example.com -d www.example.com \ -w /var/www/app -d app.example.com \ -w /var/www/api -d api.example.com \ --email admin@example.com \ --agree-tos
|
同一服务器多张证书
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| server { listen 443 ssl http2; server_name example.com www.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; root /var/www/example; }
server { listen 443 ssl http2; server_name another-example.com; ssl_certificate /etc/letsencrypt/live/another-example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/another-example.com/privkey.pem; root /var/www/another; }
|
常见问题与排错
证书申请失败
1 2 3 4 5 6 7 8 9 10 11
| sudo certbot --debug certificates
sudo ufw status verbose
sudo systemctl status firewalld
nslookup example.com dig example.com
|
证书即将过期
1 2 3 4 5 6 7 8
| sudo certbot certificates
sudo certbot renew
sudo certbot renew --force-renewal
|
证书撤销
如果需要更换私钥或域名不再使用:
1 2 3 4 5
| sudo certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem
sudo certbot delete --cert-name example.com
|
常见错误对照表
| 错误信息 | 原因 | 解决方案 |
Connection refused | 80 端口未开放或被占用 | 检查防火墙规则,确保无其他进程占用 80 端口 |
Invalid response | 验证文件无法通过 HTTP 访问 | 检查 Web 服务器是否正常运行,路径是否正确 |
Rate limit exceeded | 超过 Let's Encrypt 频率限制 | 同一域名每周最多 50 张证书,等待限制解除 |
No valid DNS | 域名 DNS 解析不正确 | 确认域名 A 记录指向正确 IP |
Failed to connect | CA 服务器无法访问 | 检查服务器网络连接和 DNS 解析 |
频率限制
Let’s Encrypt 有以下速率限制:
- 每注册域名每周最多 50 张证书
- 每张证书最多包含 100 个域名
- 重复验证失败 5 次后将锁定 1 小时
- 证书重复颁发限定每周 5 张(重复的证书申请)
如需查看当前配额,可以访问:https://letsencrypt.org/docs/rate-limits/
完整部署示例
以下是一个完整的自动化部署脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #!/bin/bash
DOMAIN="$1" EMAIL="admin@${DOMAIN}" WEBROOT="/var/www/${DOMAIN}"
if [ -z "$DOMAIN" ]; then echo "用法: sudo bash $0 <domain>" exit 1 fi
if ! command -v certbot &> /dev/null; then echo "正在安装 Certbot..." sudo snap install --classic certbot sudo ln -sf /snap/bin/certbot /usr/bin/certbot fi
sudo mkdir -p "$WEBROOT" echo "Hello, ${DOMAIN}" | sudo tee "${WEBROOT}/index.html"
sudo cat > /etc/nginx/sites-available/${DOMAIN}.conf << 'NGINX' server { listen 80; server_name _; root /var/www/example; index index.html; } NGINX
sudo sed -i "s|example|${DOMAIN}|g" /etc/nginx/sites-available/${DOMAIN}.conf sudo ln -sf /etc/nginx/sites-available/${DOMAIN}.conf /etc/nginx/sites-enabled/ sudo systemctl reload nginx
sudo certbot certonly --webroot \ -w "$WEBROOT" \ -d "$DOMAIN" \ -d "www.${DOMAIN}" \ --email "$EMAIL" \ --agree-tos \ --non-interactive
if [ $? -eq 0 ]; then echo "✅ 证书申请成功!" else echo "❌ 证书申请失败,请检查日志。" exit 1 fi
if [ ! -f /etc/ssl/certs/dhparam.pem ]; then echo "正在生成 DH 参数..." sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 fi
(crontab -l 2>/dev/null; echo "0 3,15 * * * /usr/bin/certbot renew --quiet --post-hook 'systemctl reload nginx'") | sudo crontab -
echo "✅ SSL 配置完成!" echo "📄 证书路径: /etc/letsencrypt/live/${DOMAIN}/" echo "🔒 每日自动续期已设置"
|
总结
Let’s Encrypt 使得 HTTPS 部署变得前所未有的简单。通过本文的配置,你可以:
- 快速为站点部署免费的 SSL 证书
- 配置安全的 Nginx SSL 参数,获取 A+ 评分
- 设置自动续期,确保证书永不过期
- 通过 OCSP Stapling、HSTS 等特性进一步强化安全性
SSL/TLS 配置不是一次性的工作,需要持续关注安全最佳实践和协议版本更新。定期检查 SSL Labs 评分和证书状态,保持服务器的安全性。
提示:本博客正是使用 Let’s Encrypt + Nginx 部署的 HTTPS,关于 Nginx 反向代理的详细配置,可以参考前文《Nginx 配置与反向代理完全指南》。
本文由AI辅助生成,内容仅供参考