IPsec VPN Configuration with strongSwan

strongSwan is a comprehensive, open-source IPsec implementation for Linux providing both IKEv2 and legacy IKEv1 protocol support. Unlike simpler VPN solutions, IPsec operates at the network layer, encrypting all traffic between networks transparently. strongSwan supports complex scenarios including site-to-site connectivity, roadwarrior (mobile) access, split tunneling, and advanced authentication mechanisms. This guide covers installation, core configuration, certificate-based authentication, various deployment scenarios, and advanced features.

Table of Contents

System Requirements

strongSwan requires standard Linux development tools and libraries:

  • GCC compiler or Clang
  • OpenSSL or wolfSSL (cryptography library)
  • libcurl (optional, for revocation checking)
  • Linux kernel with IPsec support (ESP, AH, XFRM)
  • At least 256 MB RAM (1 GB+ recommended)

Verify kernel IPsec support:

grep -i ipsec /boot/config-$(uname -r) | head -10
cat /proc/net/ipsec_interfaces

Installation

Install strongSwan from official repositories or compile from source.

For Ubuntu/Debian:

sudo apt-get update
sudo apt-get install -y strongswan strongswan-charon strongswan-libcharon charon-cmd

For CentOS/RHEL:

sudo yum install -y strongswan

For Fedora:

sudo dnf install -y strongswan

Install optional components for advanced features:

sudo apt-get install -y libstrongswan libstrongswan-extra-plugins strongswan-plugin-eap-tls

Verify installation:

ipsec version
ipsec status

Enable IP forwarding:

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

Make persistent:

sudo nano /etc/sysctl.conf

Add:

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.icmp_ignore_bogus_error_responses=1

Apply:

sudo sysctl -p

Generating Certificates

strongSwan supports pre-shared key (PSK) and certificate-based authentication. Certificates provide stronger security for production deployments.

Create a certificate authority (CA):

mkdir -p /etc/strongswan/ipsec.d/cacerts
cd /tmp
openssl genrsa -out cakey.pem 4096

Generate CA certificate:

openssl req -new -x509 -days 3650 -key cakey.pem -out cacert.pem \
  -subj "/C=US/ST=State/L=City/O=Organization/CN=strongSwan-CA"

Create server certificate signing request:

openssl genrsa -out serverkey.pem 2048
openssl req -new -key serverkey.pem -out server.csr \
  -subj "/C=US/ST=State/L=City/O=Organization/CN=vpn.example.com"

Sign server certificate:

openssl x509 -req -days 730 -in server.csr -CA cacert.pem -CAkey cakey.pem \
  -CAcreateserial -out servercert.pem \
  -extensions v3_req -extfile <(printf "subjectAltName=DNS:vpn.example.com")

Create client certificate:

openssl genrsa -out clientkey.pem 2048
openssl req -new -key clientkey.pem -out client.csr \
  -subj "/C=US/ST=State/L=City/O=Organization/[email protected]"

openssl x509 -req -days 730 -in client.csr -CA cacert.pem -CAkey cakey.pem \
  -CAcreateserial -out clientcert.pem

Copy certificates to strongSwan directories:

