Configuring HAProxy with Virtual IPs

I would like to create a redundant HAProxy configuration with:

  • Keepalived - for determining which HA Proxy is active
  • HAProxy - for doing load balancing and failover

I will be using a cloud service provider and their VPSs

  • Each VPS has its own, public IP address
  • The provider has a “failover IP” that can be purchased

The issue I’ve encountered previously with using VRRP on a service level (as opposed to just a Layer 3 technology), is that the destination and reply IP addresses are different. For example, when I considered only using Keepalived for load-balancing and failover, I encountered the problem:

  • Clients would make a connection to the servers using the virtual failover IP
  • Responses from the server would be sent from the server’s physical IP address, and not from the virtual failover IP
  • The destination and response IP addresses would not match

Load-balancers, like HA Proxy, deal with this problem to an extent, by essentially NATing the traffic, such that the traffic from the servers appear to be sent to/from the Load-balancer’s IP address.

  • Instead of replies originating from the server’s physical IP address, the replies are NATed to the load-balancer’s IP address

However, I foresee the same problem, if I try to use a virtual failover IP with a pair of HA Proxys running keepalived. That is,

  • Traffic would be sent to the Virtual IP as the destination IP
  • Traffic response would be sent from the HA Proxy’s IP address, not from the Virtual IP

Does HA Proxy have a solution to this?
Can I configure HA Proxy to reply with the virtual IP?

Configure the virtual IP as an additional IP on eth0 or even better lo interface, and you can bind to it just normally.

You can also configure your kernel to allow binding to non-existing IPs and/or enable transparent mode on the bind line, if you don’t like the first simple option of adding the IP to an interface.

The important part is that absolutely must not configure any kind of iptables destination NAT, that is absolutely the wrong thing to do.

For keepalived, the floating IP is the incoming IP, the host IP’s are the outgoing IP’s. (works as designed)

This should just work without problems.
If you need Src IP and Dst IP to be the same, you may try the following.

firewall config (in context of keepalived):

  • On the firewall, you need an dNAT rule (=inbound) that translates an external IP to your floating IP.
  • For the sNAT rule (=outbound) you may configure a rule that all outbound traffic (from the subnet, or at least from floating IP, haproxy host1, haproxy host2) must translate to the floating IP’s external IP.
    In other words, outbound traffic from the individual HAProxy’s host IP’s would in this case use the floating IP’s external IP (using dNAT masquerading).

First of all, if we are talking about the same TCP connection, the kernel will respond with the same IP, not the physical IP.

Second of all, if we are talking about outgoing TCP connection, you have to instruct the application to bind to the proper IP address (in case of haproxy, that would be the source keyword).

Configuring workarounds with NAT is a terrible idea, please stop spreading this bad advice.