0

For context, i am using nginx's reverse proxy ngx_http_proxy_module to cache content from an upstream https server. For a specific project, i need nginx to pass through a corporate HTTP proxy (using the HTTP CONNECT method), and unfortunately this is not supported by nginx (and not planned either). Additionnaly, this project requires the connection to the proxy to be over SSL/TLS.

To work around this, i found a related question on stackoverflow which suggests to run socat as forwarder with the PROXY feature below, and have nginx use it as upstream server.

socat TCP4-LISTEN:8443,reuseaddr,fork PROXY:yourproxy:backendserver:443,proxyport=<yourproxyport>

The man page of socat states:

PROXY:<proxy>:<hostname>:<port>
Connects to an HTTP proxy server on port 8080 using TCP/IP version 4 or 6 depending on address specification, name resolution, or option pf, and sends a CONNECT request for hostname:port. If the proxy grants access and succeeds to connect to the target, data transfer between socat and the target can start. Note that the traffic need not be HTTP but can be an arbitrary protocol.
Option groups: FD,SOCKET,IP4,IP6,TCP,HTTP,RETRY
Useful options: proxyport, ignorecr, proxyauth, resolve, crnl, bind, connect-timeout, mss, sourceport, retry
See also: SOCKS, TCP

In other terms, this works with http proxies, except that the PROXY feature of socat does not support SSL/TLS (i.e. it cannot use an https proxy, only a plain http proxy), which is required among several professional environments nowadays.

Keeping in mind that i cannot easily swap nginx for something else, is there a way to turn the socat-> proxy connection over TLS, not involving writing a custom socat alternative ? Are there any alternative tools that can achieve this ?

1 Answers1

1

It would be a 'heavy' workaround - but you can always use stunnel to encapsulate your connection inside TLS. Here's an example on how to use it:

sudo apt install stunnel4

# /etc/stunnel/service.conf
[service]
client = yes
accept = 127.0.0.1:<local-port>
connect = <target-server>:<target-port>
checkHost = <target-server-name>
verifyChain = yes
sslVersionMin = TLSv1.2
# if internal CA is used
CAfile = <path-to-ca-crt>
# if client-cert-auth is used
cert = <path-to-client-crt>
key = <path-to-client-key>

Source: Google LDAP - STunnel

NiceRath
  • 11
  • 2
  • Stunnel will solve the problem however the example link is probably not very helpful in this case. The HTTPS request must be made using the DNSname of the target host in order to be routed correctly at the origin server. That means overriding the DNS on the nginx host. That's typically done with /etc/hosts - but stunnel needs to see the true resolution of the DNS name - so either use a hard-coded IP (bad) or run it on a separate host. – symcbean Aug 16 '23 at 12:25
  • If there are <10 known target hosts one could supply the stunnel config with multiple hardcoded `checkHost` options: > Multiple checkHost options are allowed in a single service section – NiceRath Aug 28 '23 at 09:10
  • But how is SNI configured at the origin host? You need to use the DNS name of the origin to connect. – symcbean Aug 29 '23 at 12:46