strongSwan IKEv1/XAuth in FreeBSD vnet jail — SAD entry failure and kernel-libipsec not available in pkg

Background


I am building a VPN client manager where each VPN profile runs in its own isolated vnet jail on FreeBSD 15.0. The goal is to have parallel IKEv1/XAuth tunnels to FortiGate gateways, each fully isolated with its own network stack, with pf on the host doing NAT and port forwarding.


This post documents my findings after extensive testing. The problem summary and text were prepared with the assistance of Claude (Anthropic's AI assistant), based on actual debugging sessions.




Setup


  • FreeBSD 15.0-RELEASE-p9, GENERIC kernel (VIMAGE present)
  • strongSwan 6.0.6 from pkg
  • vnet jail with epair interface, default route via host epair
  • IKEv1 Aggressive Mode, XAuth PSK, connecting to FortiGate at 185.222.95.230
  • IKE phase 1 completes successfully, XAuth authentication passes



Problem 1: kernel-pfkey cannot install SAD entries from vnet jail


With the default pkg build (kernel-pfkey + kernel-pfroute), IKE phase 1 and XAuth complete successfully, but phase 2 fails:




<span><span>[KNL] unable to add SAD entry with SPI xxxxxxxx: Invalid argument (22)<br></span></span><span>[KNL] unable to add SAD entry with SPI xxxxxxxx: Invalid argument (22)<br></span><span>[IKE] unable to install inbound and outbound IPsec SA (SAD) in kernel</span>

The vnet jail has a fully isolated network stack. The pfkey socket inside the jail cannot reach the host kernel's IPsec SAD/SPD. This appears to be a fundamental limitation of vnet isolation — the jail's pfkey socket operates on the jail's vnet instance, which does not have IPsec SA support.




Problem 2: kernel-libipsec not compiled in pkg


The userland IPsec backend (kernel-libipsec) would bypass the kernel SAD issue entirely by handling encryption in userspace via TUN device. However, the FreeBSD port has KERNELLIBIPSEC=off by default, so the plugin is not present in the pkg binary:




<span><span>lib/ipsec/plugins/libstrongswan-kernel-libipsec.so → @comment (not installed)</span></span>

When manually compiled from ports with KERNELLIBIPSEC=on, charon fails with:




<span><span>[LIB] feature CUSTOM:libcharon in critical plugin 'charon' has unmet dependency: CUSTOM:kernel-ipsec<br></span></span><span>[DMN] initialization failed - aborting charon</span>

This happens because /dev/tun is not accessible inside the vnet jail by default.




Problem 3: /dev/tun not available in vnet jail


Even with a devfs ruleset that unhides tun*, it is unclear whether creating tun interfaces from within a vnet jail is supported or whether the TUN device would operate correctly with kernel-libipsec in this context. This combination appears to be untested and undocumented.




Questions


  1. Is there any supported path to run strongSwan (IKEv1 client) inside a FreeBSD vnet jail, where the jail handles its own IPsec tunnel end-to-end without touching the host IPsec stack?
  2. Would enabling KERNELLIBIPSEC=on in the default pkg build be appropriate, given that it is already the only viable option for jail and container environments?
  3. Is there a known devfs ruleset configuration that allows kernel-libipsec with TUN to work inside a vnet jail on FreeBSD 15?
  4. Would it make sense to add an allow.ipsec or similar jail parameter that grants a vnet jail access to its own isolated IPsec SAD/SPD, similar to how vnet grants an isolated network stack?



References


 
Back
Top