Skip to content

Last updated: 2026-02-13

strongSwan TLS/IPsec Configuration Guide

This guide provides recommended IKEv2/IPsec settings for strongSwan to establish encrypted VPN tunnels using certificate-based authentication. strongSwan implements the IKEv2 protocol with modern cryptographic algorithms for secure site-to-site and remote access VPN connections.

Prerequisites

RHEL/CentOS: Install with dnf install strongswan.

Debian/Ubuntu: Install with apt install strongswan strongswan-pki.

Certificate Setup

Generate Certificates with strongSwan PKI

# Generate a CA private key and certificate
pki --gen --type rsa --size 4096 --outform pem > /etc/strongswan/ipsec.d/private/ca-key.pem
pki --self --ca --lifetime 3650 --in /etc/strongswan/ipsec.d/private/ca-key.pem \
    --dn "CN=VPN CA" --outform pem > /etc/strongswan/ipsec.d/cacerts/ca-cert.pem

# Generate a server private key and certificate
pki --gen --type rsa --size 2048 --outform pem > /etc/strongswan/ipsec.d/private/server-key.pem
pki --req --type priv --in /etc/strongswan/ipsec.d/private/server-key.pem \
    --dn "CN=vpn.example.com" --san vpn.example.com --outform pem > server.csr
pki --issue --cacert /etc/strongswan/ipsec.d/cacerts/ca-cert.pem \
    --cakey /etc/strongswan/ipsec.d/private/ca-key.pem \
    --type pkcs10 --in server.csr --serial 01 --lifetime 365 \
    --flag serverAuth --flag ikeIntermediate \
    --san vpn.example.com --outform pem > /etc/strongswan/ipsec.d/certs/server-cert.pem

Using Existing Certificates

If you have certificates from an external CA:

cp ca.crt /etc/strongswan/ipsec.d/cacerts/ca-cert.pem
cp server.crt /etc/strongswan/ipsec.d/certs/server-cert.pem
cp server.key /etc/strongswan/ipsec.d/private/server-key.pem

chmod 600 /etc/strongswan/ipsec.d/private/server-key.pem

Set Permissions

chmod 600 /etc/strongswan/ipsec.d/private/*.pem
chown root:root /etc/strongswan/ipsec.d/private/*.pem

swanctl Configuration

strongSwan 5.7+ uses swanctl.conf as the primary configuration format. The file is located at /etc/strongswan/swanctl/swanctl.conf.

IKEv2 Proposals

Configure strong cryptographic proposals for the IKE (control) channel:

connections {
    vpn {
        version = 2

        proposals = aes256gcm16-sha384-x25519,aes256gcm16-sha384-ecp384,aes128gcm16-sha256-x25519,aes128gcm16-sha256-ecp256
    }
}

ESP (Data Channel) Proposals

Configure the ESP proposals for encrypting tunnel traffic:

connections {
    vpn {
        children {
            net {
                esp_proposals = aes256gcm16-sha384,aes128gcm16-sha256,chacha20poly1305-sha256
            }
        }
    }
}

Configuration Explained

Certificate Authentication

Configure certificate-based authentication in the connection:

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

Complete Configuration

swanctl.conf

connections {
    vpn {
        version = 2
        rekey_time = 86400
        dpd_delay = 30

        # IKE proposals (control channel)
        proposals = aes256gcm16-sha384-x25519,aes256gcm16-sha384-ecp384,aes128gcm16-sha256-x25519,aes128gcm16-sha256-ecp256

        # Local (server) authentication
        local {
            auth = pubkey
            certs = server-cert.pem
            id = vpn.example.com
        }

        # Remote (client) authentication
        remote {
            auth = pubkey
            cacerts = ca-cert.pem
        }

        # Child SA (tunnel)
        children {
            net {
                local_ts = 10.0.0.0/24
                esp_proposals = aes256gcm16-sha384,aes128gcm16-sha256,chacha20poly1305-sha256
                rekey_time = 3600
                dpd_action = restart
            }
        }
    }
}

secrets {
    private {
        file = server-key.pem
    }
}

Remote Access (Road Warrior)

For remote access VPN with virtual IP assignment:

connections {
    roadwarrior {
        version = 2
        proposals = aes256gcm16-sha384-x25519,aes128gcm16-sha256-x25519

        pools = client_pool

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

        children {
            roadwarrior {
                local_ts = 0.0.0.0/0
                esp_proposals = aes256gcm16-sha384,aes128gcm16-sha256
            }
        }
    }
}

pools {
    client_pool {
        addrs = 10.10.10.0/24
        dns = 10.0.0.1
    }
}

Client Configuration

Generate Client Certificate

pki --gen --type rsa --size 2048 --outform pem > client-key.pem
pki --req --type priv --in client-key.pem --dn "CN=client@example.com" --outform pem > client.csr
pki --issue --cacert /etc/strongswan/ipsec.d/cacerts/ca-cert.pem \
    --cakey /etc/strongswan/ipsec.d/private/ca-key.pem \
    --type pkcs10 --in client.csr --serial 02 --lifetime 365 \
    --flag clientAuth --outform pem > client-cert.pem

Export as PKCS#12 for import into clients:

openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem \
    -certfile /etc/strongswan/ipsec.d/cacerts/ca-cert.pem \
    -out client.p12 -name "VPN Client"

Native Client Support

Verification

Load the configuration and start the connection:

swanctl --load-all
swanctl --list-conns

Check active security associations:

swanctl --list-sas

View the negotiated algorithms:

swanctl --list-sas --raw

Check strongSwan logs for IKE negotiation details:

grep -i ike /var/log/syslog

Verify the connection from a client:

swanctl --initiate --child net
swanctl --list-sas