12

So, I have a third party proxy (probably under squid) which will only accept connections from one of my IP's, but I need to be able to access it from a variety of IPs.

So I'm trying to put a nginx to forward requests to this proxy. I know nginx can forward request like this:

location / {
    proxy_pass http://$http_host$uri$is_args$args;
}

This would work if I needed nginx to forward requests directly to the target site, but I need it to pass it to proxy X first. I tried this:

upstream myproxy {
   server X.X.X.X:8080;
}

location / {
   proxy_pass http://myproxy$uri$is_args$args; // also tried: http://myproxy$http_host$uri$is_args$args
}

But I get "(104) Connection reset by peer". I guess because nginx is proxying like this:

GET /index.html HTTP/1.1
Host: www.targetdomain.com.br

But I need it to proxy like this:

GET http://www.targetdomain.com.br/index.html HTTP/1.1
lucaswxp
  • 2,031
  • 5
  • 23
  • 34

1 Answers1

6

I found out that this works:

http {
  # resolver 8.8.8.8; # Needed if you use a hostname for the proxy
  server_name ~(?<subdomain>.+)\.domain\.com$;

  server {
    listen 80;

    location / {
      proxy_redirect off;
      proxy_set_header Host $subdomain;
      proxy_set_header X-Forwarded-Host $http_host;
      proxy_pass "http://X.X.X.X:8080$request_uri";
    }
  }
}

You need to use resolver if X.X.X.X is a hostname and not an IP.

Check https://github.com/kawanet/nginx-forward-proxy/blob/master/etc/nginx.conf for more tricks.

EDIT: also check nginx server_name wildcard or catch-all and http://nginx.org/en/docs/http/ngx_http_core_module.html#var_server_name

Community
  • 1
  • 1
Silex
  • 1,707
  • 17
  • 24
  • I understand, but in this case you need to set "www.targetdomain.com.br" manually, I want it to be resolved automatically. I'm using squid to do this now. – lucaswxp Mar 03 '17 at 13:42
  • I edited my answer to show how I deal with that (with `server_name` which captures into subdomain variable). – Silex Mar 03 '17 at 14:09
  • If you need to set the host based on the query parameters, you can do matches using `if` and `set`, etc (see the link at the bottom of my answer). – Silex Mar 03 '17 at 14:12
  • That's very interesting solution. Would be possible to match ANY server_name, not only a subdomain name, and then use it? – lucaswxp Mar 03 '17 at 14:23
  • For instance: server_name ~(?.+)$; Sorry, I don't have this setup anymore, so I cant test it. – lucaswxp Mar 03 '17 at 14:24
  • 1
    Yes, see http://nginx.org/en/docs/http/server_names.html. In your case, I believe you could remove the `server_name` directive, add a `default_server` to the `listen` directive and use `$server_name` instead of `$subdomain`. See my edits. – Silex Mar 03 '17 at 14:50
  • 3
    This still sends the request to the proxy in path-only form, not full URL with scheme. – adib Mar 15 '18 at 05:48
  • hi @lucaswxp I want to understand how you managed to resolve the URL instead from nginx. – Aman Jain Feb 18 '22 at 17:54