Score:0

Using socat forwarder over HTTP tunnel (CONNECT) over SSL/TLS

cn flag

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 ?

Score:1
by flag

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

ws flag
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.
NiceRath avatar
by flag
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
ws flag
But how is SNI configured at the origin host? You need to use the DNS name of the origin to connect.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.