1

I'm trying to set up a proxy_pass while also using a socks5 proxy. I can access my backing service with curl using the following:

curl -x socks5h://localhost:8001 -svo /dev/null -I http://[abcd:1234::]:8000

So what I've currently got in my nginx config which doesn't work is:

location / {
  proxy_pass http://[abcd:1234::]:8000
  proxy_redirect http://localhost:8001 /;
}

It also seems like nginx has no notion of ALL_PROXY|HTTP(S)_PROXY environment variables which other applications can use.

Any idea how I can get this to work?

I did find a related question - socks5 proxy/tunnel for nginx upstream? but it's now 6 years old and I'm not sure works still.

Peter
  • 3,144
  • 11
  • 37
  • 56

1 Answers1

2

Why it does not work?

To my knowledge, proxy_pass, proxy_redirect and other functionality in the ngx_http_proxy_module is meant to act as a HTTP/HTTPS proxy only. This seems to be confirmed by the 'As a protocol, “http” or “https” can be specified.' note in proxy_pass documentation (no mention of SOCKS).

The proxy_pass directive allows you to tell NGINX to take whatever requests it receives at specific location and blindly send them to another HTTP server, wait for the response from said server and return the response to the client. Other directives from the module (for example proxy_redirect) allow slight modifications to requests/responses. What is important is that the entire process is very simple and there is no tunneling (aside from TLS when location is https) or wrapping in additional protocols.

In contrast, SOCKS proxies require implementation of the SOCKS proxy protocol and using it to wrap all the connections. This additional work cannot be performed using the ngx_http_proxy_module.

How to make it work?

Unfortunately, using SOCKS proxies in NGINX does not seem to be supported by any of the core modules (listed here below 'Module reference'). It also does not seem to be a popular use case, so i would not expect support for it in NGINX core anytime soon. In another question you linked one of the answers references a third party nginx module which is also listed on the nginx.com website (the list has no anchors, so CTRL + F for "SOCKS" and you will find it). Last commit is from 2016 but it is possible it will still work.

If you can't change the way you access your backend service, i would say your best bet is either using the module mentioned above and trying to fix it if it does not work or writing your own module. Alternatively, maybe you could establish port forwarding to the backend service over the SOCKS proxy, and just proxy_pass to your local port. If you have an ssh server running on your backend service host, you could set up a simple proof-of-concept like this:

ssh <YOUR-SSH-LOGIN>@<BACKEND-HOST> \
    -L 8081:localhost:80 \
    -o "ProxyCommand=nc -X 5 -x <YOUR-SOCKS-PROXY-IP>:<YOUR-SOCKS-PROXY-PORT> %h %p"

The -L argument creates port forwarding between your local 8081 port and port 80 (http) on backend host. The -o argument adds a ProxyCommand option which uses netcat to forward traffic over a SOCKS proxy (not all netcat versions support the -X and -x arguments, the one i am using is openbsd-netcat on Arch Linux). After using that you should be able to just proxy_pass to localhost:8081 in NGINX. This setup is not very performant and serves only as a proof-of-concept, if you decide to go this way you should find another method of forwarding ports over the proxy.

Finally, in my personal opinion, if you can you should change the way you access your backend service. If you were the one to set up the connection then SOCKS proxy is an overkill when all you want to do is to connect to few hosts. If it is a proxy put in place by your company or someone else above you then i would discuss it with the network administrators.

msaw328
  • 1,459
  • 10
  • 18