核心是用server_name精准识别请求来源,再配合return或rewrite跳转;必须为每个待跳转域名配置独立server块,严格匹配Host头,禁止混用$host变量或if判断。

用 server_name 实现不同域名的重定向,核心不是“靠它跳转”,而是靠它**精准识别请求来源**,再配合 return 或 rewrite 完成跳转。关键在于:每个要跳转的域名必须有独立、明确的 server 块,且 server_name 必须严格匹配用户请求中的 Host 头。
单独为待跳转域名建 server 块
这是最可靠、官方推荐的做法。不要把多个跳转逻辑塞进同一个 server 块里。
- 比如要把 old.com 永久跳到 new.com,就专门写一个只认
old.com的块:
server {
listen 80;
server_name old.com;
return 301 https://new.com$request_uri;
}
- 如果还要处理
www.old.com,就再加一个块,server_name www.old.com;不能只写server_name old.com www.old.com然后统一跳转——那样会丢失意图,也容易出错。
裸域(如 example.com)跳 www(如 www.example.com)
很多问题出在只配了 www.example.com,却没管裸域。用户直接输 example.com 时,Nginx 找不到匹配的 server_name,就会落到默认 server 块,结果不可控。
- 正确做法是:裸域和 www 各自独立配置,裸域块只负责跳转:
server {
listen 80;
server_name example.com;
return 301 http://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
# 这里放真实站点配置,比如 root /var/www/html;
}
- HTTPS 场景同理,两个
server块分别监听 443,各自配好证书,裸域块 return 到https://www...。
避免混用 $host 和 server_name
$host 是请求头里的值,可能被客户端篡改或为空(比如 IP 直连),而 server_name 是你静态定义的、可信的域名列表。
- 错误写法:
server_name a.com b.com; return 301 https://$host$request_uri;—— 当用户用 IP 访问时,$host可能为空,跳转变成https:///xxx,报错。 - 正确写法:每个域名单独配块,用固定目标域名,比如
return 301 https://www.a.com$request_uri;,不依赖变量。
多域名共存但跳转规则不同
比如 site1.com 要跳 new1.com,site2.com 要跳 new2.com,那就必须写两个完全独立的 server 块:
server {
listen 80;
server_name site1.com;
return 301 https://new1.com$request_uri;
}
server {
listen 80;
server_name site2.com;
return 301 https://new2.com$request_uri;
}
- 别试图用
if ($host = ...)在一个块里判断跳转——Nginx 官方明确不推荐在 server 级别用 if 做重定向,易出边界问题,且性能略低。 - 确保 DNS 已把所有相关域名(包括裸域和 www)都解析到服务器 IP,否则请求根本到不了 Nginx。


















