Chained HAProxy in tcp mode with proxy protocol enabled not working

Hi,

I have a haproxy setup as follow:

Client --> Haproxy (LOCATION A)------> HAProxy(LOCATION B)----> Server

Both HA Proxy are running in TCP mode in both frontend and backend. My server wants to see actual client ip connecting to it, so I have enabled send-proxy on location A haproxy and sending it haproxy at location B. I can proxy header on my server. I can see initial ssl handshake between haproxy at location B and server, but no data is being sent and response not received at the client end.

Location A config :

global
log 127.0.0.1:514 local0 info
log 127.0.0.1:514 local0 debug
#log 127.0.0.1:514 local1 notice
#log loghost local0 info
maxconn 4096
#chroot /usr/share/haproxy
#user haproxy
#group haproxy
daemon
debug
#quiet
#ssl-server-verify none
defaults
mode tcp
log global
option httplog
option dontlognull
option http-server-close
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000

frontend https_in
bind *:443
mode tcp
option tcplog
timeout client 1m
default_backend https

backend https
mode tcp
option tcplog
option log-health-checks
#option redispatch
server halocb x.x.x.x:443 check send-proxy-v2

Location B config :

global
log 127.0.0.1:514 local0 info
log 127.0.0.1:514 local0 debug
#log 127.0.0.1:514 local1 notice
#log loghost local0 info
maxconn 4096
#chroot /usr/share/haproxy
#user haproxy
#group haproxy
daemon
debug
#quiet
#ssl-server-verify none
defaults
mode tcp
log global
option httplog
option dontlognull
option http-server-close
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000

frontend https_in
bind *:443
mode tcp
option tcplog
timeout client 1m
default_backend https

backend https
mode tcp
option tcplog
option log-health-checks
#option redispatch
server halocb mysite.ul.com:443 check ssl verify none

Your missing the accept-proxy keyword on the bind line of haproxy B.

If I put accept-proxy on the Location B, Protocol Header (Proxy TCP4 srcip, dstip, srcport, dstport) is not received on the web server

Which software is that webserver running on how does the configuration look like?

Its our custom upload server written in JAVA.

Well it sounds like your implementation is buggy then.

Are you absolutely sure that you implemented the v2 (the binary) PROXY protocol in your server, not the ASCII one?

1 Like

Hi,

Yes, both v1 and v2 are supported. Even I have tested with v1, results are same.

I have tested the same in in my test setup by installing nginx . If I don’t set accep-proxy in second haproxy. I can see client ip in access log. If I set accept-proxy then connection won’t get established

What’s certainly wrong the configuration of the haproxy location B is the ssl directive in the backend. You are trying to transparently pass SSL towards your backend, so you need to remove ssl verify none from server halocb mysite.ul.com:443.

To be honest even I tried that . I left out of choice, only after that I posted it here . I have tried with AWS NLB in my setup but not chained though, it worked with both v1 and v2

Then retry everything from scratch, because if you made half the tests with the wrong configuration, half of your conclusions are wrong.

Use v1 and don’t use any “ssl” keywords at all. If it still doesn’t work, capture the traffic and analyze it.

Will do and let you know

Hi Lukas,

I have tried with V1 on HAproxy A and no ssl on HA Proxy B. I can just see only TCP Handlshake, no SSL handshake . If I use accept-proxy on HA Proxy B, it establishes SSL connection and transfers the data, but my server didn’t receive any proxy header which could give me client IP.

Can you share the capture between haproxy B and your backend?

Hi Lukas,

Thank you for assisting me. As per policy, I should not share capture. Could you please tell me where to look for proxy protocol header in capture when accept-proxy is set with some sample screenshot .

The interesting capture is without accept-proxy (and with send-proxy, not send-proxy-v2), because what we wanna know is why it fails. We already know why it works with accept-proxy.

So make a screenshot of the TCP payload between haproxy B and your java server, by selecting the TCP flow in wireshark and in the context menu click Follow --> TCP Stream, then set the data to Hex Dump and make a screenshot of that window.

Hi Lukas,

Attached the screenshot of accept-proxy and without accept-proxy. When we set accept-proxy, there is no protocol header from Location B. But I could see that when unsetting accept-proxy.

You can clearly see that in the case without accept-proxy, the PROXY protocol is preceding a real TLS client hello, therefor haproxy works correctly as configured.

That’s the evidence that your backend server is incorrectly implementing the PROXY protocol.

edit: maybe your implementation looks for the PROXY header after TLS instead of before?

1 Like

Hi Lukas,

Thank you for your reply. We have fixed the issue. Yes, I have accept-proxy and send-proxy on location B. The problem seems to be, the first packet from ha proxy has both proxy protocol and ssl handshake data. We were expecting proxy protocol come in first place and then handshake. We fixed our application to handle both scenarios, because we have another proxy which is sending proxy protocol first and then followed by ssl.

1 Like