Project

General

Profile

kernel-libipsec plugin

The kernel-libipsec plugin provides an IPsec backend that works entirely in userland, using TUN devices and our own IPsec implementation libipsec (source:src/libipsec).

Both other kernel interfaces, kernel-netlink (the default) and kernel-pfkey, install IPsec SAs in the operating system's IPsec stack. This plugin provides an alternative, for instance, if the OS implementation does not support a required algorithm (e.g. AES-GCM on Mac OS X). However, it generally performs worse than the OS kernel's IPsec stack. In particular, when handling lots of SAs and/or lots of traffic, so it is not recommended to be used on security gateways.

To enable the plugin, add

--enable-kernel-libipsec
to the ./configure options.

A network kernel backend is still required, so either the kernel-netlink or the kernel-pfroute plugin has to be enabled too.

It is available since 5.1.0.

Behavior

With the plugin enabled a TUN device is created on startup that will be used to handle cleartext traffic from and to the host. For each IPsec SA routes get installed that direct traffic to the TUN device, from there the plugin reads the cleartext packets and encrypts them via libipsec. The resulting ESP packets will be sent over the UDP sockets the daemon uses for IKE traffic, which is why the plugin currently only works with UDP encapsulation (NAT-T) enabled. Encapsulated ESP packets that are received on the daemon's UDP socket are decrypted by libipsec and then injected via TUN device. libipsec can use all ciphers supported for IKE to encrypt and authenticate traffic.

Note that libipsec is not intended for scenarios with high amounts of traffic or high burst traffic. It is not optimized for performance and buffers each packet in memory. In combination with insufficient processor power, this will lead to a out of memory condition and a crash of charon or the whole device. SA and policy lookups are also not particularly optimized. See #964 for details.

On systems that use the kernel-pfroute plugin (FreeBSD, Mac OS X) a separate TUN device will be created for each virtual IP, on Linux this is not required.

Configuration

The plugin is configured using the following strongswan.conf options.

Key Default Description
charon.plugins.kernel-libipsec.allow_peer_ts no Allow that the remote traffic selector equals the IKE peer (see below for details)

Host-to-Host Tunnels

If the IKE peer is included in the remote traffic selector a separate route is installed that excepts such traffic from the route via TUN device to allow further IKE traffic between the peers (otherwise a routing loop would ensue). But if the remote traffic selector equals the IKE peer this won't work anymore, therefore, such traffic selectors are not allowed by default.

Since 5.1.1 it is possible to use such traffic selectors on newer Linux hosts by using fwmarks with the kernel-netlink and socket-default plugins. The libipsec/host2host-cert test scenario demonstrates this.

The relevant options in the strongswan.conf file are as follows:

charon {
    plugins {
        kernel-netlink {
            fwmark = !0x42
        }
        socket-default {
            fwmark = 0x42
        }
        kernel-libipsec {
            allow_peer_ts = yes
        }
    }
}

The first option configures the routing rule for strongSwan's own routing table in such a way that the routes in that table will only apply to packets that do not feature the configured fwmark (0x42 in the example above).

The second option forces an fwmark of 0x42 on all packets sent by the IKE daemon. This includes IKE packets but also the UDP encapsulated ESP packets that are sent over that socket. Such traffic is now not affected by the routes (via TUN device) installed by strongSwan in its own routing table.

The third option finally enables negotiation of host-to-host tunnels.

To make the Linux kernel actually consider the routes as required the net.ipv4.conf.all.rp_filter setting has to be set:

# sysctl -w net.ipv4.conf.all.rp_filter=2

Read the documentation about this settings to understand the impact.
It basically disables the rp_filter. You possibly need to alter your local firewall rules to plug a hole caused by changing the setting.