0
votes

I have the following setup in Docker:

PRIVATE SERVER <--> NGINX <--> PUBLIC SERVER

I need the NGINX server to work as both reverse and forward proxy with SSL passthrough. I have found online the following configuration for achieving this (note that for the forward proxy, I send packets always to the same destination, the public server, hardcoded in proxy_pass):

stream {
        upstream backend {
                server <private server IP address>:8080;
        }
        # Reverse proxy
       server {
               listen 9090;
               proxy_pass backend;
       }

        # Forward proxy
        server{
                listen 9092;
                proxy_pass <public server IP address>:8080;
        }
}

I have not tried the reverse proxy capability yet as the forward proxy is already giving me problems. In particular, when the private server tries to connect to the public server the TLS session fails.

On the public server it says:

http: TLS handshake error from <PUBLIC_SERVER_IP>:49848: tls: oversized record received with length 20037

while on the private server it says:

Post https://<PUBLIC_SERVER_IP>:8080/subscribe: malformed HTTP response "\x15\x03\x01\x00\x02\x02\x16"

This is what I see with tshark:

PRIVATE_SRV ? NGINX   TCP 74 48044?9092 [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=1209793579 TSecr=0 WS=128

NGINX ? PRIVATE_SRV   TCP 74 9092?48044 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=1209793579 TSecr=1209793579 WS=128

PRIVATE_SRV ? NGINX   TCP 66 48044?9092 [ACK] Seq=1 Ack=1 Win=29312 Len=0 TSval=1209793579 TSecr=1209793579

NGINX ? PUBLIC_SRV TCP 74 49848?8080 [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=1209793579 TSecr=0 WS=128

PRIVATE_SRV ? NGINX   HTTP 161 CONNECT <PUBLIC_SRV_IP>:8080 HTTP/1.1 

NGINX ? PRIVATE_SRV   TCP 66 9092?48044 [ACK] Seq=1 Ack=96 Win=29056 Len=0 TSval=1209793580 TSecr=1209793580

PUBLIC_SRV ? NGINX   TCP 74 8080?49848 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=854036623 TSecr=1209793579 WS=128

NGINX ? PUBLIC_SRV TCP 66 49848?8080 [ACK] Seq=1 Ack=1 Win=29312 Len=0 TSval=1209793580 TSecr=854036623

NGINX ? PUBLIC_SRV HTTP 161 CONNECT <PUBLIC_SRV_IP>:8080 HTTP/1.1 

PUBLIC_SRV ? NGINX   TCP 66 8080?49848 [ACK] Seq=1 Ack=96 Win=29056 Len=0 TSval=854036623 TSecr=1209793580

PUBLIC_SRV ? NGINX   HTTP 73 Continuation

NGINX ? PUBLIC_SRV TCP 66 49848?8080 [ACK] Seq=96 Ack=8 Win=29312 Len=0 TSval=1209793581 TSecr=854036623

NGINX ? PRIVATE_SRV   HTTP 73 Continuation

PRIVATE_SRV ? NGINX   TCP 66 48044?9092 [ACK] Seq=96 Ack=8 Win=29312 Len=0 TSval=1209793581 TSecr=1209793581

PUBLIC_SRV ? NGINX   TCP 66 8080?49848 [FIN, ACK] Seq=8 Ack=96 Win=29056 Len=0 TSval=854036624 TSecr=1209793580

NGINX ? PUBLIC_SRV TCP 66 49848?8080 [FIN, ACK] Seq=96 Ack=9 Win=29312 Len=0 TSval=1209793581 TSecr=854036624

NGINX ? PRIVATE_SRV   TCP 66 9092?48044 [FIN, ACK] Seq=8 Ack=96 Win=29056 Len=0 TSval=1209793581 TSecr=1209793581

PRIVATE_SRV ? NGINX   TCP 66 48044?9092 [FIN, ACK] Seq=96 Ack=9 Win=29312 Len=0 TSval=1209793581 TSecr=1209793581

NGINX ? PRIVATE_SRV   TCP 66 9092?48044 [ACK] Seq=9 Ack=97 Win=29056 Len=0 TSval=1209793581 TSecr=1209793581

PUBLIC_SRV ? NGINX   TCP 66 8080?49848 [ACK] Seq=9 Ack=97 Win=29056 Len=0 TSval=854036624 TSecr=1209793581

Do you have any suggestion on how to debug this? Is the fact that I am using HTTPS POST matter? Does it matter for NGINX that I am not using the default port 443 for SSL?

Thanks a lot for all the help you may give me.

P.S. If I remove the NGINX proxy, everything works fine.

1

1 Answers

1
votes

I have found the problem. It was actually a code issue. I am using Golang. The problem was that I was configuring the Proxy as:

*httpsCl = http.Client{
       Transport: &http.Transport{
            Proxy: http.ProxyURL(proxyUrl),
            TLSClientConfig: tlsConfig
       },
}

and in doing so the private server was expecting to talk to the Proxy which does not work if we are using SSL passthrough. Instead I had to configure the proxy as:

*httpsCl = http.Client{
                Transport: &http.Transport{
                        Dial: func(network, addr string) (net.Conn, error){
                                   return net.Dial("tcp", proxyUrl.Host)
                              },
                        TLSClientConfig: tlsConfig
                },
}

Thanks all!