推荐用 return 301 替代 rewrite 实现 HTTP 到 HTTPS 跳转,因其性能更高、语义明确、无正则开销且避免 if 块风险;若必须用 rewrite,需独立 server 块监听 80 端口、加 permanent 关键字、防开放重定向。

直接用 rewrite 实现 HTTP 强制跳转 HTTPS 是可行的,但不推荐作为首选方案。它能工作,但存在性能开销、配置易错、语义模糊等实际风险。如果你因历史配置或特殊场景必须使用 rewrite,以下是安全、可用的做法和关键避坑点。
必须用独立 server 块监听 80 端口
rewrite 跳转逻辑不能塞进 HTTPS 的 server { listen 443 ssl; ... } 块里——Nginx 不允许 listen 80 和 ssl on 共存于同一块,否则启动失败。
正确结构是:
- 新增一个纯 HTTP 的
server块,只写listen 80;和跳转指令; - 原有的 HTTPS 服务保持在另一个
server块中,专注处理加密请求。
server {
listen 80;
server_name example.com www.example.com;
rewrite ^(.*)$ https://$host$1 permanent;
}✅
permanent关键字不可省略,否则默认返回 302(临时跳转),搜索引擎不传递权重。
❌ 错误写法:rewrite ^ https://$host$request_uri;(漏 permanent → 302);
❌ 更危险写法:rewrite ^ https://$host$request_uri redirect;(显式 302,明确放弃 SEO 权重)。
防开放重定向:别信 $host
$host 来自用户请求头中的 Host 字段,可被恶意篡改(如 Host: evil.com),导致跳转到任意第三方域名。
生产环境禁止直接拼接 $host。安全做法有两种:
-
硬编码目标域名(最简单可靠)
rewrite ^(.*)$ https://www.example.com$1 permanent;
-
白名单校验后跳转(适合多域名)
Linux Security Scanner下载Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
if ($host ~ ^(example\.com|www\.example\.com)$) { rewrite ^(.*)$ https://www.example.com$1 permanent; } return 444; # 非法 Host 直接断连
比 rewrite 更优的替代方案:用 return 301
虽然你问的是 rewrite,但必须强调:
-
return 301是立即响应,不触发 location 匹配、无正则解析、零变量展开; -
rewrite走完整匹配流程,若配置中有其他location或嵌套规则,可能意外干扰或循环; - 官方文档明确指出
if在server上下文中应尽量避免,而rewrite在server级本质也依赖类似机制。
推荐等效 return 写法(更稳更快):
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}补充:测试与上线前必查项
- 运行
nginx -t确认语法无误; - 检查证书路径是否为绝对路径,
.key文件权限是否为600; - 防火墙需放行
443端口(firewall-cmd --add-port=443/tcp --permanent); - 修改后用
nginx -s reload而非restart,避免连接中断。
不复杂但容易忽略。

