sudo cp cacert.pem /etc/strongswan/ipsec.d/cacerts/
sudo cp servercert.pem /etc/strongswan/ipsec.d/certs/
sudo cp serverkey.pem /etc/strongswan/ipsec.d/private/
sudo cp clientcert.pem /etc/strongswan/ipsec.d/certs/
sudo cp clientkey.pem /etc/strongswan/ipsec.d/private/
sudo chown root:root /etc/strongswan/ipsec.d/private/*
sudo chmod 600 /etc/strongswan/ipsec.d/private/*

Basic IKEv2 Configuration

Configure strongSwan for IKEv2 with certificate authentication.

Edit the main configuration file:

sudo nano /etc/strongswan/ipsec.conf

Basic IKEv2 server configuration:

config setup
    uniqueids = never
    charondebug = "all"
    strictcrlpolicy = no
    
conn %default
    type = tunnel
    dpdaction = clear
    dpddelay = 300s
    rekey = no
    left = %any
    leftcert = servercert.pem
    leftid = vpn.example.com
    leftauth = pubkey
    right = %any
    rightid = %any
    rightauth = pubkey
    rightsourceip = 10.8.0.0/24
    compression = yes
    
conn ikev2-pubkey
    keyexchange = ikev2
    auto = add

Configure IPsec credentials in secrets file:

sudo nano /etc/strongswan/ipsec.secrets

Add certificate passphrases:

: RSA serverkey.pem
: RSA clientkey.pem

Start strongSwan:

sudo systemctl start strongswan
sudo systemctl enable strongswan

Verify configuration:

sudo ipsec status
sudo ipsec listall

Site-to-Site VPN

Configure IPsec tunnel between two sites.

Site A (203.0.113.1) configuration:

sudo nano /etc/strongswan/ipsec.conf

Content:

config setup
    uniqueids = never
    dpdaction = restart
    dpddelay = 10s
    dpdtimeout = 30s
    
conn site-to-site
    type = tunnel
    keyexchange = ikev2
    ike = aes256-sha2_256-modp2048!
    esp = aes256-aes256!
    dpdaction = restart
    left = 203.0.113.1
    leftcert = sitea-cert.pem
    leftid = site-a.example.com
    leftsubnet = 192.168.1.0/24
    right = 198.51.100.5
    rightid = site-b.example.com
    rightcert = siteb-cert.pem
    rightsubnet = 192.168.2.0/24
    auto = start
    rekey = yes
    reauth = no

Site B (198.51.100.5) configuration:

sudo nano /etc/strongswan/ipsec.conf

Content:

config setup
    uniqueids = never
    dpdaction = restart
    dpddelay = 10s
    
conn site-to-site
    type = tunnel
    keyexchange = ikev2
    ike = aes256-sha2_256-modp2048!
    esp = aes256-aes256!
    dpdaction = restart
    left = 198.51.100.5
    leftcert = siteb-cert.pem
    leftid = site-b.example.com
    leftsubnet = 192.168.2.0/24
    right = 203.0.113.1
    rightid = site-a.example.com
    rightcert = sitea-cert.pem
    rightsubnet = 192.168.1.0/24
    auto = start
    rekey = yes

Reload configuration:

sudo ipsec reread
sudo ipsec reload

Initiate the tunnel from Site A:

sudo ipsec up site-to-site

Verify tunnel status:

sudo ipsec status site-to-site

Test connectivity:

# From Site A
ping 192.168.2.5  # Site B internal server

Roadwarrior Configuration

Configure IPsec for remote clients connecting to a VPN gateway.

VPN gateway configuration:

conn %default
    type = tunnel
    keyexchange = ikev2
    ike = aes128-sha2_256-modp2048!
    esp = aes128-sha2_256!
    dpdaction = clear
    left = 203.0.113.1
    leftcert = vpn-cert.pem
    leftid = vpn.example.com
    leftauth = pubkey
    right = %any
    rightid = %any
    rightauth = pubkey
    rightsourceip = 10.8.0.0/24
    rightdns = 8.8.8.8,8.8.4.4
    
conn ikev2-pubkey
    keyexchange = ikev2
    auto = add

Secrets file:

: RSA vpn-key.pem

Configure DHCP pool for remote clients. Edit charon daemon configuration:

sudo nano /etc/strongswan/strongswan.d/charon.conf

Add:

charon {
    dns1 = 8.8.8.8
    dns2 = 8.8.4.4
    pools = dns_pool
}

dns_pool {
    addrs = 10.8.0.0/24
}

Export client certificate and key for distribution:

# Create PKCS12 file for Windows clients
openssl pkcs12 -export -in clientcert.pem -inkey clientkey.pem \
  -certfile cacert.pem -out client.p12 -name "VPN Client"

On client machine, import certificate and configure:

conn vpn-client
    type = tunnel
    keyexchange = ikev2
    ike = aes128-sha2_256-modp2048!
    esp = aes128-sha2_256!
    left = %defaultroute
    leftauth = pubkey
    leftcert = clientcert.pem
    leftid = [email protected]
    right = 203.0.113.1
    rightid = vpn.example.com
    rightauth = pubkey
    rightsourceip = %dhcp
    auto = start

Split Tunneling

Configure split tunneling to route only specific traffic through the VPN.

Modify roadwarrior configuration to exclude certain traffic:

conn vpn-splitdns
    type = tunnel
    keyexchange = ikev2
    left = %defaultroute
    leftauth = pubkey
    leftcert = clientcert.pem
    right = 203.0.113.1
    rightid = vpn.example.com
    rightauth = pubkey
    # Only route corporate subnet through VPN
    rightsubnet = 192.168.1.0/24
    auto = start

With this configuration, only traffic to 192.168.1.0/24 goes through VPN; other traffic uses local default route.

Configure traffic selectors for fine-grained control:

conn selective-vpn
    type = tunnel
    keyexchange = ikev2
    left = %defaultroute
    leftid = [email protected]
    leftauth = pubkey
    right = 203.0.113.1
    rightid = vpn.example.com
    rightauth = pubkey
    # Multiple subnets through VPN
    rightsubnet = 192.168.1.0/24,192.168.2.0/24,10.0.0.0/8
    # Exclude 192.168.3.0/24 from VPN tunnel
    leftsubnet = 0.0.0.0/0 except 192.168.3.0/24
    auto = start

ipsec.conf Syntax

Understand the syntax and options for strongSwan configuration.

Common IKEv2 parameters:

ike = aes256-sha2_256-modp2048!  # IKE encryption-hash-dhgroup
esp = aes256-sha2_256!            # ESP encryption-hash
lifetime = 24h                     # Rekeying interval
dpdaction = restart                # Dead peer detection action
dpddelay = 10s                     # Dead peer detection interval

Traffic selector options:

leftsubnet = 192.168.1.0/24       # Left subnet to protect
rightsubnet = 10.0.0.0/24         # Right subnet to protect
type = tunnel                      # tunnel vs transport mode

Authentication options:

leftauth = pubkey                  # Certificate-based
rightauth = psk                    # Pre-shared key
leftid = vpn.example.com           # Identity

Source IP options:

rightsourceip = 10.8.0.0/24       # Assign IP from pool
rightsourceip = %dhcp              # Dynamic allocation
rightsourceip = %config            # Demand specific IP

Firewall Integration

Configure firewall rules to allow IPsec traffic.

Allow IKE (Internet Key Exchange) traffic:

sudo iptables -A INPUT -p udp --dport 500 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 4500 -j ACCEPT

Allow IPsec protocols (ESP and AH):

sudo iptables -A INPUT -p esp -j ACCEPT
sudo iptables -A INPUT -p ah -j ACCEPT

Allow traffic from VPN clients to internal networks:

sudo iptables -A FORWARD -i ipsec0 -s 10.8.0.0/24 -j ACCEPT
sudo iptables -A FORWARD -o ipsec0 -d 10.8.0.0/24 -j ACCEPT

Configure NAT for VPN clients:

sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

Save rules:

sudo iptables-save > /etc/iptables/rules.v4

Using ufw (simplified):

sudo ufw allow 500/udp
sudo ufw allow 4500/udp
sudo ufw allow in on ipsec0
sudo ufw allow out on ipsec0

Monitoring and Troubleshooting

Monitor IPsec connections and troubleshoot issues.

View VPN status:

sudo ipsec status
sudo ipsec statusall

List all connections:

sudo ipsec listall

Monitor live traffic:

sudo ipsec traffic

View connected clients:

sudo ipsec leases

Check configuration syntax:

sudo ipsec checkconfig

Enable debugging:

sudo ipsec set-loglevel -c charon -d 3

View strongSwan logs:

sudo journalctl -u strongswan -f

Test connectivity through VPN:

ping 192.168.2.5  # Remote network address

Troubleshoot connection failures:

# Check IKE negotiation
sudo ipsec status
# Check SAD (Security Association Database)
sudo ip xfrm state
# Check SPD (Security Policy Database)
sudo ip xfrm policy

View detailed statistics:

sudo ipsec leases pool-name
sudo ipsec listcerts
sudo ipsec listcrl

Test with tcpdump to see actual IPsec packets:

sudo tcpdump -i eth0 'udp port 500 or udp port 4500 or esp'

Conclusion

strongSwan provides enterprise-grade IPsec VPN capabilities for diverse deployment scenarios. By following this guide, you've installed strongSwan, generated and managed X.509 certificates for secure authentication, configured IKEv2 tunnels for modern security, deployed site-to-site VPNs for network interconnection, set up roadwarrior access for remote clients, implemented split tunneling for selective routing, integrated with firewalls for security control, and established monitoring for ongoing operation. Whether protecting site-to-site traffic with mutual authentication or enabling remote workers with split-tunnel VPN, strongSwan scales from small deployments to large enterprise networks with transparent IPsec encryption and advanced security policies.