IPsec VPN with strongSwan on Linux

IPsec is the standard suite of protocols for network-layer encryption, built into every major operating system and most enterprise routers and firewalls. strongSwan is the leading open-source IKE daemon for Linux, supporting IKEv1, IKEv2, certificate and PSK authentication, and both site-to-site and road-warrior (remote access) topologies.

This guide covers installation, IKEv2 configuration with certificate authentication, site-to-site tunnels, and road-warrior setups with virtual IP pools.

Part of the VPN and SSH guide series. See also: WireGuard Setup | OpenVPN Guide | VPN Protocol Comparison


Installation

# Debian / Ubuntu
sudo apt update
sudo apt install strongswan strongswan-pki libcharon-extra-plugins

# RHEL / Fedora
sudo dnf install strongswan

Verify:

ipsec version
# strongSwan 5.x ...

PKI: Generating Certificates

strongSwan includes pki for certificate management. Create a self-signed CA and server certificate:

# Create directories
mkdir -p ~/pki/{cacerts,certs,private}
chmod 700 ~/pki

# CA private key and self-signed certificate
pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/ca-key.pem
pki --self --ca --lifetime 3650 --in ~/pki/private/ca-key.pem \
    --type rsa --dn "CN=VPN Root CA" --outform pem > ~/pki/cacerts/ca-cert.pem

# Server key and certificate signed by the CA
pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/server-key.pem
pki --pub --in ~/pki/private/server-key.pem --type rsa |
    pki --issue --lifetime 1825 \
        --cacert ~/pki/cacerts/ca-cert.pem \
        --cakey  ~/pki/private/ca-key.pem \
        --dn "CN=vpn.example.com" \
        --san vpn.example.com \
        --flag serverAuth --flag ikeIntermediate \
        --outform pem > ~/pki/certs/server-cert.pem

Copy to strongSwan directories:

sudo cp ~/pki/cacerts/ca-cert.pem    /etc/ipsec.d/cacerts/
sudo cp ~/pki/certs/server-cert.pem  /etc/ipsec.d/certs/
sudo cp ~/pki/private/server-key.pem /etc/ipsec.d/private/

Client certificate

pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/client1-key.pem
pki --pub --in ~/pki/private/client1-key.pem --type rsa |
    pki --issue --lifetime 1825 \
        --cacert ~/pki/cacerts/ca-cert.pem \
        --cakey  ~/pki/private/ca-key.pem \
        --dn "[email protected]" \
        --san [email protected] \
        --outform pem > ~/pki/certs/client1-cert.pem

Core Configuration: ipsec.conf

Create /etc/ipsec.conf:

config setup
    charondebug="ike 2, knl 2, cfg 2"
    uniqueids=no

conn %default
    ikelifetime=60m
    keylife=20m
    rekeymargin=3m
    keyingtries=1
    keyexchange=ikev2
    authby=pubkey

# ── Site-to-site tunnel ──────────────────────────
conn site-to-site
    left=%defaultroute
    leftcert=server-cert.pem
    leftsubnet=10.1.0.0/24
    [email protected]
    right=203.0.113.50
    rightsubnet=10.2.0.0/24
    [email protected]
    auto=start

# ── Road-warrior (remote access) ─────────────────
conn roadwarrior
    left=%defaultroute
    leftcert=server-cert.pem
    leftsubnet=0.0.0.0/0
    [email protected]
    right=%any
    rightauth=pubkey
    rightsourceip=10.10.10.0/24
    rightdns=1.1.1.1,9.9.9.9
    auto=add

Directive reference

Directive Meaning
left / right Local / remote endpoint. %defaultroute auto-detects.
leftcert Certificate file (looked up in /etc/ipsec.d/certs/).
leftsubnet Traffic selectors -- which subnets sit behind this endpoint.
rightsourceip Virtual IP pool for road-warrior clients.
auto=start Initiate the tunnel at startup.
auto=add Load the connection but wait for the remote side to initiate.

Secrets: ipsec.secrets

For certificate-based auth, point to the private key:

# /etc/ipsec.secrets
: RSA server-key.pem

For PSK (pre-shared key) authentication instead:

# /etc/ipsec.secrets
@vpn.example.com @remote.example.com : PSK "V3ryS3cur3Passphrase!"

Set restrictive permissions:

sudo chmod 600 /etc/ipsec.secrets

IP Forwarding and Firewall

# Persistent forwarding
cat <<'EOF' | sudo tee /etc/sysctl.d/99-ipsec.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
EOF
sudo sysctl --system

# Allow IPsec traffic (nftables example)
sudo nft add rule inet filter input udp dport { 500, 4500 } accept
sudo nft add rule inet filter input ip protocol { esp, ah } accept

Starting and Managing the Tunnel

sudo systemctl enable --now strongswan-starter
# or on newer installs:
sudo systemctl enable --now strongswan

# Check SA status
sudo ipsec statusall

# Manually bring up a connection
sudo ipsec up site-to-site

# Tear down
sudo ipsec down site-to-site

# Reload config after editing
sudo ipsec reload

Example status output:

Security Associations (1 up, 0 connecting):
  site-to-site[1]: ESTABLISHED 5 minutes ago, 10.1.0.1[vpn.example.com]...203.0.113.50[remote.example.com]
  site-to-site{1}: INSTALLED, TUNNEL, ESP SPIs: c1a2b3d4_i 5e6f7a8b_o
  site-to-site{1}: 10.1.0.0/24 === 10.2.0.0/24

Road-Warrior Client (Linux)

On the client install strongSwan and copy the CA cert plus the client key and cert. Create /etc/ipsec.conf:

conn myvpn
    keyexchange=ikev2
    left=%defaultroute
    leftauth=pubkey
    leftcert=client1-cert.pem
    [email protected]
    right=vpn.example.com
    rightauth=pubkey
    [email protected]
    rightsubnet=0.0.0.0/0
    auto=start
sudo ipsec up myvpn

For Windows and macOS clients, export the CA certificate and a PKCS#12 bundle (openssl pkcs12 -export ...) and import them into the native VPN settings. Both support IKEv2 natively.

Troubleshooting

Increase debug output:

# ipsec.conf
config setup
    charondebug="ike 4, knl 4, cfg 4, net 4"

Then watch the log:

journalctl -u strongswan -f
Symptom Fix
NO_PROPOSAL_CHOSEN Cipher mismatch. Ensure both sides offer the same IKE and ESP proposals.
AUTHENTICATION_FAILED Certificate not trusted. Verify the CA cert is in /etc/ipsec.d/cacerts/.
TS_UNACCEPTABLE Traffic selector mismatch -- check leftsubnet/rightsubnet.
SA established but no traffic Missing firewall rule for ESP, or IP forwarding disabled.

Return to the VPN and SSH hub for more guides, or continue with the VPN Protocol Comparison.