Nginx配置HTTPS全攻略|从申请证书到安全加固

现在不上HTTPS,浏览器直接标红"不安全",SEO也受影响。

这篇文章整理了HTTPS配置的完整流程,从证书申请到安全加固,一篇搞定。


一、证书选择

1.1 证书类型

类型 验证方式 价格 适合场景
DV 域名验证 免费-几百 个人站、小网站
OV 组织验证 几百-几千 企业官网
EV 扩展验证 几千-几万 金融、电商

个人站用DV就够了,企业网站上OV,对安全要求极高的上EV。

1.2 免费证书推荐

服务商 有效期 限制 推荐度
Let's Encrypt 90天 ⭐⭐⭐⭐⭐
阿里云免费证书 1年 每年20个 ⭐⭐⭐⭐
腾讯云免费证书 1年 每年20个 ⭐⭐⭐⭐

二、申请Let's Encrypt证书

用Certbot自动申请,最方便。

2.1 安装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

2.2 申请证书

# 自动配置Nginx(推荐)
certbot --nginx -d example.com -d www.example.com

# 只申请证书,不修改Nginx配置
certbot certonly --nginx -d example.com

按提示输入邮箱,同意协议即可。

2.3 证书位置

申请成功后,证书在:

/etc/letsencrypt/live/example.com/
├── fullchain.pem  # 证书链
├── privkey.pem    # 私钥
├── cert.pem       # 证书
└── chain.pem      # 中间证书

2.4 自动续期

Let's Encrypt证书90天过期,需要自动续期:

# 测试续期
certbot renew --dry-run

# 添加定时任务
crontab -e
# 每天凌晨2点检查并续期
0 2 * * * certbot renew --quiet --post-hook "systemctl reload nginx"

三、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_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;
    }
}

3.2 检查配置并重载

# 检查语法
nginx -t

# 重载配置
systemctl reload nginx

四、安全加固

4.1 完整的安全配置

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;
}

4.2 生成DH参数(可选但推荐)

# 生成2048位DH参数,需要几分钟
openssl dhparam -out /etc/nginx/dhparam.pem 2048

Nginx配置添加:

ssl_dhparam /etc/nginx/dhparam.pem;

五、SSL评分检测

配置完成后,用这些工具检测:

SSL Labs: https://www.ssllabs.com/ssltest/

目标是拿到A+评分:

  • A+:完美配置
  • A:很好
  • B:还行
  • C及以下:需要优化

常见扣分原因:

  • 启用了TLS 1.0/1.1
  • 使用弱加密套件
  • 没有HSTS
  • 证书链不完整

六、常见问题

6.1 证书链不完整

现象: 某些浏览器/设备显示证书不可信

原因: 只配置了cert.pem,没配置中间证书

解决: 使用fullchain.pem而不是cert.pem

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

6.2 Mixed Content警告

现象: 页面有HTTPS,但控制台报Mixed Content

原因: 页面里引用了HTTP资源

解决:

<!-- 把http改成https或者用协议相对路径 -->
<img src="//example.com/image.jpg">

6.3 重定向循环

现象: 访问网站提示"重定向次数过多"

原因: 前面有负载均衡,Nginx收到的是HTTP请求

解决: 根据X-Forwarded-Proto判断

if ($http_x_forwarded_proto != "https") {
    return 301 https://$server_name$request_uri;
}

6.4 证书续期失败

原因: 80端口被占用,验证失败

解决: 使用DNS验证方式

certbot certonly --manual --preferred-challenges dns -d example.com

七、多域名/泛域名证书

7.1 多域名

certbot --nginx -d example.com -d www.example.com -d api.example.com

7.2 泛域名

# 泛域名必须用DNS验证
certbot certonly --manual --preferred-challenges dns -d "*.example.com" -d example.com

按提示添加DNS TXT记录完成验证。


八、反向代理HTTPS

8.1 Nginx代理后端服务

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;
    }
}

8.2 内网服务加HTTPS

有时候内网服务也需要HTTPS(比如自建NAS、内部系统)。

如果没有公网域名,可以用自签名证书或者mkcert。

更优雅的方案: 用组网工具配合域名

我有个内网的GitLab,想从外面HTTPS访问:

  1. 用星空组网把本地和服务器连起来
  2. 服务器上配置Nginx反向代理
  3. 申请正常的HTTPS证书

这样内网服务也能用正规HTTPS证书,不用处理浏览器安全警告。


九、配置模板

9.1 静态网站

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";
    }
}

9.2 API服务

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配置核心步骤:

  1. 申请证书 - Let's Encrypt免费够用
  2. 配置Nginx - 监听443,配置证书路径
  3. 强制跳转 - 80端口跳转443
  4. 安全加固 - TLS版本、加密套件、安全Header
  5. 自动续期 - 定时任务自动renew
  6. 检测评分 - SSL Labs测试拿A+

配置一次,后面自动续期,基本不用管了。

有问题评论区交流~


posted @ 2025-12-04 09:42  花宝宝  阅读(353)  评论(0)    收藏  举报