现在不上HTTPS,浏览器直接标红"不安全",SEO也受影响。
这篇文章整理了HTTPS配置的完整流程,从证书申请到安全加固,一篇搞定。
| 类型 | 验证方式 | 价格 | 适合场景 |
|---|---|---|---|
| DV | 域名验证 | 免费-几百 | 个人站、小网站 |
| OV | 组织验证 | 几百-几千 | 企业官网 |
| EV | 扩展验证 | 几千-几万 | 金融、电商 |
个人站用DV就够了,企业网站上OV,对安全要求极高的上EV。
| 服务商 | 有效期 | 限制 | 推荐度 |
|---|---|---|---|
| Let’s Encrypt | 90天 | 无 | ⭐⭐⭐⭐⭐ |
| 阿里云免费证书 | 1年 | 每年20个 | ⭐⭐⭐⭐ |
| 腾讯云免费证书 | 1年 | 每年20个 | ⭐⭐⭐⭐ |
用Certbot自动申请,最方便。
# CentOS 7
yum install -y epel-release
yum install -y certbot python2-certbot-nginx
# CentOS 8 / Rocky Linux
dnf install -y epel-release
dnf install -y certbot python3-certbot-nginx
# Ubuntu/Debian
apt update
apt install -y certbot python3-certbot-nginx
# 自动配置Nginx(推荐)
certbot --nginx -d example.com -d www.example.com
# 只申请证书,不修改Nginx配置
certbot certonly --nginx -d example.com
按提示输入邮箱,同意协议即可。
申请成功后,证书在:
/etc/letsencrypt/live/example.com/
├── fullchain.pem # 证书链
├── privkey.pem # 私钥
├── cert.pem # 证书
└── chain.pem # 中间证书
Let’s Encrypt证书90天过期,需要自动续期:
# 测试续期
certbot renew --dry-run
# 添加定时任务
crontab -e
# 每天凌晨2点检查并续期
0 2 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
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_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;
# 网站根目录
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# 检查语法
nginx -t
# 重载配置
systemctl reload nginx
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协议 ==========
# 只启用TLS 1.2和1.3,禁用老旧协议
ssl_protocols TLSv1.2 TLSv1.3;
# ========== 加密套件 ==========
# 优先使用ECDHE密钥交换,禁用弱加密
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会话 ==========
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets 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;
# ========== 安全Headers ==========
# HSTS - 强制HTTPS
add_header Strict-Transport-Security "max-age=63072000" always;
# 防止点击劫持
add_header X-Frame-Options DENY always;
# 防止MIME类型嗅探
add_header X-Content-Type-Options nosniff always;
# XSS防护
add_header X-XSS-Protection "1; mode=block" always;
# ========== 其他配置 ==========
root /var/www/html;
index index.html;
}
# 生成2048位DH参数,需要几分钟
openssl dhparam -out /etc/nginx/dhparam.pem 2048
Nginx配置添加:
ssl_dhparam /etc/nginx/dhparam.pem;
配置完成后,用这些工具检测:
SSL Labs: https://www.ssllabs.com/ssltest/
目标是拿到A+评分:
A+:完美配置A:很好B:还行C及以下:需要优化常见扣分原因:
启用了TLS 1.0/1.1使用弱加密套件没有HSTS证书链不完整现象: 某些浏览器/设备显示证书不可信
原因: 只配置了cert.pem,没配置中间证书
解决: 使用fullchain.pem而不是cert.pem
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
现象: 页面有HTTPS,但控制台报Mixed Content
原因: 页面里引用了HTTP资源
解决:
<!-- 把http改成https或者用协议相对路径 -->
<img src="//example.com/image.jpg">
现象: 访问网站提示"重定向次数过多"
原因: 前面有负载均衡,Nginx收到的是HTTP请求
解决: 根据X-Forwarded-Proto判断
if ($http_x_forwarded_proto != "https") {
return 301 https://$server_name$request_uri;
}
原因: 80端口被占用,验证失败
解决: 使用DNS验证方式
certbot certonly --manual --preferred-challenges dns -d example.com
certbot --nginx -d example.com -d www.example.com -d api.example.com
# 泛域名必须用DNS验证
certbot certonly --manual --preferred-challenges dns -d "*.example.com" -d example.com
按提示添加DNS TXT记录完成验证。
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
有时候内网服务也需要HTTPS(比如自建NAS、内部系统)。
如果没有公网域名,可以用自签名证书或者mkcert。
更优雅的方案: 用组网工具配合域名
我有个内网的GitLab,想从外面HTTPS访问:
用星空组网把本地和服务器连起来服务器上配置Nginx反向代理申请正常的HTTPS证书这样内网服务也能用正规HTTPS证书,不用处理浏览器安全警告。
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl http2;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
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;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
# 静态资源缓存
location ~* .(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
HTTPS配置核心步骤:
申请证书 - Let’s Encrypt免费够用配置Nginx - 监听443,配置证书路径强制跳转 - 80端口跳转443安全加固 - TLS版本、加密套件、安全Header自动续期 - 定时任务自动renew检测评分 - SSL Labs测试拿A+配置一次,后面自动续期,基本不用管了。
有问题评论区交流~