How to Configure a Site-to-site Ikev2 Ipsec VPN with Strongswan on Ubuntu Server

Learning how to configure a site-to-site IKEv2 IPsec VPN with Strongswan on Ubuntu Server is one of the most practical skills a Linux administrator can have. A site-to-site VPN creates an encrypted tunnel between two separate networks. This lets both sides communicate securely over the public internet, as if they were on the same local network.

This tutorial walks you through the full setup from scratch. You’ll install Strongswan, generate certificates, write the configuration files, and bring the tunnel up. By the end, both Ubuntu servers will be able to route traffic between their private subnets through an encrypted IPsec tunnel. This setup is ideal for connecting a branch office to a headquarters network, linking two cloud VPCs, or securing server-to-server communication.

Prerequisites and Requirements for This IKEv2 IPsec VPN Setup

Before you start, make sure you have the following in place.

Two Ubuntu servers , both running Ubuntu 20.04 or 22.04 LTS. Each server needs a public IP address and a private subnet behind it.

For this tutorial, we’ll use these example values:

– Server A (Left): Public IP 203.0.113.1, private subnet 10.0.1.0/24
– Server B (Right): Public IP 203.0.113.2, private subnet 10.0.2.0/24

You’ll need root or sudo access on both servers. You should be comfortable editing Linux config files and running terminal commands. Basic knowledge of networking concepts like subnets and routing will help.

Estimated time: 30–45 minutes.

Make sure UDP ports 500 and 4500 are open on both servers’ firewalls. These ports are required for IKEv2 key exchange. Also allow the ESP protocol (IP protocol 50) if your firewall filters by protocol.

How to Configure a Site-to-site IKEv2 IPsec VPN: Installing and Configuring Strongswan

You might also find this useful: How to Set Up Nginx Reverse Proxy with Docker Containers for Multiple Applications

Run every step below on both servers unless stated otherwise.

Step 1: Update your system and install Strongswan

sudo apt update && sudo apt upgrade -y
sudo apt install strongswan strongswan-pki libcharon-extra-plugins -y

This installs Strongswan along with the PKI tools you’ll need to generate certificates. You can read more about Strongswan’s features in the official Strongswan documentation.

Step 2: Generate a Certificate Authority (CA)

Run this only on Server A. You’ll copy the CA certificate to Server B later.

mkdir -p ~/pki/{ca,certs,private}
chmod 700 ~/pki

# Generate the CA private key
pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/ca-key.pem

# Self-sign the CA certificate
pki --self --ca --lifetime 3650 --in ~/pki/private/ca-key.pem 
    --type rsa --dn "CN=VPN CA" --outform pem > ~/pki/ca/ca-cert.pem

Step 3: Generate server certificates for both hosts

Still on Server A, generate a certificate for each server.

# Server A certificate
pki --gen --type rsa --size 2048 --outform pem > ~/pki/private/server-a-key.pem
pki --pub --in ~/pki/private/server-a-key.pem --type rsa | 
    pki --issue --lifetime 1825 --cacert ~/pki/ca/ca-cert.pem 
    --cakey ~/pki/private/ca-key.pem 
    --dn "CN=203.0.113.1" --san "203.0.113.1" 
    --flag serverAuth --flag ikeIntermediate --outform pem > ~/pki/certs/server-a-cert.pem

# Server B certificate
pki --gen --type rsa --size 2048 --outform pem > ~/pki/private/server-b-key.pem
pki --pub --in ~/pki/private/server-b-key.pem --type rsa | 
    pki --issue --lifetime 1825 --cacert ~/pki/ca/ca-cert.pem 
    --cakey ~/pki/private/ca-key.pem 
    --dn "CN=203.0.113.2" --san "203.0.113.2" 
    --flag serverAuth --flag ikeIntermediate --outform pem > ~/pki/certs/server-b-cert.pem

Step 4: Install certificates into Strongswan’s directories

On Server A, copy the files into place:

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

Securely copy the CA cert, Server B’s certificate, and Server B’s key to Server B using scp. Then on Server B, run:

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

Step 5: Configure /etc/ipsec.conf on Server A

Open the file with sudo nano /etc/ipsec.conf and replace the contents:

config setup
    charondebug="ike 1, knl 1, cfg 0"

conn site-to-site
    auto=start
    left=203.0.113.1
    leftsubnet=10.0.1.0/24
    leftcert=server-a-cert.pem
    leftid="CN=203.0.113.1"
    right=203.0.113.2
    rightsubnet=10.0.2.0/24
    rightid="CN=203.0.113.2"
    ike=aes256-sha256-modp2048!
    esp=aes256-sha256!
    keyexchange=ikev2
    ikelifetime=28800s
    lifetime=3600s
    dpdaction=restart
    dpddelay=30s

On Server B, use the same config but swap the left and right values accordingly.

Step 6: Configure /etc/ipsec.secrets on both servers

On Server A:

: RSA server-a-key.pem

On Server B:

: RSA server-b-key.pem

Step 7: Enable IP forwarding and start Strongswan

Run this on both servers to allow traffic to pass through:

sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf

Now restart Strongswan:

sudo systemctl restart strongswan-starter
sudo systemctl enable strongswan-starter

Check the tunnel status with:

sudo ipsec status

You should see the site-to-site connection listed as ESTABLISHED.

Troubleshooting Common Strongswan VPN Problems

Even with a clean setup, things can go wrong. Here are the most common issues.

Tunnel shows as CONNECTING but never ESTABLISHED
Check that UDP ports 500 and 4500 are open on both servers. Use sudo ufw allow 500/udp and sudo ufw allow 4500/udp. Also confirm the public IPs in your config match the actual server IPs.

Certificate errors in logs
Run sudo journalctl -u strongswan-starter --no-pager | tail -50 to read the full log. A common mistake is mismatched CN values between the cert and the leftid/rightid fields. They must match exactly.

Traffic not routing between subnets
Confirm IP forwarding is active with sysctl net.ipv4.ip_forward. It should return 1. Also check that no firewall rules are blocking forwarded traffic. You may need to add sudo ufw allow in on eth0 from 10.0.2.0/24 on Server A.

Tunnel drops after a few minutes
This usually points to a DPD (Dead Peer Detection) misconfiguration. Make sure <code

Similar Posts