Skip to main content
RunBook Academy

OPNsenseXXVII · CARPCARP configuration

CARP virtual IP configuration on OPNsense — the GUI, the ifconfig, and the packet flow

Intermediate⏱ ~15 minifconfigtcpdumpconfigctlpfctl

What you'll learn

  • Configure a CARP virtual IP in OPNsense with all required fields
  • Map each GUI field to a kernel state (interface, VHID, password, skew, interval)
  • Trace the path of a packet from the wire to the application when the local node is master
  • Trace the path when the local node is backup and the packet is destined for the VIP
  • Verify the configuration with ifconfig and tcpdump

Prerequisites

Verified against OPNsense 25.x · FreeBSD 14.x · PF (FreeBSD packet filter) FreeBSD 14.x · Unbound 1.20+ · Kea DHCP OPNsense 25.x plugin · WireGuard in-kernel + OPNsense plugin · strongSwan (IPsec plugin) OPNsense 25.x plugin · OpenVPN 2.6.x · Suricata 7.x · 2026-08-14

Not yet marked complete on this device.

The OPNsense GUI exposes CARP through two pages: Interfaces → Virtual IPs → Add for the virtual IP itself, and System → High Availability → Settings for the CARP daemon, the sync interface, and the synchronisation password. The VIP page is where most of the operational decisions live — VHID, advertising interface, password, skew, frequency. The HA settings page is where the sync (pfsync) interface is named and the XMLRPC remote is configured.

This lesson walks the configuration, maps each GUI field to the kernel state it produces, and traces how a packet flows through the master (and through the backup when the local node is not the master). The lesson is intentionally concrete — the goal is that an operator who has read the lesson can configure a CARP VIP from the GUI and predict what ifconfig will show.

The GUI fields

To add a CARP VIP: Interfaces → Virtual IPs → Add. The form asks for:

  • ModeCARP. (Other modes are IP Alias, Proxy ARP, Other. CARP is the only one that participates in HA.)
  • Interface — the OPNsense interface the VIP will advertise on. Conventionally the LAN, the WAN, or a DMZ. The interface must be up and have a physical IP.
  • IP address — the shared IP. Must be in the same subnet as the interface’s physical IP.
  • VHID — the Virtual Host ID, 1 to 255. Each VHID on a segment must be unique.
  • Password — the CARP authentication password, 1 to 20 characters. Must match exactly on the secondary.
  • Advertising frequency — the base advertisement interval. Default 1 (one second). The OPNsense GUI exposes this as a base; the skew is a separate field.
  • Skew — the base advertisement skew. Default 0 on the primary, 100 on the secondary.
  • Description — free text. Use something that identifies the role and the segment, e.g. lan-vip-primary.

The OPNsense convention is to enable forcible failover by setting the primary’s skew to 0 and the secondary’s skew to 100. Some operators use 10 and 100 to give the primary a small preference while leaving room for the secondary to demote (tie-breaking without a demote gets ugly).

The CARP password is set on the HA settings page, not the VIP page. The password is per-segment, not per-VIP — the same password authenticates every CARP advertisement on the same network. Operators who run multiple CARP segments (LAN, WAN, DMZ) use the same password on each segment, or different passwords if they want to prevent accidental cross-segment authentication.

Read-only / Safeifconfig igb0
$ ifconfig igb0
igb0: flags=8963<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
      ether aa:bb:cc:11:22:44
      inet 192.0.2.2 netmask 0xffffff00 broadcast 192.0.2.255
      inet 192.0.2.1 netmask 0xffffff00 broadcast 192.0.2.255 vhid 1
      media: Ethernet autoselect (1000baseT <full-duplex>)
      status: active
      carp: MASTER vhid 1 advbase 1 advskew 0

Illustrative output

Mapping the GUI to the kernel

Each GUI field has a corresponding kernel state. The OPNsense configuration is stored in config.xml under <virtualip> and <hasync>. The configctl interface list shows the live state:

GUI fieldconfig.xmlKernel state
Mode = CARP<mode>carp</mode>CARP enabled for this address
Interface<interface>lan</interface>the VHID is attached to that parent interface
IP address<ipaddr>192.0.2.1/24</ipaddr>inet alias on the parent, tagged with the vhid
VHID<vhid>1</vhid>vhid in the carp: line
Password<password>p4ssw0rd</password>HMAC key for the VHID
Frequency<advbase>1</advbase>advbase in the carp: line
Skew<advskew>0</advskew>advskew in the carp: line

