【问题标题】:nginx dynamic proxy_pass based on url pa基于url pa的nginx动态proxy_pass
【发布时间】:2019-02-04 06:17:05
【问题描述】:

我的 nginx 配置文件中目前有以下代理传递定义:

location /pass/ {
    proxy_pass http://localhost:9999/pass/;
    proxy_redirect     off;
    proxy_set_header   Host $host;
}

这是按预期工作的 - /pass 请求被转发到在端口 9999 上运行的应用程序。

现在,我想做的是使端口转发部分动态如下:

location /pass/<input> {
    {a $port variable here that is evaluated via a script (php?)}
    proxy_pass http://localhost:$port/pass/;
    proxy_redirect     off;
    proxy_set_header   Host $host;
}

对 /pass/ABCD1234 的请求应转发到端口 9898,对 /pass/ABCD5678 的请求应转发到端口 9797。

请注意,流程是动态的 - 因此,从 ABCD1234 到 9898 的映射应该通过某种脚本(可能是 PHP?)发生,并且根据脚本的输出(端口)proxy_pass 应该将请求转发给那个港口。

请在这方面提供帮助。

更新:

我不想从 URI 输入中获取 proxy_pass 端口,而是希望通过 cookie 来实现这一点。所以,这里是更新的代码块:

location /pass/ {
    add_header X-debug-message $host always;
    add_header X-debug-message $cookie_sdmport;
    set $proxyurl http://127.0.0.1:$cookie_theport/pass/;
    add_header X-debug-message $proxyurl;
    proxy_pass $proxyurl;
    proxy_redirect     off;
    proxy_set_header   Host $host;
}

使用此代码,将循环 301 重定向回浏览器。我切换回静态端口的那一刻,它又可以工作了!奇怪的! X-debug-message 中的 $proxyurl 在浏览器上看起来是正确的。所以,想知道为什么 proxy_pass 会做 301!

更新 2:

终于可以使用以下设置进行转发:

    set $targetIP 127.0.0.1;
    set $targetPort $cookie_passport;
    proxy_pass http://$targetIP:$targetPort$request_uri;

不确定为什么上面发布的解决方案一直以 301 旋转 - 我猜 nginx 不喜欢在 proxy_pass 参数中混合动态和静态部分

谢谢。

【问题讨论】:

    标签: nginx nginx-reverse-proxy


    【解决方案1】:

    您可以使用auth_request 模块执行此操作。虽然它不是默认构建的,但您可以通过运行以下命令来确定是否拥有它:

    nginx -V 2>&1 | grep -qF -- --with-http_auth_request_module && echo ":)" || echo ":("
    

    如果你看到一张笑脸,那你就可以走了。

    location ~* /pass/(.*) { <- regex capture for your variable
        auth_request /auth;  <- location to process request
        auth_request_set $proxyurl http://localhost:$upstream_http_x_port/pass/; <- set $proxyurl using value returned in x-port header of your php script
        add_header x-my-variable $1; <- Pass variable from regex capture to auth location
        proxy_pass $proxyurl;
    }
    

    然后是处理身份验证子请求的位置:

    location /auth {
        internal; <- make location only accessible to internal requests from Nginx
        proxy_set_header x-my-variable $http_x_my_variable; <- pass variable to php
        proxy_pass_request_body off; <- No point sending body to php
        proxy_set_header Content-Length "";
        proxy_pass http://your-php-script/file.php;
    }
    

    这个模块实际上是用来控制访问的,所以如果你的 php 脚本返回响应码 200 则客户端将被允许访问,如果它返回 401 或 403 则访问将被拒绝。您是否不在乎,然后将其设置为始终返回 200。

    做任何你需要的评估,让你的 php 在前面定义的标头中返回端口:

    header('X-Port: 9999');
    

    现在这会为您的 proxy_pass 指令端口号设置变量,其余的由 Nginx 完成。

    【讨论】:

    • :) :) :) - 当然我有 auth_request_module。那里的触感很好。
    • 我尝试使用 cookie 略有不同。大部分流程工作正常 - 但是一旦构建了 proxy_pass url,请求就会不断重定向回浏览器。我修改后的代码块是
      location /pass/ { proxy_pass http://localhost:$cookie_theport/pass/; proxy_redirect off; proxy_set_header Host $host; }
    • 使用调试标头我看到 URL 构造正确,但代理传递只是以某种方式简单地重定向回浏览器
    • cookie 确定了吗?在您更新的问题中,您还引用了$cookie_sdmport,这相关吗?我个人建议不要这样做,风险可能很小,但您将请求基础设施的路由暴露给可以被客户端利用的机制。使用 auth_request,将客户端 IP 路由存储在 Memcache 中,运行一个 php 脚本,无论如何,但保持该进程内部而不是对客户端干扰开放
    • 当然,我不打算将端口或主机信息放在 $cookie_XXX 中——一旦我完成了基本流程,我打算使用 auth_request 方式将令牌转移到实际端口php
    猜你喜欢
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 2020-06-09
    • 2013-09-27
    相关资源
    最近更新 更多