Nc18 HAProxy reverse proxy proxy_protocol

Hi Community,

Is it possible to receive the client IP if using HAProxy ssl pass-through?

I have HAProxy as reverse proxy and a couple of different apps running in LXC containers, spread on two physical boxes. One of these (also running my production NC) runs my HAProxy NOT on i a container.

So far it is running smoothly but as I terminates TLS inside the containers and not on HAProxy, I receive only localhost connections. This kinda makes it hard to use the suspicious logins and bruteforce protection apps.

Anyone with a succes in this regards?

Hi Kerasit,

From what you described here, I think that you shot yourself in the foot on that one… The client IP is extracted from the IP packet received by the HTTP engine. From what you described, you put your HAProxy in TCP mode. That is, HAProxy terminates the TCP socket and starts a new one, without being able to put a note in the HTTP Header about it. It can not because it did not decrypt the SSL and did not handled the HTTP request.

So for that reason, the HTTP engine will receive a packet that is from HAProxy’s IP address. Because of that, this IP is what looks like the client.

To avoid that, you must work at either a higher level (HTTP) or a lower level (IP). Should you terminate the SSL on HAProxy, there it can see what is the “external” IP address and save it in a header like X-Forwarded-For. That way, when the HTTP engine will process the request, it can extract that header instead of the IP header and use it as a client IP address.

The other option would be to work at IP level. Instead of terminating the TCP session, just do NAT and port forwarding. That will replace only the destination part of the packet, not the source. That way, when the HTTP engine will see the IP packet, the original source will still be there.

But by playing at TCP level, you end up with the worst of each mode: IP is masked in the process, the request is not filtered at application layer and the HTTP engine ends up blinded without gaining any protection.

If you are about not adding protection in front of HTTP, just do NAT - Port forwarding and you will save your IP. Should you wish to add extra protection by filtering the requests before the HTTP engine, you need to terminate SSL and decrypt in front of the HTTP engine.

Thank you Heracles. That was the cleanest - and very easy to understand - explanation right there.

If I am to change my setup in such a fundamental way I considers a third option but I have not found a guide for it, but it must be possible:
Have HAProxy forward requests to my downstream application using FastCGI over LAN. That way HAProxy acts as if it is the webserver but without the load and then I can do the SSL teemination in HAProxy and still have my containered PHP-FPM application (nextcloud) isolated to keep the security and isolation intact.

Or I monitors the I/O on TCP level on HAProxy and the application layer on NC and correlates those logs to do Bruteforce protection and suspicious login protection from HAProxy.

Either way then NC is happy if HTTPS is set in NC side of things if using for example the password apps. The FastCGI seems as the best option - and fun project.

Sendt fra ProtonMail-mobil

Proxy Protocol V2 starts a connect with added payload to allow for downstream proxies and servers to be able to identify the origin client IP. However if ANY link in this chain does not support proxy protocal V2, then the connection fails entirely as the destination sees something wrong with the handshake connect attempt. I think this could have worked as both Apache and NGINX has support for this version however the LXD proxy only supports V1. So because of the LXD proxy, this is not possible.

If I changed to a LXD network bridge that either supports pure NAT and no proxying or a bridge which exposed the containers to my LAN so I could assign them LAN IP adresses I am pretty sure this could be achieved. I favors the NAT part - which might has to be PAT now that I think about it - for security of my containers.