Nginx configuration with HAproxy proxy protocol and internal redirection

haproxynginxreverse-proxy

I need to redirect HTTPS stream from HAProxy to Nginx without SSL termination and without loosing an info about the original client IP. Unfortunately I cannot change the configuration of default 443 site on Nginx because it's maintained by Synology NAS configuration.

I was thinking about new listen port on Nginx accepting proxy protocol from HAProxy and kind of internal redirection to the local 443 port without SSL decoding / encoding, but with passing the original client IP taken from HAProxy. Is that somehow possible?

Edit:
The background is that I have tunneled OpenVPN and web services on the same external 443 port, so actually it looks as below:

router 443 TCP  ->  HAProxy -> SNI check -> stunnel -> OpenVPN
                                  |
                                  ------> SSL termination -> Nginx 443 HTTPS

I use HAProxy because ngx_stream_ssl_preread_module is not available on Synology's builtin Nginx.

Edit: I think the situation and question can be more generic:

Nginx:
port X accessed via proxy protocol with SSL/TLS
port Y

How to pass the stream from port X to Y with the information about the source client IP and without the SSL termination? Is listen directive with proxy_protocol on port Y the only possible option?

Best Answer

Yes, you can do the above with nginx.

A simple Google search reveals that the listen directive has a proxy_protocol parameter since 1.5.12, which, for security reasons, should probably be used in conjunction with the set_real_ip_from directive:

Note that this will invariably require minimal modification of the nginx configuration that's in your case maintained by the third-party tool that you mention; for obvious security reasons, it should not be possible to pass client-IP information without any such modification.


Additionally, note that you don't actually need HAProxy anymore — the new stream functionality within nginx already lets you operate on TCP and SSL streams, including, as of the most recent versions, the ability to discriminate unopened SSL streams based on SNI, the Server Name Indication — see ssl_preread and the corresponding $ssl_preread_server_name since 1.11.5.