Nginx rewrite实现域名跳转:从基础到进阶配置指南

一、Nginx rewrite模块的核心机制

Nginx的rewrite模块基于PCRE正则表达式实现URL路径和域名的灵活转换,其工作原理可分为三个关键阶段:

  1. 规则匹配阶段:通过ifserver块中的rewrite指令进行条件判断,支持~(区分大小写)、~*(不区分大小写)等正则修饰符。例如:
    1. if ($host != "example.com") {
    2. rewrite ^/(.*)$ https://example.com/$1 permanent;
    3. }
  2. 标志位控制last终止当前规则集处理并重启搜索,break直接停止处理,redirect(302)和permanent(301)控制重定向类型。测试时建议先用redirect验证逻辑。
  3. 变量应用:Nginx提供$host$http_x_forwarded_proto等200+内置变量,结合$1-$9捕获组可实现复杂跳转逻辑。如HTTPS强制跳转:
    1. server {
    2. listen 80;
    3. server_name example.com;
    4. rewrite ^ https://$host$request_uri? permanent;
    5. }

二、域名跳转的典型应用场景

1. 基础域名重定向

  • 裸域名跳转:将example.com跳转到www.example.com
    1. server {
    2. server_name example.com;
    3. return 301 https://www.example.com$request_uri;
    4. }
  • 多域名统一:将多个旧域名指向新主域
    1. server {
    2. server_name old1.com old2.com;
    3. rewrite ^/(.*)$ https://new.com/$1 permanent;
    4. }

2. HTTPS强制跳转

结合$scheme变量实现协议升级:

  1. server {
  2. listen 80;
  3. server_name example.com;
  4. return 301 https://$host$request_uri;
  5. }

对于反向代理场景,需额外处理X-Forwarded-Proto头:

  1. map $http_x_forwarded_proto $proxy_scheme {
  2. default $scheme;
  3. https https;
  4. }
  5. server {
  6. if ($proxy_scheme != "https") {
  7. return 301 https://$host$request_uri;
  8. }
  9. }

3. 路径保留跳转

使用捕获组保持URL路径不变:

  1. server {
  2. server_name old-site.com;
  3. rewrite ^/blog/(.*)$ https://new-site.com/articles/$1 permanent;
  4. }

三、性能优化与安全实践

1. 配置效率提升

  • 优先使用return:简单跳转时return 301rewrite ... permanent性能高30%
  • 避免复杂正则:如^/([a-z]+)/([a-z]+)/?$可拆分为多个简单规则
  • 启用PCRE缓存:在nginx.conf中添加pcre_jit on提升正则匹配速度

2. 安全防护措施

  • 防止URL注入:对$request_uri进行转义处理
    1. set $safe_uri $request_uri;
    2. if ($safe_uri ~* "(\.\.|/../)") {
    3. return 403;
    4. }
  • 限制跳转频率:通过limit_req模块防止滥用
    1. limit_req_zone $binary_remote_addr zone=rewrite_limit:10m rate=5r/s;
    2. server {
    3. location / {
    4. limit_req zone=rewrite_limit;
    5. # 正常跳转规则...
    6. }
    7. }

3. 监控与调试

  • 日志记录:在access_log中记录重定向信息
    1. log_format rewrite_log '$remote_addr - $host "$request" '
    2. 'status $status redirect "$upstream_addr"';
    3. access_log /var/log/nginx/rewrite.log rewrite_log;
  • 实时测试:使用curl -I验证跳转状态码
    1. curl -I http://example.com
    2. # 应返回 HTTP/1.1 301 Moved Permanently

四、进阶配置技巧

1. 动态域名处理

结合Lua脚本实现动态跳转逻辑(需安装ngx_http_lua_module):

  1. location / {
  2. set_by_lua $target '
  3. local host = ngx.var.host
  4. if host == "api.example.com" then
  5. return "https://new-api.example.com"
  6. else
  7. return "https://www.example.com"
  8. end
  9. ';
  10. return 301 $target$request_uri;
  11. }

2. 条件跳转链

通过多个if实现复杂逻辑(注意Nginx的if是邪恶的,建议用map替代):

  1. map $host$request_uri $redirect_url {
  2. default "";
  3. "~^old\.com/product/(.*)" "https://new.com/goods/$1";
  4. "~^beta\.old\.com" "https://preview.new.com";
  5. }
  6. server {
  7. if ($redirect_url) {
  8. return 301 $redirect_url;
  9. }
  10. }

3. 正则表达式优化

  • 非捕获组:使用(?:...)减少不必要的捕获
    1. rewrite ^/(?:en|fr)/news/(.*)$ https://global.example.com/news/$1 permanent;
  • 预查断言:实现更精确的匹配
    1. rewrite ^(?=.*\/api\/)(.*)$ https://api.example.com$1 permanent;

五、常见问题解决方案

  1. 跳转后丢失参数:确保使用$request_uri而非$uri

    1. # 错误示例
    2. rewrite ^/old$ /new permanent; # 丢失查询参数
    3. # 正确写法
    4. rewrite ^/old$ /new$is_args$args permanent;
  2. HTTPS跳转循环:检查是否同时存在80和443端口的跳转规则

  3. 正则匹配失效:确认正则修饰符是否正确,如~*表示不区分大小写

  4. 性能瓶颈:对高流量站点,建议将重定向规则放在独立的server块中

六、最佳实践建议

  1. 301与302的选择:永久变更用301(利于SEO),临时变更用302
  2. 测试环境验证:使用nginx -t检查配置语法,通过strace跟踪执行过程
  3. 版本控制:对rewrite规则进行版本管理,便于回滚
  4. 缓存控制:对重定向响应设置Cache-Control: no-store
  5. 文档维护:为每条重定向规则添加注释说明其业务背景

通过系统掌握这些配置技巧,开发者可以构建出高效、安全、可维护的域名跳转系统。实际部署时建议先在测试环境验证所有跳转路径,确保不会出现意外重定向或信息泄露风险。