【问题标题】:conditional routing with nginx based on referer基于referer的nginx条件路由
【发布时间】:2019-05-12 03:15:51
【问题描述】:

我需要根据 http 请求来源路由流量。我有两个环境,我们需要使用“$http_referer”将“/us-en”的每个 http 请求重定向到 Environment1,将其他请求重定向到 Environment2。

  1. 基于位置的重定向有效。
location ~ /us-en { 
    proxy_pass Environment1; 
    proxy_set_header Host Environment1; 
} 
  1. 对于“$http_referer”,以下选项不起作用。请求您的建议。
if ($http_referer ~ ^https?://dev.xyz.com/us-en){ 
    rewrite ^/us-en(/*)$ HOME_PAGE$1 break; 
    proxy_pass Environment1; 
}
Error: nginx: [emerg] "proxy_pass" directive is not allowed here in /opt/nginx/conf/nginx.conf.

注意:默认情况下,所有流量都进入 Environment2,因为存在上游配置。

【问题讨论】:

  • 您确定要准确检查 Origin 标头,而不是 RefererOrigin 标头不包含 URI(在您的情况下,它可以是 http://dev.xyz.comhttps://dev.xyz.com),并且主要由浏览器在 AJAX 请求上发出。
  • 是的,referer 更合适。你能推荐一下语法吗?

标签: nginx nginx-reverse-proxy nginx-config


【解决方案1】:
    # needed if your proxy destination specified with domain name instead of IP address
    resolver 8.8.8.8;

    location /home/ {
        proxy_set_header Host HOST1;
        # setup other proxied headers if needed
        if ($http_referer ~ ^https?://dev.xyz.com/home) {
            rewrite ^/home(/.*)$ HOME_PAGE$1 break;
            proxy_pass https://HOST1:8080; # this can be specified by IP address
        }
    }

对于来自dev.xyz.com/home/...(但不是来自dev.xyz.com/any/other/path!)的your_domain.com/home/path/file 的此类配置请求将被代理到https://HOST1:8080/HOME_PAGE/path/file。如果您使用域名而不是 IP 地址指定代理目标,则需要在服务器配置中指定附加参数 resolver。如果您有本地名称服务器,您可以使用本地名称服务器,也可以使用外部名称服务器,例如 Google 公共 DNS (8.8.8.8) 或 ISP 为您提供的 DNS。无论如何,这样的配置会导致额外的 DNS 查找,因此如果可以,请使用 IP 地址指定您的代理目标。

更新

valid_referers 指令还有另一种方法:

    # needed if your proxy destination specified with domain name instead of IP address
    resolver 8.8.8.8;

    location /home/ {
        proxy_set_header Host HOST1;
        # setup other proxied headers if needed
        valid_referers example.com/home;
        if ($invalid_referer = "") {
            rewrite ^/home(/.*)$ HOME_PAGE$1 break;
            proxy_pass https://HOST1:8080; # this can be specified by IP address
        }
    }

更新@2020.11.11

除了这个答案以某种方式获得了 5 分之外,给定的解决方案的设计非常糟糕(在 location 和嵌套的 if 块中拥有不同的内容处理程序并不是一个好方法;此外,具有如果可能,应避免使用除来自 nginx rewrite module 之外的任何指令的 if 块)并且在早期的 nginx 版本上根本不起作用(当我看到我的一些早期答案时,我想哭)。一个原始的 OP 问题是

逻辑应该如下,但有一些语法错误。

if ($http_origin ~ '^http?://(dev.xyz.com/home)') {
    set $flag 'true';
}

if ($flag = 'true') {
    location /home/ {
        proxy_pass  "https://HOST1:8080/HOME PAGE/";        
    }
}else{
    Do Not proxy pass
}

不清楚不代理通过是什么意思。如果它意味着返回一些 HTTP 错误(例如,HTTP 403 Forbidden),可以通过以下配置完成:

location /home/ {
    if ($http_referer !~ ^https?://dev.xyz.com/home) {
        return 403;
    }
    rewrite ^/home(/.*)$ HOME_PAGE$1 break;
    proxy_set_header Host HOST1;
    # setup other proxied headers if needed
    proxy_pass https://HOST1:8080; # this can be specified by IP address
}

如果不代理传递的意思是在本地服务请求,解决方法就比较复杂了:

map $http_referer $loc {
    ~^https?://dev.xyz.com/home    loc_proxy;
    default                        loc_local;
}

server {
    ...
    location /home/ {
        try_files /dev/null @$loc;
    }
    location @loc_proxy {
        rewrite ^/home(/.*)$ HOME_PAGE$1 break;
        proxy_set_header Host HOST1;
        # setup other proxied headers if needed
        proxy_pass https://HOST1:8080;
    }
    location @loc_local {
        rewrite ^/home(/.*)$ HOME_PAGE$1 break;
        root /path/to/required/page;
        ...
    }

try_files /dev/null @the_named_location; 技巧取自 this 优秀答案。

但是,现在编辑后的 ​​OP 的问题说明了不同的要求,这也可以通过 map 指令帮助来实现:

map $http_referer $environment {
    ~^https?://dev.xyz.com/home    Environment1;
    default                        Environment2;
}

server {
    ...
    location /home/ {
        rewrite ^/home(/.*)$ HOME_PAGE$1 break;
        proxy_set_header Host $environment;
        # setup other proxied headers if needed
        proxy_pass https://$environment;
    }

【讨论】:

  • 感谢您的建议 #1。基于位置的重定向工作 ***** location ~ /HOME_PAGE { proxy_pass IP_ADDRESS; proxy_set_header 主机 IP_ADDRESS; } ***** #2。使用 '$http_referer' 以下选项不起作用。请求您的建议。 ***** if ($http_referer ~ ^https?://dev.xyz.com/HOME_PAGE){ rewrite ^/HOME_PAGE(/*)$ HOME_PAGE$1 break; proxy_pass IP_ADDRESS; } ***** 错误:nginx: [emerg] "proxy_pass" 指令在 /opt/nginx/conf/nginx.conf 中是不允许的
  • @DebarshiDasGupta 你能用这个信息更新你的问题吗? Stackoverflow 的 cmets 格式化功能非常有限,这真的很难阅读。
  • 这个if 约束似乎位于任何location 块之外?尝试将其放在默认的 location 块中。顺便说一句,如果您提供完整的 nginx 配置,建议适当的解决方案会非常简单。
猜你喜欢
  • 1970-01-01
  • 2016-05-04
  • 2020-01-12
  • 2019-04-08
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-14
相关资源
最近更新 更多