具有动态端口转发的 Nginx 反向代理

stu*_*f22 5 nginx proxy reverse-proxy

我正在 Nginx 上设置反向代理。我需要它来监听多个端口。然后我想在后端服务器上访问完全相同的端口。像这样:http://frontendserver:9000 -> http://backendserver:9000

这是我认为会起作用的

   ## server configuration
    server {

        listen 9000 ;
        listen 9001 ;
        listen 9002 ;
        listen 9003 ;
        listen 9004 ;
        listen 9005 ;
        listen 9006 ;
        listen 9007 ;
        listen 9008 ;
        listen 9009 ;

        server_name frontendserver;

        if ($http_x_forwarded_proto = '') {
            set $http_x_forwarded_proto  $scheme;
        }

        location / {
                proxy_read_timeout  900;
                proxy_pass_header   Server;
                proxy_cookie_path ~*^/.* /;
                proxy_pass         http://backendserver:$server_port/;
                proxy_set_header    X-Forwarded-Port  $server_port;
                proxy_set_header    X-Forwarded-Proto $http_x_forwarded_proto;
                proxy_set_header    Host              $http_host;
                proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是,它给了我 502 Bad Gateway 错误。任何线索为什么会这样,或者是否有另一种方法可以像上面解释的那样工作?

如果我改变:

proxy_pass         http://backendserver:$server_port/;
Run Code Online (Sandbox Code Playgroud)

proxy_pass         http://backendserver:9000/;
Run Code Online (Sandbox Code Playgroud)

它工作得很好,这当然违背了目的......

unN*_*med 1

/var/www/9000我准备了只包含一个文件的目录index.html,其中包含与路径名对应的端口的内容。

server {
        listen 81;
        server_name example.com;
        location ~ /([^/]+) {
                proxy_set_header Host '10.20.30.40';
                proxy_pass http://10.20.30.40:$1/;
        }
}
server {
        listen 9000;
        server_name default;
        root /var/www/9000;
        try_files $uri $uri/index.html;
}
server {
        listen 9001;
        server_name default;
        root /var/www/9001;
        try_files $uri $uri/index.html;
}
server {
        listen 9002;
        server_name default;
        root /var/www/9002;
        try_files $uri $uri/index.html;
}
Run Code Online (Sandbox Code Playgroud)

我编辑了我的hosts文件以包含我的服务器的 IP 10.20.30.40 exmaple.com,这样我就可以在不需要 DNS 服务器的情况下进行测试。
然后我用地址打开浏览器http://example.com:81/9000。内容显示与我通过该位置提供的端口号相对应。

然后我认为可能是变量的问题,$server_name所以我进行了第二次测试。

server {
        listen 82;
        server_name example.com;
        location / {
                proxy_set_header Host '10.20.30.40';
                proxy_pass http://10.20.30.40:90$server_port/;
        }
}
server {
        listen 9082;
        server_name default;
        root /var/www/9082;
        try_files $uri $uri/index.html;
}
Run Code Online (Sandbox Code Playgroud)

现在我打开浏览器,http://example.com:82内容9082按预期显示。

如果您提供组名称以外的任何内容,upstream它将被视为域名。那就是你收到Bad gateway错误的时候。

这是您的解决方案:
您需要使用map将请求的端口转换为upsteam组并在proxy_pass.

upstream mycustombackend9082 {
        server 10.20.10.48:9082;
}
map $server_port $backendname {
        82      mycustombackend9082;
}
server {
        listen 82;
        server_name example.com;
        location / {
                proxy_set_header Host '10.20.30.40';
                proxy_pass http://$backendname;
        }
}
server {
        listen 9082;
        server_name default;
        root /var/www/9082;
        try_files $uri $uri/index.html;
}
Run Code Online (Sandbox Code Playgroud)

就我而言,我需要写入82map因为我无法两次打开端口。
您可以在此处查看另一个示例。