This page looks best with JavaScript enabled

High availability VIP using CARP on FreeBSD

 ·  🎃 kr0m

In high availability environments, the use of floating IPs is essential. These are characterized by being able to migrate from one server to another transparently, thus continuing to provide service in case of failure of one of the servers.

This time we will use CARP , which is the implementation of VRRP by the OpenBSD team. The code is fully integrated into FreeBSD, so all configuration will be done using the system’s own tools without the need to install any additional packages.

To show the operation of CARP, we will have two servers, each with its own independent IP, sharing a VIP between them:

  • VIP: 192.168.69.40
  • PeanutBrain01: 192.168.69.41
  • PeanutBrain02: 192.168.69.42

We load the carp module on both servers:

kldload carp

We tell the operating system to load it at startup:

vi /boot/loader.conf

carp_load="YES"

If we are using a custom kernel , we will have to enable the following option in its compilation:

device carp

In CARP, there are two roles: MASTER/BACKUP. This role is decided based on the weight assigned in the configuration, with the server with the lowest weight being the MASTER.

In my case, I am going to assign the following weights:

MASTER: PeanutBrain01 -> advskew 0 (default)
BACKUP: PeanutBrain02 -> advskew 100

We perform the configuration on PeanutBrain01:

vi /etc/rc.conf

ifconfig_em0_alias0="inet vhid 1 pass testpass alias 192.168.69.40/32"

We perform the configuration on PeanutBrain02:

vi /etc/rc.conf

ifconfig_em0_alias0="inet vhid 1 advskew 100 pass testpass alias 192.168.69.40/24"

We restart the network on both servers:

service netif restart
service routing restart

We can see an additional IP in each server’s ifconfig output, indicating the VIP role and weight.

PeanutBrain01:

root@PeanutBrain01:~ # ifconfig em0
em0: flags=8963<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=481009b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,VLAN_HWFILTER,NOMAP>
	ether 08:00:27:42:4c:a5
	inet 192.168.69.41 netmask 0xffffff00 broadcast 192.168.69.255
	inet 192.168.69.40 netmask 0xffffff00 broadcast 192.168.69.40 vhid 1
	carp: MASTER vhid 1 advbase 1 advskew 0
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

PeanutBrain02:

root@PeanutBrain02:~ # ifconfig em0
em0: flags=8963<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=481009b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,VLAN_HWFILTER,NOMAP>
	ether 08:00:27:37:5f:f2
	inet 192.168.69.42 netmask 0xffffff00 broadcast 192.168.69.255
	inet 192.168.69.40 netmask 0xffffff00 broadcast 192.168.69.40 vhid 1
	carp: BACKUP vhid 1 advbase 1 advskew 100
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

The easiest way to check which server has the VIP is to listen on a socket using netcat . Depending on which server has the VIP active at that moment, we will see the output on one server or the other.

We install netcat on both servers:

pkg install netcat

Now we listen on the socket on both servers:

nc -l 7777

From our PC, we make a connection to the VIP:

nc 192.168.69.40 7777

We can see how PeanutBrain01 receives the connection:

Garrus $ ~> nc 192.168.69.40 7777
111111
root@PeanutBrain01:~ # nc -l 7777
111111

If we restart PeanutBrain01, we will see in PeanutBrain02 that it is now MASTER:

root@PeanutBrain02:~ # ifconfig em0
em0: flags=8963<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=481009b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,VLAN_HWFILTER,NOMAP>
	ether 08:00:27:37:5f:f2
	inet 192.168.69.42 netmask 0xffffff00 broadcast 192.168.69.255
	inet 192.168.69.40 netmask 0xffffff00 broadcast 192.168.69.40 vhid 1
	carp: MASTER vhid 1 advbase 1 advskew 100
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

If we make the connection again, it is received by PeanutBrain02:

Garrus $ ~> nc 192.168.69.40 7777
222222
root@PeanutBrain02:~ # nc -l 7777
222222

We must keep in mind that if the BACKUP takes the VIP, it will NOT return to the MASTER when it recovers. If we want this to happen automatically, we will have to enable the sysctl parameter net.inet.carp.preempt on both servers:

sysctl net.inet.carp.preempt=1

If we want to make it permanent:

vi /etc/sysctl.conf

net.inet.carp.preempt=1

We can also force the manual change by running on the BACKUP server:

ifconfig em0 vhid 1 state backup

If you liked the article, you can treat me to a RedBull here