nginx严格执行https策略需三步:一、443端口启用ssl/tlsv1.2+及强加密套件;二、80端口独立server块用return 301跳转,禁用if判断;三、443块中add_header strict-transport-security含max-age、includesubdomains、preload与always参数。

要让 Nginx 严格执行 HTTPS 传输策略,关键不是“支持 HTTPS”,而是“拒绝 HTTP、强制加密、杜绝降级”。配置需分三步落地:启用 HTTPS 服务、强制跳转、启用 HSTS 安全头。下面直接讲清楚每一步该怎么做、为什么这么设。
启用并加固 HTTPS 服务
这是基础,但细节决定安全性:
-
监听端口与协议必须明确写死:用
listen 443 ssl http2;(推荐加http2提升性能),不能只写listen 443; -
证书路径要准确且权限受限:私钥文件(
.key)权限建议设为600,防止非 root 用户读取 -
协议和加密套件必须现代且精简:禁用 TLSv1.0 和 TLSv1.1;推荐配置:
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_session_cache shared:SSL:10m;和ssl_session_timeout 10m;,避免频繁握手
彻底关闭 HTTP 明文入口
仅配好 HTTPS 不够,用户手动输 http:// 或旧链接仍可能走明文。必须做 301 强制跳转:
- 单独定义一个
server块监听 80 端口,仅做重定向:server {<br> listen 80;<br> server_name example.com www.example.com;<br> return 301 https://$server_name$request_uri;<br>} - 不要用
if ($scheme = http) { ... },Nginx 官方明确不推荐在server块外用if做协议判断,易出错 - 确保所有
server_name都覆盖到,包括带 www 和不带 www 的域名,否则跳转会失败
启用 HSTS 强制浏览器只走 HTTPS
这是真正让“HTTPS 成为唯一选项”的最后防线。浏览器收到该响应头后,会在指定时间内自动把所有 HTTP 请求升级为 HTTPS,连首次访问也能保护(若加入预加载列表):
- 在 HTTPS 的
server块中添加:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; -
max-age=31536000表示一年有效期(秒),足够长但不过度激进;上线初期可先用max-age=300(5 分钟)测试 -
includeSubDomains让所有子域名(如 api.example.com、cdn.example.com)也受保护 -
preload是加入浏览器预加载列表的前提,提交前务必确认整个站点及所有子域已 100% 支持 HTTPS,否则会导致子域完全无法访问 - 注意:
always参数必须加上,否则 301/302 跳转响应中不会携带该头,起不到作用
验证与上线前检查
配置完别急着 reload,先做这几项确认:
- 用
nginx -t检查语法;用openssl s_client -connect example.com:443 -servername example.com验证证书链是否完整 - 用在线工具如 SecurityHeaders.com 检查 HSTS 头是否生效、是否含
preload - 用
curl -I http://example.com确认返回 301 且Location是https://开头 - 用
curl -I https://example.com确认响应头含Strict-Transport-Security,且没有http相关的混合内容警告











