Skip to content
FreeBSDDeep Dive Published Updated 6 min readViews unavailable

FreeBSD if_ipsec(4): Route-Based IPsec Without VTI Assumptions

Configure and verify FreeBSD's if_ipsec virtual tunneling interface while keeping routes, ESP policies, reqids, and peer behavior distinct.

FreeBSD’s if_ipsec is a virtual tunneling interface intended for route-based VPNs. The useful distinction is that the routing table selects the interface for inner traffic, while IPsec security policies and security associations still determine whether ESP protects that traffic. A route is not a substitute for a matching policy, negotiated association, or reachable outer endpoint.

The current FreeBSD 15.1 manual describes if_ipsec as tunneling IPv4 or IPv6 over either IPv4 or IPv6, secured with ESP. It also documents a reqid value that distinguishes policies for multiple interfaces. Treat those as the implementation’s explicit contract; do not assume that a FreeBSD interface called ipsec0 has all the policy or interface-ID behavior of a Linux XFRM interface, a vendor VTI, or a gif(4) tunnel.

First confirm that the running kernel includes the feature: FreeBSD documents options IPSEC for a built-in interface, or options IPSEC_SUPPORT when loading it through the IPsec kernel module. A missing interface is not necessarily a route or IKE configuration failure.

Separate the outer path from the inner route

An if_ipsec setup has two address layers:

  • The tunnel endpoint addresses are used in the outer IP header carrying ESP. They must remain reachable through the ordinary underlay route, even when the protected route is installed.
  • The interface’s inner addresses and the routes through ipsec0 describe traffic sent into the tunnel. A route-based design can steer only selected remote prefixes rather than changing the host’s default route.

Before changing a live routing table, record the existing route to each peer’s public endpoint and the return path for management access. Use an isolated pair of FreeBSD hosts or a disposable jail/network lab for a first configuration. The following shows the interface layer only; it deliberately does not install keys, choose a cryptographic suite, or change a production route:

# Documentation-only addresses: replace them in an isolated lab.
ifconfig ipsec0 create reqid 100
ifconfig ipsec0 inet tunnel 192.0.2.10 198.51.100.20
ifconfig ipsec0 inet 10.44.0.1/30 10.44.0.2

The if_ipsec(4) manual documents ifconfig ... create, the outer inet tunnel endpoints, and separate inner interface addresses. For a real deployment, configure a supported IKE daemon or deliberately managed manual security associations, then install only the destination routes the peer is authorized to carry. The kernel implements the IPsec policy/SA machinery, but the FreeBSD ipsec(4) manual says that dynamic IKE key exchange is provided by a user-space daemon, not by the kernel itself.

In a lab with the peer and policies already configured, a narrow route can be added through the point-to-point interface:

# Lab-only example; this changes the active routing table.
route add -net 10.60.0.0/16 ipsec0
route -n get 10.60.1.25

The manual’s route-based model requires both configuring the interface and modifying the routing table. Confirm that the peer has a reciprocal route and compatible selectors/SA. The documented examples use different reqid values on their two hosts (100 and 200); on each host, the local interface’s value must match the identifier in that host’s security-policy entry. Changing a reqid creates new policies and may require new associations, so treat it as a coordinated change rather than a harmless label edit.

Do not collapse route, policy, and encryption into one claim

The route answers “which interface should carry this destination?” The IPsec policy answers “which packets require or use IPsec?” The SA supplies negotiated keys, algorithms, sequence state, and peer information. These are related but separate checks. An installed route does not prove an SA exists, and a healthy IKE session does not prove the desired destination is actually routed through ipsec0.

Likewise, do not copy if_ipsec configuration as if it were generic “VTI syntax.” The FreeBSD manual calls this a virtual tunneling interface and exposes reqid; it does not define Linux XFRM if_id semantics or promise that other vendors use matching traffic selectors. Compare the peer’s actual IPsec implementation and policy model, then verify both directions with a lab flow before widening prefixes.

Verify the route and the security state separately

Start with read-only observations on the target version:

ifconfig ipsec0
netstat -rn -f inet
route -n get 10.60.1.25
setkey -D
setkey -DP

Use the installed setkey(8) manual for the exact SA and policy display supported by the system. Check the interface’s reqid, outer endpoints, route selection, policy selectors, and negotiated inbound and outbound ESP associations. Test a known, authorized inner address from each peer; an interface being UP is not proof of end-to-end protection.

For an IPv4 outer path, a bounded capture on the physical underlay can confirm native ESP packets (IP protocol 50):

tcpdump -ni em0 'ip proto 50'

That filter does not match ESP encapsulated in UDP for NAT traversal. If the peers negotiated NAT-T, include UDP/4500 in a bounded capture; that port can also carry IKE and NAT keepalives, so its presence alone does not prove that ESP data is flowing:

tcpdump -ni em0 'ip proto 50 or udp port 4500'

RFC 3947 describes NAT-Traversal negotiation and the move to UDP/4500 after NAT is detected; RFC 3948 defines UDP encapsulation of ESP on the IKE ports. UDP/4500 can also carry IKE and NAT keepalives, so seeing it is not proof that ESP data is flowing. These captures are evidence of outer traffic, not proof that the intended inner flow was selected or that the remote application is healthy. Do not capture or publish secrets, and do not infer inner packet contents from an encrypted outer capture. If a firewall must inspect inner tunnel traffic, consult the firewall and ipsec(4) documentation for the chosen interface path; do not change global filtering sysctls as an exploratory fix.

Stage route changes with a rollback path

Use a dedicated remote console or out-of-band access before modifying routes on a remote firewall, gateway, or host. Add one narrow test prefix, confirm that the public peer endpoint still resolves through the underlay, test both directions, and preserve a command or configuration rollback that restores the previous route. Avoid replacing a default route until the endpoint-exclusion route and management recovery have been proven. Persistent configuration belongs in the site’s existing network-management system, not an undocumented one-off shell command.

The operational model stays clear when the evidence is recorded in three columns: interface and endpoints; routes and prefixes; policies and live SAs. When one fails, diagnose that layer instead of repeatedly changing all three.

Related:

Sources:

Comments