Skip to main contentSkip to navigation
[email protected]
Client AreaSupport
Hosting Mammoth
HostingMammothYour Data, Our Responsibility
Home
Solutions
Hosting Services
Store
Pricing
About
Blog
API
Contact

Stay Ahead of the Curve

Get the latest insights on cybersecurity, AI innovations, and enterprise data solutions delivered to your inbox.

Hosting Mammoth
HostingMammothEnterprise Solutions

Enterprise-grade data solutions. Hosting, recovery, cybersecurity, and AI-powered services for businesses worldwide.

[email protected]
Sun - Fri, 9:00am - 5:00pm

Services

  • Cloud Hosting
  • Data Recovery
  • Cybersecurity
  • Legal Support
  • MSP Services
  • Web Development
  • AI Services
  • Free Server Migration

Hosting

  • VPS Hosting (NVMe SSD)
  • VDS Hosting (NVMe)
  • Storage VPS (High SSD)
  • GPU Servers
  • Managed Services
  • Cloud Firewall
  • Load Balancer
  • One-Click Apps
  • n8n Hosting
  • Object Storage
  • FAQ

Company

  • Store
  • Pricing
  • About Us
  • Locations
  • Blog
  • Testimonials
  • Contact
  • Affiliate Program
  • White-Label
  • Terms of Service
  • Privacy Policy
  • Browser Cookies
  • SLA

Support

  • Client Area
  • Submit Ticket
  • Knowledge Base
  • Server Status
  • API Documentation

© 2026 Hosting Mammoth. All rights reserved.

Knowledge Base
Getting StartedAccount ManagementVPS HostingGPU ServersStorage VPSCloud FirewallLoad BalancerServer ManagementBilling & PaymentsSupport & TicketsAffiliate ProgramReseller ProgramMarketplace & Appsn8n HostingManaged ServicesServer MigrationAPI & DevelopersSecurityTroubleshootingGlossaryInstall Guides
  1. Home
  2. /
  3. Support
  4. /
  5. Install Guides
  6. /
  7. How To Install Strongswan Ubuntu
GUIDEInstall Guides

How to Install strongSwan IPsec VPN on Ubuntu 24.04 VPS: IKEv2 Remote Access & Site-to-Site

31 min read

How to Install strongSwan IPsec VPN on Ubuntu 24.04 — IKEv2 Remote Access & Site-to-Site

IPsec with IKEv2 is the standards-based VPN protocol that every modern operating system speaks natively. Unlike WireGuard or OpenVPN, which require a third-party client, IKEv2 connects directly from the built-in VPN settings on iOS, macOS, Windows, Android, and Linux. This guide walks you through installing strongSwan on an Ubuntu 24.04 VPS, building a complete certificate authority with the pki tool, configuring an IKEv2 road-warrior server with EAP-MSCHAPv2 authentication, generating client profiles for every major platform, and extending the setup with a site-to-site tunnel.

Want a VPN without the moving parts? Most home users only need an encrypted tunnel and a new IP. Deploy WireGuard in 15 minutes or OpenConnect for SSL-based access. strongSwan is the right choice when you need native OS integration, site-to-site tunnels, or enterprise authentication.

