Hi, I have a question regarding source port selection when using haproxy in tcp mode.
We are using haproxy with the following scenario: | public haproxy with tcpmode | -> | PNAT Fortigate FW | -> | internal Host | The Fortigate is reachable via two ISPs (ISP-A, ISP-B) and has port forwards (NAT) to an internal host. The haproxy backend configuration contains both public IPs assigned to the Fortigate FW, enabling a distribution of the connections on both ISP connections (haproxy config appended). In this scenario we are getting "session clash" messages on the Fortigate FW. A session clash message indicates, that the tuple of <source ip, source port, dest ip, dest port> for tcp connection tracking (sessions in the Fortigate world) is reused, before the previous session was closed. >From the Fortigate knowledgebase, the tupel is calculated from [HAPROXY-IP]:49660 and [INTERNAL-HOST-IP]:443 (Ports used from the example message appended, where 49660 is the haproxy client ip port) The message shows, that haproxy created a session / tcp connection using the ISP-B-IP and then created a new connection using the ISP-A-IP using the same client-ip-port as in the previous connection. This leads to unexpected behaviour (e.g. packet drop) and I want to get rid of these messages (and behaviour). Therefore it might be necessary to understand how haproxy chooses the client-ip-port when creating new tcp connections to backend servers. Especially how haproxy behaves when a connection attempt fails and a retry is triggered because this retry might change the backend server. Will the retry use the same client port? If yes, is this intended? Best regards, Jack Additional infos: =================== - Connection / session creation rate is low at around 3/s with peaks of 25/s. - connection duration is low - peak total concurrent connections is around 600 haproxy.cfg: ============== global maxconn 10000 log stdout format raw daemon notice defaults log global mode tcp retries 2 timeout client 120s timeout connect 4s timeout server 120s timeout check 5s option tcpka option tcplog option logasap balance leastconn frontend tcp_443_frontend_with_proxy_protocol mode tcp bind *:443 accept-proxy maxconn $MAX_CONN default_backend tcp_443_backend backend tcp_443_backend mode tcp fullconn $MAX_CONN option tcp-check default-server init-addr libc,last,none server ip1_port1 [ISP-A-IP]:443 send-proxy maxconn $MAX_CONN check inter 1s server ip2_port1 [ISP-B-IP]:443 send-proxy maxconn $MAX_CONN check inter 1s Example message (the actual IP addresses have been replaced by placeholders): =============================================================================== New Status [HAPROXY-IP]:49660->[ISP-A-IP]:443([INTERNAL-HOST-IP]:443) dir=0 act=1 hook=4 [HAPROXY-IP]:49660->[INTERNAL-HOST-IP]:443([INTERNAL-FW-IP]:22686) dir=1 act=2 hook=0 [INTERNAL-HOST-IP]:443->[INTERNAL-FW-IP]:22686([HAPROXY-IP]:49660) dir=1 act=1 hook=4 [INTERNAL-HOST-IP]:443->[HAPROXY-IP]:49660([ISP-A-IP]:443) Old Status [HAPROXY-IP]:49660->[ISP-B-IP]:443([INTERNAL-HOST-IP]:443) dir=0 act=1 hook=4 [HAPROXY-IP]:49660->[INTERNAL-HOST-IP]:443([INTERNAL-FW-IP]:49660) dir=1 act=2 hook=0 [INTERNAL-HOST-IP]:443->[INTERNAL-FW-IP]:49660([HAPROXY-IP]:49660) dir=1 act=1 hook=4 [INTERNAL-HOST-IP]:443->[HAPROXY-IP]:49660([ISP-B-IP]:443)