The ifconfig igb0 output above shows the kernel state produced by the GUI configuration. The mapping is direct — the operator who can read ifconfig can tell whether the GUI took the configuration correctly.

Packet flow when the local node is master

When the local node is the master for a VHID, the kernel is the owner of the VIP. The packet flow for an inbound frame addressed to the VIP’s MAC is:

  1. Frame arrives on the physical interface. The NIC driver delivers the frame to the kernel. The destination MAC is the CARP multicast MAC 01:00:5e:00:00:12 (for advertisements) or the VIP’s MAC (for data frames, which is the master’s MAC).
  2. Kernel decapsulates the frame. The IP packet is handed to the IP layer. The destination IP is the VIP.
  3. IP routing decision. The local routing table matches the destination IP to the local carp interface. The kernel marks the packet as IFF_LOCAL — destined for the local host.
  4. PF input. PF sees the packet as INPUT on the carp interface. The rule set is evaluated. If the rule allows the traffic, the packet is passed.
  5. Local delivery. The kernel delivers the packet to the listening socket. For an inbound TCP connection, the socket is the daemon bound to the VIP (e.g. the OPNsense webGUI on port 443, if configured to listen on the VIP).

The master’s MAC for the VIP is the physical MAC of the master, or the CARP virtual MAC if the operator has configured it. The CARP virtual MAC is computed from the VHID — 00:00:5e:00:01:XX where XX is the VHID in hex. Using the virtual MAC has the advantage that the switches do not need to update their MAC tables when failover happens — the new master’s interface MAC is the same as the old master’s. The disadvantage is that some switches (especially older firmware) have buggy MAC tables for the uncommon OUI 00:00:5e.

Read-only / Safetcpdump inbound VIP
$ tcpdump -nn -i igb0 'host 192.0.2.1'
12:34:56.789012 198.51.100.50.51820 > 192.0.2.1.443: Flags [S], seq 100, win 64240, length 0
12:34:56.789234 192.0.2.1.443 > 198.51.100.50.51820: Flags [S.], seq 200, ack 101, win 64240, length 0

Illustrative output

Packet flow when the local node is backup

When the local node is backup, the kernel is not the owner of the VIP. The packet flow for the same inbound frame is:

  1. Frame arrives on the physical interface. Same as the master.
  2. Kernel decapsulates the frame. Same as the master.
  3. IP routing decision. The local routing table matches the destination IP to the VIP alias on the parent interface. But the kernel sees that the local node is not the master for this VHID — the carp subsystem is in BACKUP state.
  4. Packet is dropped at the carp layer. The kernel discards the packet before PF sees it. The packet is not delivered to the local socket. PF does not log it.
  5. No reply. The client that sent the SYN does not receive a SYN-ACK. The client’s kernel retransmits the SYN (per the TCP retransmission algorithm). If the master is healthy, the client never sees this — the SYN reaches the master via the LAN, the master replies, and the connection establishes.

The backup’s role is to discard the packets silently. If the backup processed the packets and forwarded them, the network would have two active firewalls processing the same traffic, and the LAN would see inconsistent state. The backup is an observer, not a forwarder.

Summary

  • The OPNsense CARP VIP is configured under Interfaces → Virtual IPs → Add with mode CARP, the interface, the IP, the VHID, the password, the advertising frequency, and the skew.
  • Each GUI field maps directly to kernel state on the VIP’s parent interface. ifconfig <parent> is the source of truth; there is no carp0 device to query.
  • The master is the destination for VIP-bound traffic. The backup discards the traffic at the carp layer, before PF sees it.
  • A backup that processes VIP traffic is a split-brain — the worst-case HA failure. Verify the kernel state, not the GUI, after every change.

Knowledge check · 4 questions

  1. Q1. Where in OPNsense is the CARP virtual IP configured?

  2. Q2. A CARP backup node discards packets destined for the VIP at the carp layer, before PF sees them.

  3. Q3. Which of the following are valid ways to verify the CARP configuration after a change? Select all that apply.

  4. Q4. A firewall has the CARP VIP `192.0.2.1/24` on interface `lan`. The operator runs `ifconfig` on the LAN parent interface and sees `carp: BACKUP vhid 1`. A client at `198.51.100.50` sends a TCP SYN to `192.0.2.1:443`. What happens?

Passing score: 75%. Answers are checked in this browser.