Nginx Reverse Proxy – How to Use Nginx as SSL Reverse Proxy for PostgreSQL TCP Connection

nginx-reverse-proxypostgresqlssl

What I want to achieve is this

[Postgresql Database] — transparent TCP — [clients on the cloud]

[Postgresql Database] — transparent TCP — [nginx on jump server] –SSL TCP– [clients outside the cloud]

I would like to add an additional layer of SSL encryption by nginx reverse proxy on stream with SSL parameter.

The added configuration in nginx.conf is this (with SSL certificates and keys already made)

stream{
        upstream pg{
                server [postgresql server ip]:5432;
        }
        server{
                listen  5430;
                #ssl_preread on;
                ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
                ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
                ssl_certificate /etc/nginx/cert/server.crt;
                ssl_certificate_key /etc/nginx/cert/server.key;
                ssl_session_timeout 2h;
                ssl_verify_client off;
                proxy_pass pg;
        }
}

I tried to telnet [jump server public ip] 5430 and the connection opened. However as I uses dbeaver client to connect to that gateway, it responded 'SSL is not allowed on the server'. What is wrong? Does postgresql know that this dbeaver client's connection with nginx is SSL encrypted and replied an error message?

Best Answer

You cannot do this since TLS within PostgreSQL is not a simple wrapper around the non-TLS connection like it is with HTTPS being HTTP over TLS. Instead it starts with some plain communication which then gets upgraded to TLS. Because of this a reverse proxy cannot simply terminate TLS and forward the inner application data, but must actually implement some basics of the protocol used by PostgreSQL - and nginx does not provide this.

For more details see NGINX TLS termination for PostgreSQL