Running strongSwan in Network Namespaces on Linux

Normally, the network stack (interfaces, routing tables, firewall rules etc.) is shared by all processes running on an operating system. With Linux network namespaces (netns) it's possible to have multiple separate instances of the network stack.

Note: While basic support for network namespaces was added to the Linux kernel a long time ago some features (e.g. CLUSTERIP support) might require a recent kernel.

The easiest way to work with network namespaces is to use the ip command of the iproute2 package. These commands will have to be executed as root (i.e. with sudo on most distros).

Network Namespace Basics

To create a new netns use the following command:

# ip netns add <network namespace name>

A list of all currently defined netns is provided by ip netns list.

Interfaces can be assigned to a netns with the ip link command:

# ip link set <interface name> netns <netns name>

If you run ip link list afterwards such an interface won't be seen as it is only available in the configured netns.

So to actually list the interface in a specific netns it's required to be able to run commands in a specific netns. This can be done with the ip netns exec command. So to get a list of interfaces defined in a specific netns use:

# ip netns exec <netns name> ip link list

If only one physical interface is available, or if you don't want to assign physical interfaces to the netns for other reasons, it's possible to create virtual Ethernet interface pairs (veth, provided via CONFIG_VETH). These are like a bi-directional pipe (i.e. what's written to one end comes out the other and vice-versa) of which one end is placed inside the netns and the other stays outside in the "default" or "global" namespace.

To create such a pair use:

# ip link add <interface name 1> type veth peer name <interface name 2>

This creates two connected Enthernet interfaces with the given names. One is assigned to a netns (via ip link) the other is not (it doesn't matter which one and it's also possible to assign both interfaces to two different netns to connect them). How the outer interface is used depends on the use case, it may be put inside a bridge, or used in routing rules to route traffic to and from a netns.

Since interfaces assigned to a netns are disabled they have to be enabled first, and they will probably also require an IP address, which can be done with:

# ip netns exec <netns name> ip addr add x.x.x.x/x dev <iface name>
# ip netns exec <netns name> ip link set dev <iface name> up

Similar to these commands routes or firewall rules may be added by running ip route or iptables inside a specific netns via ip netns exec <command>.

Running strongSwan Inside a Network Namespace

Running a single instance of strongSwan inside a netns is straight-forward. Simply run ipsec commands via ip netns exec ipsec <command>.

But more interesting is probably running multiple instances of strongSwan in separate namespaces. Because all netns share the same file system this is a bit tricky.

Luckily, the ip netns exec command provides a helpful feature: Every file found in /etc/netns/<name>/ for a given netns is bind mounted over its corresponding counterpart in /etc (so it has to exist there). This can be used to provide different config files for each instance, but may also be used to redirect the so called piddir, where the charon and starter daemons create their PID files and UNIX sockets (the default is to use /var/run, which would conflict if multiple instances would use it).

To do so make sure strongSwan is configured with --sysconfdir=/etc and e.g. --with-piddir=/etc/ipsec.d/run. Then after building and installing strongSwan the piddirs can be created as follows:

# mkdir -p /etc/ipsec.d/run
# mkdir -p /etc/netns/<netns name 1>/ipsec.d/run
# mkdir -p /etc/netns/<netns name 2>/ipsec.d/run

For config files that differ between netns a modified copy of the original may be placed in /etc/netns/<name>/ or a subdirectory.