TTR Networks

Intermediate · Two Debian routers: VRRP and connection sync · section 2 of 9

VRRP with keepalived

✓ Lab-tested 4 November 2026 on Debian 13.7, keepalived 2.3.3, conntrackd 1.4.8, nftables 1.1.3, systemd 257

Debian installs keepalived enabled but inactive: with no configuration file, the service doesn't start. The configuration is almost the same on both routers; only the router ID and the priority differ.

  • vrrp_instance STAFF shares 10.10.10.1 on the staff VLAN, and vrrp_instance WAN shares 203.0.113.4 on the WAN. Each has a virtual router ID (10 and 20) that's the same on both routers, and must be unique on that network.
  • Priority: r1 has 150, r2 has 100, so r1 is the normal master. Both start as BACKUP and let the priorities decide.
  • advert_int 1: the master sends a VRRP advertisement every second. If the backup misses three, plus a short skew based on its priority, it takes over: about 3.6 seconds for r2.
  • vrrp_sync_group OFFICE ties the two instances together. Without it, a fault on one interface could leave the LAN address on one router and the WAN address on the other, and traffic would go in one door and find no way out.
  • vrrp_script isp_reachable is a health check; more on it later.

The firewall needs one more rule on each router: VRRP is IP protocol 112, and it must be allowed in on both interfaces, or each router thinks the other is dead.

After starting keepalived on both routers, r1's log shows both instances, synchronised, entering MASTER, and it now holds 10.10.10.1 and 203.0.113.4 alongside its own addresses. r2 enters BACKUP. The staff PC's default route points at 10.10.10.1, and traffic flows. On the staff VLAN, tcpdump shows r1's advertisements to the multicast address 224.0.0.18: virtual router 10, priority 150, every second.

The versions in this lab (real output)
root@r1:~# cat /etc/debian_version; dpkg-query -W keepalived conntrackd nftables; uname -r
13.7
conntrackd	1:1.4.8-2+b1
keepalived	1:2.3.3-1
nftables	1.1.3-1
7.0.14-linuxkit

root@r1:~# systemctl is-active keepalived conntrackd; ls /etc/keepalived/
inactive
active
keepalived.conf.sample
keepalived.config-opts
  • Lines 3–5: keepalived, conntrackd and nftables from Debian 13.
  • Lines 8–10: keepalived is installed but inactive: there's no configuration yet. conntrackd runs in its default statistics mode.
/etc/keepalived/keepalived.conf on r1
# /etc/keepalived/keepalived.conf on r1
global_defs {
    router_id r1
    enable_script_security
    script_user root
}

# Is the ISP reachable from here? Two failed pings in a row and this router steps down.
vrrp_script isp_reachable {
    script "/usr/bin/ping -c 1 -W 1 203.0.113.1"
    interval 2
    fall 2
    rise 2
}

# Both addresses move together: a router that holds one must hold the other.
vrrp_sync_group OFFICE {
    group {
        STAFF
        WAN
    }
}

vrrp_instance STAFF {
    state BACKUP
    interface staff
    virtual_router_id 10
    priority 150
    advert_int 1
    virtual_ipaddress {
        10.10.10.1/24
    }
    track_script {
        isp_reachable
    }
}

vrrp_instance WAN {
    state BACKUP
    interface eth0
    virtual_router_id 20
    priority 150
    advert_int 1
    virtual_ipaddress {
        203.0.113.4/24
    }
}
  • Line 3: The only differences on r2: its name and its priority (100).
  • Lines 9–14: A health check: can this router reach the ISP?
  • Lines 17–22: Both addresses move together.
  • Lines 24–36: The staff gateway, 10.10.10.1, on VLAN 10, with the health check attached.
  • Lines 38–47: The shared public address, 203.0.113.4.
Starting both routers (real output)
root@r1:~# cp keepalived.conf /etc/keepalived/ && systemctl restart keepalived

root@r2:~# cp keepalived.conf /etc/keepalived/ && systemctl restart keepalived

root@r1:~# journalctl -u keepalived --no-pager -o cat | grep -E "STATE|Syncing"; ip -br -4 addr show dev staff; ip -br -4 addr show dev eth0
(STAFF) Entering BACKUP STATE
VRRP_Group(OFFICE) Syncing instances to BACKUP state
(WAN) Entering BACKUP STATE
(WAN) Entering MASTER STATE
VRRP_Group(OFFICE) Syncing instances to MASTER state
(STAFF) Entering MASTER STATE
staff@eth1       UP             10.10.10.2/24 10.10.10.1/24 
eth0@if5551      UP             203.0.113.2/24 203.0.113.4/24 

root@r2:~# journalctl -u keepalived --no-pager -o cat | grep -E "STATE|Syncing"; ip -br -4 addr show dev staff; ip -br -4 addr show dev eth0
(STAFF) Entering BACKUP STATE
VRRP_Group(OFFICE) Syncing instances to BACKUP state
(WAN) Entering BACKUP STATE
staff@eth1       UP             10.10.10.3/24 
eth0@if5556      UP             203.0.113.3/24 

root@staff:~# ip route; ping -c 2 -W 1 198.51.100.10 | tail -2
default via 10.10.10.1 dev eth0.10 
10.10.10.0/24 dev eth0.10 proto kernel scope link src 10.10.10.20 
2 packets transmitted, 2 received, 0% packet loss, time 1060ms
rtt min/avg/max/mdev = 0.116/0.152/0.188/0.036 ms

root@r1:~# tcpdump -lnni staff -c 2 vrrp 2>/dev/null
22:47:21.253436 IP 10.10.10.2 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 150, authtype none, intvl 1s, length 20
22:47:21.253443 IP 10.10.10.2 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 150, authtype none, intvl 1s, length 20
  • Lines 6–11: r1: both instances synchronised to MASTER.
  • Lines 12–13: r1 now holds 10.10.10.1 and 203.0.113.4 as well as its own addresses.
  • Lines 16–20: r2: BACKUP, own addresses only.
  • Lines 22–26: The staff PC's gateway is the shared address, and traffic flows.
  • Lines 28–30: r1's advertisements: virtual router 10, priority 150, every second.

Check your understanding

Why do the two instances sit in one vrrp_sync_group?

  • So the LAN and WAN addresses are always on the same router; otherwise traffic could go in one router and find no way out.
  • Because keepalived only allows one instance per router.
  • To share the connection table.
  • To make the routers share a priority.