Nginx 反向代理到路径中指定的服务器

Nginx reverse proxy to server that's specified in the path

我有一个 nginx 反向代理位置设置,如下所示:

location /192.168.0.10 {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_cookie_path /phpmyadmin/ /;
    proxy_redirect off;
    proxy_pass    http://192.168.0.10/;
}

location /192.168.0.11 {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_cookie_path /phpmyadmin/ /;
    proxy_redirect off;
    proxy_pass    http://192.168.0.11/;
}

location /192.168.0.12 {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_cookie_path /phpmyadmin/ /;
    proxy_redirect off;
    proxy_pass    http://192.168.0.12/;
}

location /192.168.0.13 {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_cookie_path /phpmyadmin/ /;
    proxy_redirect off;
    proxy_pass    http://192.168.0.13/;
}

location /192.168.0.14 {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_cookie_path /phpmyadmin/ /;
    proxy_redirect off;
    proxy_pass    http://192.168.0.14/;
}

location /192.168.0.15 {..... 

这个结构重复了大约 96 次,所以我们可以对每个结构都有一个反向代理。有没有一种方法可以简化它,以便只有一个结构,并且位置路径中的 IP 神奇地出现在 proxy_pass 指令中?因为随着我们添加和删除服务器,这变得很难管理。

我认为以下正则表达式匹配位置应该有效:

location ~ ^/(?<proxy>192\.168\.0\.(?:10|11|12|13|14|15|...))(?:/(?<path>.*))?$ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_cookie_path /phpmyadmin/ /;
    proxy_redirect off;
    proxy_pass    http://$proxy/$path;
}

你还可以优化那个非捕获组 (?:10|11|12|13|14|15|...),例如匹配从 10105 的任何数字,它可以写成 (?:10[0-5]|[1-9]\d)

更新 1

根据 OP 的要求,对任何 IPv4 地址进行严格检查的 PCRE 正则表达式(仅匹配从 0.0.0.0255.255.255.255 的正确 IPv4 地址,改编自 this 答案)可以是写成

location ~ "^/(?<proxy>(?:25[0-5]|2[0-4]\d|[01]?\d?\d\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))(?:/(?<path>.*))?$" {
    ...
}

由于大括号的使用,正则表达式模式必须用双引号引起来。

更新 2

以前的解决方案不会保留请求查询字符串,保留所有请求查询参数的更正确的解决方案是使用 proxy_pass http://$proxy/$path$is_args$args 指令:

location ~ "^/(?<proxy>(?:25[0-5]|2[0-4]\d|[01]?\d?\d\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))(?:/(?<path>.*))?$" {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_cookie_path /phpmyadmin/ /;
    proxy_redirect off;
    proxy_pass    http://$proxy/$path$is_args$args;
}