Awesome Open Source
Awesome Open Source

IKEv2 VPN (Strongswan) Server @ Docker

A Docker image to help deploy Strongswan-based IKEv2 VPN on an own server.

By default, the minimum configuration is CNSA Suite compliant.


Run a container with the --privileged flag:

docker run -d --privileged --name ikev2-vpn --restart=always \
    -p 500:500/udp \
    -p 4500:4500/udp \

Or, it’s always possible to run it only with the NET_ADMIN capability:

docker run -d --name ikev2-vpn --restart=always \
    --cap-add net_admin \
    -p 500:500/udp \
    -p 4500:4500/udp \

Note: In this case, related kernel parameters setup required before.

Shared secret

To get a shared secret only, use the following:

docker run -it --rm --volumes-from ikev2-vpn \
    aeron/ikev2-strongswan-vpn:latest \

Optionally, it’s possible to save/restore a shared secret by mounting the /etc/ipsec.secrets file.

Device Management Profile

To generate a .mobileconfig file for macOS/iOS, run the following:

docker run -it --rm --volumes-from ikev2-vpn \
    -e \
    aeron/ikev2-strongswan-vpn:latest \
    profile > ikev2-vpn.mobileconfig

Replace the with the desired domain name; an IP address may be used instead as well.

Then copy this ikev2-vpn.mobileconfig file on a machine and install it by double-click, or transfer it on an iOS device via AirDrop.

If there’s a need to identify different clients, then LOCAL_ID value could be supplied:

docker run -it --rm --volumes-from ikev2-vpn \
    -e \
    -e \
    aeron/ikev2-strongswan-vpn:latest \
    profile > ikev2-vpn.mobileconfig

Usually, the LOCAL_ID should be an IP address, FQDN, UserFQDN, or ASN1DN, but a simple name suits as well.


Kernel Parameters

If a container was never run in privileged mode and such an approach is undesirable, then run the following first:

sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv6.conf.eth0.proxy_ndp=1

Kernel Modules

Running container logs may contain something similar to this:

ip6tables-restore: unable to initialize table 'nat'

Probably, Docker doesn’t load a proper kernel module for IPv6 NAT, so it’ll be necessary to run modprobe first:

sudo modprobe ip6table_nat

Or simply put a config in /lib/modules-load.d/ permanently, like so:

echo ip6table_nat | sudo tee /lib/modules-load.d/ip6table-nat.conf

IPv6 Support

Docker has IPv6 support out-of-the-box, but it needs to be enabled manually in daemon configuration and a network created afterward. More on this in the official Docker documentation.

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
Shell (229,269
Docker (34,491
Vpn (1,106
Strongswan (45
Ikev2 (27
Ipv6 Support (24
Mobileconfig (12
Related Projects