Hi I m a junior engineer trying to get better with haproxy, so far I had a good experience until this
I’m trying to setup a haproxy as reverse proxy in our dmz, to route http/s and wss to our webappplications. We would like to get rid of our nginx reverse proxy as nobody knows it well, thats why I have a working configuration for nginx to do the reversing. I figured it would be easiest to try to translate this nginx config as best as I can to a haproxy conf, but the best I’ve got out of this is a 502 error… my guess so far is, that it has something to do with the change of URL from external to internal or the webapplication (but it works with nginx though ) …
The setup:
public IP <-> demo.crm.example.com
internal IP <-> demo.crm.example.local
haproxy listens on 443 and should do tls termination for demo.crm.example.com and proxy the traffic to the webapplication which does its own tls termination for demo.crm.example.lan . As much as I understand this webapplication, it builds up a login page on http traffic and then as you logged in, starts a wss tunnel.
Firewall rules and networking in general works, I m able to reverse simple http to a webserver. Maybe I m getting something wrong her or it has something to do with SSL or maybe it is just this webapplication which is playing stupid… I don’t have any clue what I m doing wrong her.
Knowing this and wanting to keep things simple, I would try commenting out all the acl and use_backend lines in your frontend (effectively sending everything to the default_backend), and see what happens.
If that’s a bit too drastic, I would definitely comment out http-request set-path /nrpc-wss in the backend. That sets the path for everything going to the server behind HAProxy, but this does not set the path with the client (usually a browser). More often than not, this causes problems. If this was intended to be a redirect, I would use redirect location /nrpc-wss instead.
Thanks @stormrover for the fast reply. I commented all the acl and use_backend out. It is still not working, but I will use the conf like that for further troubleshooting, as it looks like, traffic is passing through haproxy and going to the webapplication.
Maybe it has to do with the headers, because there is a Istio-Mesh (forgot to mention this) in front of the webapplication. Which should route traffic to the right service based on SNI.
The only way I was able to make it work, is to let it through in tcp mode, but as it looks like WSS isn’t working. As I only reach the login page and after login where WSS tunnel opens, it doesn’t happen
TCP mode isn’t really what I need, as I need to have TLS termination for the external URL (don’t know an other way to make that happen) and it is just weird that WSS isn’t even working. We are running a similar application behind HAProxy as internal LoadBalancer in TCP mode on which WSS works perfect…
Yep, if I connect to demo.crm.example.local everything works and if I put it behind that mentioned HAProxy Load Balancer, it works as well. The Load Balancer is also in TCP and the config is pretty much exactly the same.
The main differences between the Reverse Proxy (DMZ) and the Load Balancer (Server LAN), is the network they are in and the fact that the Reverse Proxy has NAT to make it external available. Also the HAProxy versions are different: RP version 2.4.18 and LB version 2.0.29
Could you share some logs from HAProxy? I’m specifically interested to see the session state at disconnection. If HAProxy has a problem with any request or response, it will show letter codes, for example CD-- which means the client unexpectedly aborted during data transfer. Generally, if it only shows four dashes like ----, then HAProxy is fulfilling the request as the backend server instructs it to.
As I understand this SH-- from the documentation, there is an issue with my certificate or can this indicate something else?
I’ve created the cert with certbot, I don’t know if you have any experience with it, but this is the command I used to setup the cert:
Okay, I guess I should have specified: You only get two letters in TCP mode because there’s no HTTP inspection going on. In TCP mode, your logs show HAProxy is passing the request through as instructed.
As for the SH-- part:
SH The server aborted before sending its full HTTP response headers, or
it crashed while processing the request. Since a server aborting at
this moment is very rare, it would be wise to inspect its logs to
control whether it crashed and why. The logged request may indicate a
small set of faulty requests, demonstrating bugs in the application.
Sometimes this might also be caused by an IDS killing the connection
between HAProxy and the server.
It appears your backend server expects SSL since it’s listening on 443, but you did not specify SSL on the server (and I can’t belive I missed that this whole time). It should probably look like:
check: poll the server every few seconds and make sure it’s up. (optional) ssl: use SSL to connect to this server
I don’t think that will fully resolve your issue, as TCP mode shows HAProxy is handling your request, but elliminating that error might expose another error that gives better info.
The other issue I had that producced the handshake to fail:
was an issue with me testing the auto renewal of certbot, the cert that was issued was a staging cert. Solved that as well and now everything is as it should be.