Using nginx regex location matching to dynamically map URI's to different ports for multiple reverse proxies

♀尐吖头ヾ 提交于 2020-12-04 03:46:35

问题


I'm using nginx to create a reverse proxy to a web app that may be behind a firewall. For my initial proof of concept I used the following location block to ensure it worked.

    location / {
            proxy_pass https://localhost:2222;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
    }

I open up my reverse tunnel on my web app with ssh -f -N -T -R2222:localhost:443 user@nginx-ip. This works exactly as I like. I type in my nginx-ip into my browser and I get the https traffic from my web app but obfuscated by the nginx-ip, etc.

I want to allow potentially a few thousand reverse tunnels though across a few thousand ports (instead of just 2222 in the above case). Reading up on nginx, I thought to use regular expressions to dynamically use a URI containing the port number to proxy_pass to that specific port.

That is, I'd like https://nginx-ip/2222/ to proxy_pass https://localhost:2222; and I'd like https://nginx-ip/1111/ to proxy_pass https://localhost:1111;.

I've tried quite a few variations, but as far as I've been able to reason, I've landed on thinking this should work:

    location ~* ^/(\d+) {
            proxy_pass https://localhost:$1;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
    }

It doesn't. I get a 502 Bad Gateway in my browser and the error log gives me:

2016/05/31 21:02:36 [error] 6188#0: *3584 no resolver defined to resolve localhost, client: {my-client-ip}, server: localhost, request: "GET /2222/ HTTP/1.1", host: "{nginx-ip}"

When I use 127.0.0.1 instead of localhost I get a 404. The webpage says

Not Found The requested URL /2222/ was not found on this server.

Is what I'm attempting possible with nginx configuration?

To reiterate, I would like to be able to initiate many (thousands) unique reverse tunnels through an nginx web server. My initial thought was to vary the outgoing ports of the nginx server based on what other web app I want to proxy through, and to assign the request to my nginx server to a different port by a port in the URI (extracting it via regex).


回答1:


To solve my problem, and with the help of @Cirdec I ended up going a different direction.

Instead of using path in the URI to reference port, I was successful using the port as a subdomain. That is, 1111.my-host-name will send things through the reverse proxy on 127.0.0.1 (localhost) on port 1111. This requires enlisting some DNS wildcarding to help with some of the heavy listing (of note: wildcard DNS matching in /etc/hosts will not work, but you can hard code a few entries to test that it works.

Excerpt from my /etc/hosts file:

nginx-box-ip-address     2222.my-host-name
nginx-box-ip-address     1111.my-host-name

This paired with nginx config:

server {
    listen 443;
    server_name ~^(?<port_subdomain>[0-9]*).my-host-name$;

    # NOTE: omitted extra ssl configuration lines

    location / {
            proxy_pass https://127.0.0.1:$port_subdomain;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
    }
}

Now I can have my web app open up reverse proxy tunnels to arbitrary ports on my nginx box (my-host-name) and reach them through a subdomain.

An step by step example:

  • On one of my web app boxes, I open up a reverse tunnel to port 2222 on my nginx box (my-host-name) with ssh -f -N -T -R2222:localhost:443 user@my-host-name
    • On a different web app box I can open up a different tunnel to the same nginx box (my-host-name), say port 1111 by running ssh -f -N -T -R1111:localhost:443 user@my-host-name on the different web app box
  • On my nginx box, I have loaded the config above. I open up chrome and hit 2222.my-host-name and it is as if I'm directly hitting the URL/IP address of my web app box (only it can be behind a firewall thanks to the reverse proxy). Hitting 1111.my-host-name takes me to the other web app box, that is completely separate and through a completely separate tunnel.



回答2:


You should be able to do this with a combination of a url-rewriting rule to remove the digits specifying the port and a named capture to extract the requested_port as a usable variable for the proxy_pass directive.

    location ~* ^/(?<requested_port>\d+) {
            rewrite /(\d+)(.*) /$1  break;
            proxy_pass https://localhost:$requested_port;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
    }


来源:https://stackoverflow.com/questions/37555674/using-nginx-regex-location-matching-to-dynamically-map-uris-to-different-ports

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!