Table of Contents

  • What is strongSwan?
  • Why Self-Host IPsec vs WireGuard?
  • Prerequisites
  • Step 1: Update the System
  • Step 2: Install strongSwan and Plugins
  • Step 3: Enable IP Forwarding
  • Step 4: Build the PKI (Certificate Authority)
  • Step 5: Generate the Server Certificate
  • Step 6: Generate Client Certificates
  • Step 7: Configure swanctl.conf (IKEv2 Road-Warrior)
  • Step 8: Add EAP User Credentials
  • Step 9: Firewall and MASQUERADE
  • Step 10: Start strongSwan and Load Config
  • Step 11: Client Configuration
  • Step 12: Site-to-Site Tunnel Example
  • Logs, Monitoring, and Troubleshooting
  • FAQ
  • Next Steps
  • What is strongSwan?

    strongSwan is the leading open-source IPsec implementation for Linux, FreeBSD, macOS, Windows, and Android. It implements the full IKEv1 and IKEv2 key exchange protocols, the IPsec kernel interfaces (XFRM on Linux), and a comprehensive set of authentication methods including X.509 certificates, pre-shared keys, EAP-MSCHAPv2, EAP-TLS, EAP-Radius, and PKCS#11 hardware tokens. It is the reference IKEv2 implementation in many enterprise and carrier networks.

    The project has a long pedigree — it forked from FreeS/WAN in 2005 and has been actively maintained ever since by Andreas Steffen and the strongSwan team. Version 5.9+ introduces swanctl, a modern configuration and control utility that replaced the legacy ipsec.conf / ipsec secrets files. This tutorial uses the modern swanctl interface throughout.

    strongSwan is what you use when:

    • You need a road-warrior VPN that mobile devices connect to from the native OS settings (no app install, no sideloaded configuration).
    • You need site-to-site tunnels between offices, data centers, or cloud VPCs over the public internet.
    • You need standards compliance — IKEv2 is defined in RFC 7296, and strongSwan implements the full spec including MOBIKE (RFC 4555) for seamless network handovers.
    • You need EAP-Radius integration to authenticate VPN users against an existing corporate directory or 2FA system.
    • You need IPv6 support, DPD (dead peer detection), NAT traversal, and other features that have been battle-tested for two decades.

    Why Self-Host IPsec vs WireGuard?

    WireGuard is the new hotness in VPN-land — it is faster, simpler, and has a smaller attack surface. But strongSwan/IPsec still wins in several scenarios:

    • Native OS support. IKEv2 is built into iOS, iPadOS, macOS, Windows 10/11, Android (via the stock VPN menu since 12+), and Linux NetworkManager. Users connect from the system VPN settings without installing any app. WireGuard requires a third-party app on every platform.
    • Zero-touch mobile deployment. With a .mobileconfig (iOS/macOS) or .sswan profile, the entire VPN — server address, CA certificate, client cert, EAP username — is provisioned with a single tap. WireGuard requires QR code scanning and manual profile management.
    • MOBIKE roaming. IKEv2 with MOBIKE lets a phone switch between Wi-Fi and cellular without tearing down the tunnel. WireGuard reconnects on every network change.
    • Corporate authentication. strongSwan plugs into RADIUS, Active Directory, and TOTP-based 2FA out of the box. WireGuard requires bolt-on tools like wg-portal or Tailscale.
    • Site-to-site standards. IPsec is the industry standard for interconnecting offices, Cisco ASAs, FortiGates, AWS/Azure VPN gateways, and essentially every enterprise firewall. WireGuard support is growing but not universal.
    • Audited crypto. IKEv2 and the IPsec ESP transform have been deployed and audited for 25+ years. The crypto primitives (AES-GCM, SHA-2, ECDH with NIST or Curve25519 curves, Ed25519 signatures) are all supported by strongSwan.
    The trade-off: strongSwan has a steeper learning curve, configuration is more verbose, and throughput is typically 10-30% lower than WireGuard on the same hardware. If you are a solo user building a personal VPN to bypass geo-restrictions, WireGuard is simpler. If you are building a VPN for a team of non-technical users on mixed iOS/Android/Windows devices, strongSwan wins on the user-experience side.

    Comparison: strongSwan vs WireGuard vs OpenVPN

    FeaturestrongSwan (IKEv2)WireGuardOpenVPN
    Native OS clientYes (iOS, macOS, Win, Android)No (app required)No (app required)
    Mobile roamingMOBIKE (seamless)Reconnect on network changeReconnect on network change
    Throughput (1 Gbps NIC)~700-800 Mbps~900+ Mbps~300-500 Mbps
    Config complexityHighLowMedium
    Site-to-site standardYes (RFC 7296)ProprietaryProprietary
    Enterprise auth (RADIUS/AD)YesNo (external)Yes
    Codebase size~400K LoC~4K LoC~100K LoC

    Prerequisites

    Before you begin, make sure you have:

    • A VPS running Ubuntu 24.04 LTS with root or sudo access.
    • A public IPv4 address on the server. Note the address now — you will use it as the SAN (subject alternative name) on the server certificate.
    • SSH access to the server.
    • A domain name (optional but recommended) pointed to the VPS, so you can use a hostname instead of an IP in client profiles. IPsec works fine with IP-only endpoints, but hostnames make later IP changes painless.
    • UDP ports 500 and 4500 reachable from the internet. If your provider has an external firewall (AWS security group, Hetzner Cloud firewall, etc.), open these ports there as well.
    Recommended Plan: CloudCore Starter
    >
    strongSwan is lightweight — the daemon itself uses less than 50 MB of RAM. For a personal or small-team VPN serving 10-30 concurrent users, the CloudCore Starter plan is ideal:
    >
    - 2 vCPU cores
    - 4 GB RAM
    - 50 GB NVMe SSD
    - Unmetered bandwidth
    >
    CPU is the limiting factor for throughput — IPsec does a lot of crypto per packet. Two vCPUs on modern hardware (AES-NI) easily saturate a 1 Gbps link. For larger deployments (hundreds of concurrent clients or high-throughput site-to-site), step up to a plan with 4+ vCPUs.

    Connect to your server via SSH to get started:

    bash
    ssh root@your-server-ip

    For the rest of this guide we assume your public IP is 203.0.113.10 and (optionally) your hostname is vpn.example.com. Substitute your actual values.

    Step 1: Update the System

    Start by updating your package index and upgrading installed packages:

    bash
    sudo apt update && sudo apt upgrade -y

    If the kernel was updated, reboot before continuing:

    bash
    sudo reboot

    Reconnect via SSH after a minute and verify the kernel version:

    bash
    uname -r

    strongSwan uses the kernel's XFRM framework for IPsec policy. Any recent Ubuntu 24.04 kernel (6.8+) supports everything we need.

    Step 2: Install strongSwan and Plugins

    Install the core strongSwan packages plus the extra plugins you need for EAP-MSCHAPv2 and modern cipher suites:

    bash
    sudo apt install -y strongswan strongswan-pki strongswan-swanctl \
        libcharon-extra-plugins libcharon-extauth-plugins \
        libstrongswan-extra-plugins

    What each package provides:

    • strongswan — the core daemon (charon) and systemd service.
    • strongswan-pki — the pki command-line tool for generating keys, certificates, and CRLs.
    • strongswan-swanctl — the modern swanctl control utility and /etc/swanctl/ configuration tree.
    • libcharon-extra-plugins — extra authentication and crypto plugins including eap-mschapv2, xauth, and farp.
    • libcharon-extauth-plugins — plugins for external authentication backends (RADIUS, PAM).
    • libstrongswan-extra-plugins — extended crypto primitives (Curve25519, Ed25519, BLAKE2).
    Verify the installation and check the version:

    bash
    sudo swanctl --version

    Expected output:

    text
    strongSwan swanctl 5.9.13

    Check that the systemd service is enabled:

    bash
    sudo systemctl status strongswan

    Expected output:

    text
    ● strongswan.service - strongSwan IPsec IKEv1/IKEv2 daemon using swanctl
         Loaded: loaded (/usr/lib/systemd/system/strongswan.service; enabled; preset: enabled)
         Active: active (running) since ...

    The service is running with an empty configuration at this point. We will populate it in the next steps.

    Step 3: Enable IP Forwarding

    The VPN server needs to forward packets between the tunnel and the public interface. Enable IPv4 (and optionally IPv6) forwarding in the kernel:

    bash
    sudo tee /etc/sysctl.d/99-strongswan.conf > /dev/null <<EOF
    net.ipv4.ip_forward = 1
    net.ipv6.conf.all.forwarding = 1

    Don't accept ICMP redirects (prevent MITM attacks)

    net.ipv4.conf.all.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0

    Don't send ICMP redirects (we are not a router for the LAN)

    net.ipv4.conf.all.send_redirects = 0

    Disable path MTU discovery black-holing

    net.ipv4.ip_no_pmtu_disc = 0 EOF

    sudo sysctl -p /etc/sysctl.d/99-strongswan.conf

    Expected output:

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

    Step 4: Build the PKI (Certificate Authority)

    IKEv2 uses X.509 certificates to authenticate the server to clients. We will build a small private CA, issue a server certificate, and (for the road-warrior setup) use EAP-MSCHAPv2 with username/password for client authentication. The same CA can later issue per-device client certificates if you want mutual TLS-style authentication.

    strongSwan ships with the pki tool — a purpose-built certificate manager that is simpler than OpenSSL for IPsec use cases.

    Create a working directory with restrictive permissions:

    bash
    mkdir -p ~/pki/{cacerts,certs,private}
    chmod 700 ~/pki
    cd ~/pki

    Generate the CA Private Key

    bash
    pki --gen --type rsa --size 4096 --outform pem > private/ca-key.pem
    chmod 600 private/ca-key.pem

    The --type rsa --size 4096 flags produce a 4096-bit RSA key — the conservative choice. If you prefer modern elliptic-curve crypto, use --type ed25519 for a much smaller key with equivalent security.

    Self-Sign the CA Certificate

    Use pki --self to create a self-signed root certificate from the private key:

    bash
    pki --self --ca --lifetime 3650 \
        --in private/ca-key.pem --type rsa \
        --dn "CN=VPN Root CA" \
        --outform pem > cacerts/ca-cert.pem

    Flags explained:

    • --self — self-sign the certificate (no issuer).
    • --ca — mark this as a CA certificate (sets basicConstraints:CA=TRUE).
    • --lifetime 3650 — valid for 10 years. CAs should outlive everything they issue.
    • --dn "CN=VPN Root CA" — distinguished name. The CN is human-readable — it shows up in client trust dialogs.
    Verify the CA:

    bash
    pki --print --in cacerts/ca-cert.pem

    You should see the subject, validity period, and pathlen constraint.

    Step 5: Generate the Server Certificate

    Create the server's private key:

    bash
    pki --gen --type rsa --size 4096 --outform pem > private/server-key.pem
    chmod 600 private/server-key.pem

    Extract the public key (used later by the pki --issue step implicitly, but kept for reference):

    bash
    pki --pub --in private/server-key.pem --type rsa > private/server-pub.pem

    Now issue the server certificate, signed by your CA. This step is where the subject alternative names (SANs) matter — clients verify that the SAN on the cert matches what they connected to. Include every hostname and IP you expect clients to use:

    bash
    pki --issue --lifetime 1825 \
        --cacert cacerts/ca-cert.pem \
        --cakey private/ca-key.pem \
        --in private/server-key.pem --type rsa \
        --dn "CN=vpn.example.com" \
        --san vpn.example.com \
        --san 203.0.113.10 \
        --flag serverAuth --flag ikeIntermediate \
        --outform pem > certs/server-cert.pem

    Flags explained:

    • --lifetime 1825 — 5 years. Server certificates rotate more often than the CA.
    • --cacert / --cakey — the CA that will sign this cert.
    • --dn "CN=vpn.example.com" — common name. Some older clients match this; modern clients use SAN.
    • --san — subject alternative names. Include every address clients will dial. Repeat the flag for each entry.
    • --flag serverAuth — extended key usage: TLS Web Server Authentication (used by Windows).
    • --flag ikeIntermediate — extended key usage for IKE intermediate (required by iOS/macOS for IKEv2).
    Install the CA and server cert into the strongSwan config tree:

    bash
    sudo cp -r ~/pki/cacerts/* /etc/swanctl/x509ca/
    sudo cp -r ~/pki/certs/* /etc/swanctl/x509/
    sudo cp -r ~/pki/private/* /etc/swanctl/private/
    sudo chown -R root:root /etc/swanctl/
    sudo chmod -R 600 /etc/swanctl/private/

    Step 6: Generate Client Certificates

    For pure EAP-MSCHAPv2 (username/password) authentication, clients do not need individual certificates — they only need the CA certificate to verify the server. However, if you want stronger mutual authentication (recommended for production), issue a per-device client cert. This example generates one for a user named alice:

    bash
    cd ~/pki

    Alice's private key

    pki --gen --type rsa --size 4096 --outform pem > private/alice-key.pem chmod 600 private/alice-key.pem

    Issue the client cert signed by the CA

    pki --issue --lifetime 730 \ --cacert cacerts/ca-cert.pem \ --cakey private/ca-key.pem \ --in private/alice-key.pem --type rsa \ --dn "[email protected]" \ --san [email protected] \ --flag clientAuth \ --outform pem > certs/alice-cert.pem

    Export Alice's cert and key as a PKCS#12 bundle (the format iOS, macOS, and Windows import directly):

    bash
    openssl pkcs12 -export \
        -inkey private/alice-key.pem \
        -in certs/alice-cert.pem \
        -name "[email protected]" \
        -certfile cacerts/ca-cert.pem \
        -caname "VPN Root CA" \
        -out alice.p12

    You will be prompted for an export password — set a strong one and share it securely with the user.

    Transfer alice.p12 and cacerts/ca-cert.pem to the user's device (AirDrop, encrypted email, signed URL, etc.).

    Step 7: Configure swanctl.conf (IKEv2 Road-Warrior)

    The modern strongSwan configuration lives in /etc/swanctl/swanctl.conf (or any .conf file in /etc/swanctl/conf.d/). Replace the default file with a complete road-warrior configuration:

    bash
    sudo tee /etc/swanctl/swanctl.conf > /dev/null <<'EOF'
    connections {

    ikev2-eap { version = 2 proposals = aes256gcm16-prfsha384-ecp384,aes256-sha384-ecp384,default

    rekey_time = 24h dpd_delay = 30s

    # Server side of the IKE SA local_addrs = %any remote_addrs = %any

    local { auth = pubkey certs = server-cert.pem id = vpn.example.com }

    remote { auth = eap-mschapv2 eap_id = %any }

    children { ikev2-eap { local_ts = 0.0.0.0/0, ::/0 esp_proposals = aes256gcm16-ecp384,aes256-sha256,default rekey_time = 8h dpd_action = clear } }

    # Virtual IP pool and DNS handed to clients pools = primary-pool-ipv4, primary-pool-ipv6

    # Send pushed DNS / split-routes via IKEv2 config payload send_cert = always fragmentation = yes mobike = yes } }

    pools { primary-pool-ipv4 { addrs = 10.10.10.0/24 dns = 1.1.1.1, 9.9.9.9 } primary-pool-ipv6 { addrs = fd9b:7bd8:e9f2::/48 dns = 2606:4700:4700::1111, 2620:fe::fe } }

    secrets { eap-alice { id = [email protected] secret = "ReplaceWithALongRandomPassword!" } eap-bob { id = [email protected] secret = "AnotherStrongSecret#42" } } EOF

    Key sections explained:

    • connections.ikev2-eap — a single connection definition named ikev2-eap. The name is arbitrary.
    • proposals — IKE SA ciphers offered to clients. The list is preference-ordered: AES-256-GCM with PRF-SHA384 and ECP-384 DH group first, falling back to default (strongSwan's built-in modern list).
    • local.auth = pubkey — server authenticates with its X.509 certificate.
    • remote.auth = eap-mschapv2 — clients authenticate with EAP username/password.
    • children.ikev2-eap.local_ts = 0.0.0.0/0, ::/0 — the server advertises it can route all traffic (full-tunnel VPN). Change this to a specific subnet if you want split-tunnel.
    • pools — virtual IP ranges handed to clients via the IKEv2 configuration payload. Pick RFC 1918 ranges (v4) and ULA ranges (v6) that do not overlap with any network your clients are likely to be on.
    • mobike = yes — enable IKEv2 MOBIKE so clients can roam between Wi-Fi and cellular without reconnecting.
    • fragmentation = yes — enable IKEv2 fragmentation (RFC 7383) to handle large cert payloads over lossy networks.
    Protect the file — it contains EAP passwords:

    bash
    sudo chmod 600 /etc/swanctl/swanctl.conf

    Step 8: Add EAP User Credentials

    The secrets block in swanctl.conf above already defines two EAP users ([email protected] and [email protected]). To add more users later, append additional blocks:

    text
    secrets {
        eap-alice {
            id = [email protected]
            secret = "..."
        }
        eap-carol {
            id = [email protected]
            secret = "AnotherStrongSecret#99"
        }
    }

    After editing, reload the secrets without restarting the daemon:

    bash
    sudo swanctl --load-creds

    Expected output:

    text
    loaded eap secret 'eap-alice'
    loaded eap secret 'eap-carol'
    loaded certificate from '/etc/swanctl/x509/server-cert.pem'
    loaded certificate from '/etc/swanctl/x509ca/ca-cert.pem'
    loaded rsa key from '/etc/swanctl/private/server-key.pem'

    Generate strong passwords — EAP-MSCHAPv2 is the weakest link in this stack. Anything under 16 random characters is vulnerable to offline dictionary attacks if a passive attacker captures the handshake. Use openssl rand -base64 24 or pwgen -s 24 1.

    For production deployments with more than a handful of users, replace eap-mschapv2 with eap-radius and authenticate against an external RADIUS server (FreeRADIUS + LDAP, or a cloud 2FA provider like Okta or JumpCloud).

    Step 9: Firewall and MASQUERADE

    IPsec needs two UDP ports open to the internet plus NAT rules so that client traffic exits through your server's public IP.

    Open UDP 500 and 4500

    Using UFW (the default Ubuntu firewall):

    bash
    sudo ufw allow 22/tcp           # SSH (don't lock yourself out)
    sudo ufw allow 500/udp          # IKE
    sudo ufw allow 4500/udp         # IKE NAT-Traversal
    sudo ufw allow esp              # IPsec ESP (protocol 50)
    sudo ufw enable
    sudo ufw status verbose

    Expected output:

    text
    Status: active
    To                         Action      From
    --                         ------      ----
    22/tcp                     ALLOW       Anywhere
    500/udp                    ALLOW       Anywhere
    4500/udp                   ALLOW       Anywhere
    ESP                        ALLOW       Anywhere

    Configure MASQUERADE for Client Traffic

    UFW's default rules do not apply NAT to forwarded traffic from the VPN pool. Add the MASQUERADE rule manually.

    First, find the name of your public interface:

    bash
    ip -4 route show default

    Expected output:

    text
    default via 203.0.113.1 dev eth0 proto static

    In this example the public interface is eth0. Adjust the commands below if yours differs.

    Edit UFW's before rules:

    bash
    sudo tee -a /etc/ufw/before.rules > /dev/null <<'EOF'

    strongSwan NAT: masquerade VPN clients

    *nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE -A POSTROUTING -s fd9b:7bd8:e9f2::/48 -o eth0 -j MASQUERADE COMMIT EOF

    Enable forwarding in UFW's default policy:

    bash
    sudo sed -i 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw

    Apply the changes:

    bash
    sudo ufw disable && sudo ufw enable

    Verify NAT is Active

    bash
    sudo iptables -t nat -L POSTROUTING -n -v

    Expected output:

    text
    Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination
        0     0 MASQUERADE  all  --  *      eth0    10.10.10.0/24        0.0.0.0/0

    Step 10: Start strongSwan and Load Config

    Reload the swanctl configuration into the running daemon:

    bash
    sudo swanctl --load-all --noprompt

    Expected output:

    text
    loaded certificate from '/etc/swanctl/x509/server-cert.pem'
    loaded certificate from '/etc/swanctl/x509ca/ca-cert.pem'
    loaded rsa key from '/etc/swanctl/private/server-key.pem'
    loaded eap secret 'eap-alice'
    loaded eap secret 'eap-bob'
    loaded pool 'primary-pool-ipv4'
    loaded pool 'primary-pool-ipv6'
    loaded connection 'ikev2-eap'
    successfully loaded 1 connections, 0 unloaded

    Confirm strongSwan is listening on UDP 500 and 4500:

    bash
    sudo ss -ulnp | grep charon

    Expected output:

    text
    UNCONN 0  0  0.0.0.0:500       0.0.0.0:*    users:(("charon-systemd",pid=...))
    UNCONN 0  0  0.0.0.0:4500      0.0.0.0:*    users:(("charon-systemd",pid=...))

    Enable the service at boot:

    bash
    sudo systemctl enable strongswan
    sudo systemctl restart strongswan

    View loaded connections:

    bash
    sudo swanctl --list-conns

    List active SAs (will be empty until a client connects):

    bash
    sudo swanctl --list-sas

    Step 11: Client Configuration

    The exact steps depend on the platform. In every case, the client needs:

  • The CA certificate (ca-cert.pem) imported into the device's trust store.
  • The server hostname or IP (e.g., vpn.example.com).
  • The EAP username and password (or PKCS#12 client cert).
  • iOS and macOS (Apple Configurator .mobileconfig)

    The most user-friendly approach for Apple devices is to generate a signed .mobileconfig profile. The user double-taps it, enters their device passcode, and the entire VPN — CA cert, server settings, EAP username — is installed. Use Apple Configurator 2 or a tool like iMazing Profile Editor to build the profile.

    Alternatively, configure manually:

  • Settings → General → VPN & Device Management → VPN → Add VPN Configuration.
  • Type: IKEv2.
  • Description: My VPN.
  • Server: vpn.example.com.
  • Remote ID: vpn.example.com (must match the server certificate SAN).
  • Local ID: leave blank.
  • User Authentication: Username.
  • Username: [email protected].
  • Password: the EAP secret.
  • Certificate: none (using EAP) — but you must separately install ca-cert.pem via Settings → General → VPN & Device Management → Profile so that iOS trusts the server cert.
  • Windows 10 / 11

  • Copy ca-cert.pem to the Windows machine. Rename to ca-cert.crt.
  • Double-click → Install Certificate → Local Machine → Place all certificates in the following store → Trusted Root Certification Authorities.
  • Open Settings → Network & Internet → VPN → Add a VPN connection.
  • VPN provider: Windows (built-in).
  • Connection name: My VPN.
  • Server name or address: vpn.example.com.
  • VPN type: IKEv2.
  • Type of sign-in info: Username and password.
  • Save, then Change adapter options → right-click VPN → Properties → Security tab → Authentication: Use Extensible Authentication Protocol (EAP) → Microsoft: Secured password (EAP-MSCHAP v2).
  • Android 12+ (Native IKEv2)

    Native IKEv2 with EAP-MSCHAPv2 has been in Android since 12:

  • Settings → Network & Internet → VPN → Add VPN.
  • Name: My VPN.
  • Type: IKEv2/IPsec MSCHAPv2.
  • Server address: vpn.example.com.
  • IPsec identifier: leave blank.
  • IPsec CA certificate: select the CA you imported under Settings → Security → Encryption & credentials → Install a certificate → CA certificate.
  • Username/Password: [email protected] / your EAP password.
  • Android (strongSwan App — Recommended for Older Devices)

    Install the free strongSwan VPN Client from Google Play.

  • Tap Add VPN Profile.
  • Server: vpn.example.com.
  • VPN Type: IKEv2 EAP (Username/Password).
  • Username/Password: the EAP credentials.
  • CA certificate: Select automatically, or import ca-cert.pem.
  • Save and connect.
  • Linux (NetworkManager)

    Install the strongSwan NetworkManager plugin:

    bash
    sudo apt install -y network-manager-strongswan

    Then in GNOME Settings → Network → VPN → Add → IPsec/IKEv2 (strongSwan). Fill in:

    • Address: vpn.example.com
    • Certificate: path to ca-cert.pem
    • Authentication → EAP with username and password

    Linux (strongSwan CLI)

    For headless Linux clients, install strongSwan and create a client-side swanctl.conf:

    bash
    sudo apt install -y strongswan strongswan-swanctl

    sudo cp ca-cert.pem /etc/swanctl/x509ca/

    sudo tee /etc/swanctl/conf.d/client.conf > /dev/null <<'EOF' connections { home { remote_addrs = vpn.example.com version = 2 vips = 0.0.0.0

    local { auth = eap-mschapv2 eap_id = [email protected] } remote { auth = pubkey id = vpn.example.com } children { home { remote_ts = 0.0.0.0/0 esp_proposals = aes256gcm16-ecp384,default } } } } secrets { eap-home { id = [email protected] secret = "ReplaceWithALongRandomPassword!" } } EOF

    sudo swanctl --load-all --noprompt sudo swanctl --initiate --child home

    Step 12: Site-to-Site Tunnel Example

    In a site-to-site topology, two strongSwan servers (or one strongSwan and one Cisco/FortiGate/AWS VPN Gateway) authenticate to each other with certificates or a pre-shared key (PSK) and route entire LAN subnets through the encrypted tunnel. No user authentication, no virtual IP pool — just two gateways and two subnets.

    Topology

    text
    Office A                          Office B
     10.0.1.0/24                       10.0.2.0/24
          |                                  |
      [Gateway A]  <== IPsec Tunnel ==>  [Gateway B]
      203.0.113.10                      198.51.100.20

    Configuration on Gateway A (Office A)

    Add a second connection block to /etc/swanctl/swanctl.conf. This example uses PSK for brevity — use certificates (auth = pubkey) for production:

    text
    connections {

    # ...existing ikev2-eap connection above...

    site-to-site-b { version = 2 proposals = aes256gcm16-prfsha384-ecp384,default mobike = no

    local_addrs = 203.0.113.10 remote_addrs = 198.51.100.20

    local { auth = psk id = 203.0.113.10 } remote { auth = psk id = 198.51.100.20 }

    children { office-b { local_ts = 10.0.1.0/24 remote_ts = 10.0.2.0/24

    esp_proposals = aes256gcm16-ecp384,default start_action = start dpd_action = restart close_action = restart rekey_time = 4h } } } }

    secrets { # ...existing eap secrets...

    ike-site-b { id-a = 203.0.113.10 id-b = 198.51.100.20 secret = "SuperLongRandomPSKAtLeast32Chars!!" } }

    Configuration on Gateway B (Office B)

    Mirror the configuration with local/remote swapped:

    text
    connections {
        site-to-site-a {
            version = 2
            local_addrs  = 198.51.100.20
            remote_addrs = 203.0.113.10

    local { auth = psk; id = 198.51.100.20 } remote { auth = psk; id = 203.0.113.10 }

    children { office-a { local_ts = 10.0.2.0/24 remote_ts = 10.0.1.0/24 start_action = start dpd_action = restart } } } }

    secrets { ike-site-a { id-a = 198.51.100.20 id-b = 203.0.113.10 secret = "SuperLongRandomPSKAtLeast32Chars!!" } }

    Activate and Verify

    On both gateways:

    bash
    sudo swanctl --load-all --noprompt
    sudo swanctl --list-sas

    Expected output (abbreviated):

    text
    site-to-site-b: #1, ESTABLISHED, IKEv2, ...
      local  '203.0.113.10' @ 203.0.113.10
      remote '198.51.100.20' @ 198.51.100.20
      AES_GCM_16-256/PRF_HMAC_SHA2_384/ECP_384
      established 12s ago, rekeying in ...
      office-b: #1, reqid 2, INSTALLED, TUNNEL, ESP:AES_GCM_16-256
        installed 12s ago, rekeying in 3h59m48s
        10.0.1.0/24 === 10.0.2.0/24

    From a host in Office A, ping a host in Office B:

    bash
    ping 10.0.2.5

    Traffic now flows through the IPsec tunnel, encrypted with AES-256-GCM.

    Logs, Monitoring, and Troubleshooting

    Real-Time Logs

    The strongSwan daemon logs to the systemd journal:

    bash
    sudo journalctl -u strongswan -f

    For more verbose debugging, increase the log level in /etc/strongswan.d/charon-logging.conf:

    text
    charon {
        filelog {
            charon {
                path = /var/log/charon.log
                default = 2
                ike = 2
                cfg = 2
                net = 1
            }
        }
    }

    Log level 2 = detailed, 3 = controlling messages, 4 = raw packet dumps. Restart strongSwan after editing:

    bash
    sudo systemctl restart strongswan
    sudo tail -f /var/log/charon.log

    Useful swanctl Commands

    CommandPurpose
    swanctl --list-connsShow loaded connection definitions
    swanctl --list-sasShow active IKE and CHILD security associations
    swanctl --list-certsShow loaded certificates
    swanctl --list-poolsShow virtual IP pools and usage
    swanctl --statsDaemon statistics (workers, queued jobs)
    swanctl --terminate --ike <name>Disconnect a specific IKE SA
    swanctl --rekey --ike <name>Force rekey of an IKE SA
    swanctl --reload-settingsReload /etc/strongswan.conf without restart

    Common Problems

    ProblemCauseFix
    Client connects but no internetMASQUERADE rule missing or wrong interfaceCheck iptables -t nat -L POSTROUTING -v; verify interface name with ip route
    IKE_SA established but CHILD_SA failedTraffic selector mismatch between client and serverEnsure local_ts = 0.0.0.0/0, ::/0 on server; check client's split-tunnel setting
    iOS/macOS: "VPN server did not respond"Firewall blocks UDP 500/4500Verify ufw status; check cloud provider firewall/security group
    EAP-Identity request was not answeredEAP username mismatch or password wrongConfirm id in secrets matches username exactly (case-sensitive)
    Server cert rejected by clientSAN missing client's connection targetReissue cert with --san matching every hostname/IP clients use
    Android: "VPN cannot be established"Missing CA trust on deviceInstall ca-cert.pem via Settings → Encryption & credentials → Install a certificate
    Slow throughput (<100 Mbps)Software crypto on older CPU without AES-NICheck cat /proc/cpuinfo \</td><td>grep aes; move to a CPU with AES-NI or switch to ChaCha20 proposal
    charon: no shared key found for S2SPSK identities not matching id-a / id-bEnsure id-a and id-b in secrets.ike-* match the local.id / remote.id on each side

    Packet Capture for Deep Debugging

    When a client cannot connect and the logs are unclear, capture the IKE exchange on the server:

    bash
    sudo tcpdump -i eth0 -n -v "udp port 500 or udp port 4500" -w /tmp/ike.pcap

    Let the client attempt to connect, then stop tcpdump (Ctrl+C) and inspect the capture in Wireshark with the IKE dissector. You can see exactly where the handshake fails (IKE_SA_INIT, IKE_AUTH, IKE_FRAGMENTATION).

    FAQ

    Is IPsec faster or slower than WireGuard?

    On the same hardware, WireGuard typically achieves 10-30% higher throughput than strongSwan IPsec, mostly because WireGuard does all its crypto in the kernel with a fixed, modern cipher suite (ChaCha20-Poly1305 or AES-GCM with hardware acceleration). strongSwan runs key management in userspace (the charon daemon) and hands established SAs to the kernel XFRM subsystem — the data-plane is comparable in speed, but connection setup is heavier. For a single-user home VPN, the difference is imperceptible. For a 10 Gbps VPN gateway, WireGuard has the edge.

    Can I use both certificate and EAP authentication?

    Yes. strongSwan supports EAP-TLS (client authenticates with a certificate instead of username/password) and EAP-MSCHAPv2 + client cert (mutual cert auth plus a username/password second factor). For EAP-TLS, change remote.auth = eap-mschapv2 to remote.auth = eap-tls and issue a client cert per user. For cert + EAP, use remote.auth = pubkey | eap-mschapv2 with a round = 2 block. See the strongSwan docs on EAP for the full syntax.

    How do I support more than ~250 concurrent clients?

    The default IPv4 pool 10.10.10.0/24 gives you 254 usable addresses. To scale up, either widen the pool (10.10.0.0/16 for ~65k clients) or add multiple pools and reference them in the connection with pools = pool1, pool2. Also bump /etc/strongswan.d/charon.conf parameters like charon.threads = 32 (default 16) and charon.ikesa_table_size = 4096 on busy servers. Run swanctl --stats to see current utilization.

    Why do I need both UDP 500 and UDP 4500?

    UDP 500 is the IKE control channel used when neither endpoint is behind NAT. UDP 4500 is used for IKE NAT-Traversal (RFC 3948) and for ESP-in-UDP encapsulation when the client is behind NAT — which almost all mobile devices are. Most real-world connections start on 500 and immediately migrate to 4500 after detecting NAT. Block either one and mobile clients will fail.

    How do I rotate the server certificate?

    Generate a new server cert with pki --issue (same CA, new key, new dates), copy it into /etc/swanctl/x509/ and the key into /etc/swanctl/private/, remove the old files, then run sudo swanctl --load-creds. Existing connections keep their old SAs until rekey. To force all clients to reconnect on the new cert, run sudo systemctl restart strongswan. Rotate the server cert every 12-24 months; rotate the CA only if compromised (it is valid for 10 years).

    Can strongSwan act as a VPN client instead of a server?

    Yes. Any host with strongSwan installed can --initiate outbound tunnels to another IKEv2 gateway (AWS VPN, Azure VPN Gateway, another strongSwan, a Cisco ASA, etc.). The Linux CLI example at the end of Step 11 shows this pattern. Use start_action = start in the children block to auto-connect at boot.

    Next Steps

    Now that strongSwan is running, consider these follow-ups to harden and extend the setup:

    • Enable RADIUS/AD authentication. Replace static EAP secrets with eap-radius and point strongSwan at a FreeRADIUS server backed by LDAP, Active Directory, or a cloud identity provider. Any user who gets deprovisioned in AD instantly loses VPN access.
    • Add a 2FA layer. Combine eap-radius with a TOTP module (Google Authenticator, Duo, privacyIDEA) so users need both a password and a rotating 6-digit code.
    • Monitor with Prometheus. Install prometheus-strongswan-exporter to scrape active SA counts, bytes transferred, and connection success rates into Grafana dashboards.
    • Compare to WireGuard for specific use cases. For a much simpler personal VPN, try our WireGuard guide. For SSL-VPN (TCP/443) that passes through restrictive firewalls, OpenConnect is the better choice. For legacy client compatibility, see OpenVPN.
    • Read the official docs. The strongSwan documentation has deep reference material on every plugin, cipher, and configuration option. Start with the swanctl.conf man page and the conf/keywords reference.
    • Automate provisioning. Script the pki commands and .mobileconfig generation so onboarding a new user takes one command instead of 15 minutes of manual work.

    Ready to deploy? Spin up a CloudCore Starter VPS — 2 vCPU, 4 GB RAM, 50 GB NVMe, unmetered bandwidth — and have your IKEv2 VPN online in under 40 minutes. All plans include KVM virtualization, IPv6, and full root access so you can build exactly the VPN stack your team needs.

    Was this article helpful?

    ← Back to Install GuidesBrowse all categories →

    Still have questions?

    Contact Support →Submit a Ticket