本文详解如何使用Let’s Encrypt获取免费SSL证书,配置Nginx/Apache实现HTTPS,以及自动续期方案。
前言
2024年了,网站还不上HTTPS?
- 浏览器会标记为"不安全"
- SEO排名受影响
- 无法使用HTTP/2、HTTP/3
- 用户数据传输有风险
以前SSL证书很贵,现在有了Let’s Encrypt,完全免费,自动续期,没有理由不用。
一、Let’s Encrypt简介
1.1 什么是Let’s Encrypt
Let’s Encrypt是一个免费、自动化、开放的证书颁发机构(CA),由非营利组织ISRG运营。
特点:
- 完全免费
- 自动化颁发和续期
- 被所有主流浏览器信任
- 单域名/泛域名都支持
1.2 证书类型
| 类型 | 说明 | 验证方式 |
|---|---|---|
| 单域名 | 只对一个域名有效 | HTTP/DNS |
| 多域名(SAN) | 多个域名共用一个证书 | HTTP/DNS |
| 泛域名 | *.example.com | 仅DNS |
1.3 验证方式
HTTP-01验证:
- 在网站目录放置特定文件
- Let’s Encrypt访问验证
- 需要80端口可访问
DNS-01验证:
- 添加特定的DNS TXT记录
- Let’s Encrypt查询验证
- 适合泛域名、无法开放80端口的场景
二、Certbot安装与使用
2.1 安装Certbot
# Ubuntu/Debianaptupdateaptinstallcertbot# CentOS/RHELyuminstallepel-release yuminstallcertbot# 或使用snap(推荐,版本更新)snapinstall--classic certbotln-s /snap/bin/certbot /usr/bin/certbot2.2 获取证书(HTTP验证)
独立模式(没有Web服务器时):
# 需要80端口空闲certbot certonly --standalone -d example.com -d www.example.comWebroot模式(已有Web服务器):
# 指定网站根目录certbot certonly --webroot -w /var/www/html -d example.com -d www.example.comNginx插件模式(自动配置):
# 安装插件aptinstallpython3-certbot-nginx# 自动获取证书并配置Nginxcertbot --nginx -d example.com -d www.example.com2.3 获取证书(DNS验证)
# 泛域名证书certbot certonly --manual --preferred-challenges dns -d"*.example.com"-d example.com执行后会提示添加DNS TXT记录:
Please deploy a DNS TXT record under the name: _acme-challenge.example.com with the following value: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx添加记录后等待DNS生效,然后继续。
2.4 证书文件说明
证书存放在/etc/letsencrypt/live/example.com/:
| 文件 | 说明 | 用途 |
|---|---|---|
| cert.pem | 域名证书 | - |
| chain.pem | 中间证书链 | - |
| fullchain.pem | 完整证书链 | Nginx ssl_certificate |
| privkey.pem | 私钥 | Nginx ssl_certificate_key |
三、Nginx HTTPS配置
3.1 基础配置
server { listen 80; server_name example.com www.example.com; # HTTP重定向到HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name example.com www.example.com; # SSL证书 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # SSL配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; # HSTS(可选,强制HTTPS) add_header Strict-Transport-Security "max-age=31536000" always; root /var/www/html; index index.html; location / { try_files $uri $uri/ =404; } }3.2 安全加固配置
# /etc/nginx/conf.d/ssl.conf # SSL会话缓存 ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; ssl_session_tickets off; # 现代加密套件 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; ssl_prefer_server_ciphers off; # OCSP Stapling ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; # DH参数(可选,增强安全性) # openssl dhparam -out /etc/nginx/dhparam.pem 2048 # ssl_dhparam /etc/nginx/dhparam.pem;3.3 测试配置
# 测试Nginx配置nginx -t# 重载配置nginx -s reload# 测试SSLcurl-I https://example.com四、自动续期配置
4.1 证书有效期
Let’s Encrypt证书有效期是90天,建议提前30天续期。
4.2 手动续期
# 续期所有证书certbot renew# 测试续期(不真正执行)certbot renew --dry-run4.3 自动续期
方法1:Cron定时任务
# crontab -e03* * * certbot renew --quiet --post-hook"nginx -s reload"方法2:Systemd Timer(推荐)
Certbot安装后通常自带timer:
# 查看timer状态systemctl status certbot.timer# 启用timersystemctlenablecertbot.timer systemctl start certbot.timer# 查看下次执行时间systemctl list-timers|grepcertbot4.4 续期钩子
# 续期成功后执行的命令certbot renew --post-hook"systemctl reload nginx"# 或在配置文件中设置# /etc/letsencrypt/renewal/example.com.conf[renewalparams]post_hook=systemctl reload nginx五、内网服务HTTPS
5.1 问题场景
内网服务器没有公网IP和域名,如何配置HTTPS?
5.2 方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 自签名证书 | 简单 | 浏览器警告 |
| 内网CA | 企业级方案 | 配置复杂 |
| 反向代理 | 正规证书 | 需要公网入口 |
| 组网+DNS验证 | 正规证书 | 需要域名 |
5.3 自签名证书(临时方案)
# 生成私钥openssl genrsa -out server.key2048# 生成证书openssl req -new -x509 -key server.key -out server.crt -days365\-subj"/CN=myserver.local"# Nginx配置使用ssl_certificate /path/to/server.crt;ssl_certificate_key /path/to/server.key;5.4 组网访问方案
如果使用组网软件(如星空组网)将内网服务器和客户端连接起来:
- 内网服务器通过组网获得固定的虚拟IP
- 用DNS验证方式获取Let’s Encrypt证书(需要有域名)
- 将域名解析到组网的虚拟IP
- 客户端通过域名+HTTPS访问
这样既有正规证书,又不需要公网暴露服务器。
六、常见问题
6.1 验证失败
Challenge failed for domain example.com排查:
- 确认80端口可访问:
curl http://example.com/.well-known/acme-challenge/test - 检查防火墙
- 检查DNS解析是否正确
6.2 速率限制
Let’s Encrypt有速率限制:
- 每个域名每周50个证书
- 每个IP每小时10个失败验证
解决:等待限制解除,或使用测试环境:
certbot certonly --staging -d example.com6.3 证书续期失败
# 查看续期日志cat/var/log/letsencrypt/letsencrypt.log# 常见原因:# 1. 80端口被占用# 2. 域名DNS变更# 3. 防火墙规则变更七、其他ACME客户端
除了Certbot,还有其他Let’s Encrypt客户端:
| 客户端 | 特点 | 适用场景 |
|---|---|---|
| acme.sh | 纯Shell实现,轻量 | 无Python环境 |
| Caddy | 内置自动HTTPS | 简单场景 |
| Traefik | 云原生网关 | K8s环境 |
7.1 acme.sh示例
# 安装curlhttps://get.acme.sh|sh# 获取证书acme.sh --issue -d example.com -w /var/www/html# 安装证书到Nginxacme.sh --install-cert -d example.com\--key-file /etc/nginx/ssl/example.com.key\--fullchain-file /etc/nginx/ssl/example.com.crt\--reloadcmd"nginx -s reload"八、总结
Let’s Encrypt + HTTPS配置要点:
- 选择验证方式:有80端口用HTTP验证,否则用DNS验证
- 选择客户端:Certbot最通用,acme.sh最轻量
- 配置自动续期:证书90天过期,必须自动续期
- 安全加固:使用TLS1.2+,现代加密套件,开启HSTS
- 内网服务:可以用组网+DNS验证获取正规证书
参考资料
- Let’s Encrypt官方文档:https://letsencrypt.org/docs/
- Certbot文档:https://certbot.eff.org/docs/
- Mozilla SSL Configuration Generator:https://ssl-config.mozilla.org/
💡建议:所有对外服务都应该使用HTTPS,Let’s Encrypt让这件事变得零成本。