Security Recommendations

There are a couple of security-relevant topics that have to be considered when using strongSwan to set up IKE connections and policy-based IPsec tunnels.

Weak Cryptographic Algorithms

The following cryptographic algorithms are weak and prone to attacks and therefore must not be used.

Encryption
des,3des,cast,blowfish
Integrity Protection / Pseudo Random Functions
md5,sha1
Diffie-Hellman Groups
modp512,modp768,modp1024,modp1024s160,modp1536,modp2048s224,modp2048s256,ecp192

These algorithms do not directly relate to plugins. To disable them you must specify a set of crypto proposals that exclude these algorithms in the connection definitions of swanctl.conf

connections.<conn>.proposals
connections.<conn>.children.<child>.esp_proposals
connections.<conn>.children.<child>.ah_proposals

Do not set ah_proposals unless you want the CHILD_SA to use the AH (Authentication Header) IPsec protocol instead of the ESP (Encapsulating Security Payload) IPsec protocol or UDPENCAP (ESP in UDP Encapsulation) used when a NAT situation is detected or when UDPENCAP is explicitly enforced.

If no explicit proposals are defined in swanctl.conf then strongSwan uses its default proposals that neither propose nor accept any of the weak algorithms listed above, with the exception of 3des and sha1 which are still heavily used e.g. by Microsoft Windows.

Certificate Trust Chain Verification

If you want to enforce specific (strong) algorithms in the certificate chain of the peer, you can do this using the remote.auth settings in swanctl.conf.

Here is an example for enforcing the use of sha256, sha384 or sha512 in the certificate trust chain and to reject any other hashing algorithms. The same can be done for the algorithm of the actual pubkey (RSA or ECDSA).

Examples:

connection.<conn>.remote.auth = pubkey-sha256-sha384-sha512
connection.<conn>.remote.auth = rsa-sha256-sha384-sha512
connection.<conn>.remote.auth = ecdsa-sha384

Cipher Selection

The available ciphers for IKE depend on the crypto modules loaded in the IKE charon daemon. For kernel processing of ESP and AH packets the available ciphers depend on the kernel support for them and if they are supported by the XFRM or PF_KEY kernel interface.

It is advised to adhere to the recommendation of the appropriate security authority when choosing ciphers to secure the tunnel cryptographically. keylength.com lists some of the standards for western Europe and the US. It is strongly advised to use at least a 2048 bit key length for MODP Diffie-Hellman groups.

The National Institute of Standards and Technology (NIST) has mandated that a minimum cryptographic strength of 128 bit is sufficient for security beyond the year 2030. This results in the following cipher set:

aes128-sha256-modp3072

For systems without support for SHA-256, SHA-1 might be used instead. SHA-1 must not be used for anything else than an HMAC for IKE or ESP.

Alternatively the Commercial National Security Algorithm (CNSA) Suite may also be used where supported

aes256-sha384-ecp384,aes256gcm16-prfsha384-ecp384

The supported IKEv2 cipher suites are limited to what the various libstrongswan plugins implement.

The supported ESP/AH cipher suites are limited to what the Linux kernel supports. If you’re using userland ESP encryption based on the kernel-libipsec plugin then all IKE algorithms are also available for ESP.

Preshared Keys

There is nothing to be said against Pre-Shared Keys (PSKs) as long as they are chosen randomly with sufficient entropy. The openssl rand command can be used to generate a PSK with >256 bit entropy converted to base64 format:

$ openssl rand -base64 33
bjsqbPZB3Isk/RHMCH6Pe9G+TDc4tJVmbvRlWLXMSjS+

Alternatively the dd command can be used to directly retrieve the entropy either from /dev/random or the non-blocking /dev/urandom device

$ dd if=/dev/random count=1 bs=33 2>/dev/random | base64
s1Jy/Li0Bkqmd3C7eYG71EoPxmcataF/LL4ATA3gE+au

The PSK can then be used in the secrets section of swanctl.conf to configure the IKE user credentials

secrets {
  ike-alice {
    id = alice@strongswan.org
    secret = 0sbjsqbPZB3Isk/RHMCH6Pe9G+TDc4tJVmbvRlWLXMSjS+
  }
  ike-bob {
    id = bob@strongswan.org
    secret = 0ss1Jy/Li0Bkqmd3C7eYG71EoPxmcataF/LL4ATA3gE+au
  }
}

For base64-encoded secrets the 0s prefix is used whereas 0x designates a hex-encoded value.

IKEv1 Aggressive Mode with PSK Authentication

IKEv1 Aggressive Mode is inherently flawed, as a hash of the PSK is transmitted in the clear, which a passive attacker can directly use to try to crack the password using an offline dictionary or brute force attack. Thus it is strongly advised to avoid IKEv1 Aggressive Mode.

MITM Attacks on IKEv2 PSK Authentication

If user credentials don’t have enough entropy what is usually the case if you let the users freely choose their passwords, then PSK-based IKEv2 authentication is vulnerable to active Man-In-The-Middle (MITM) attacks.

Since a VPN client is usually the IKEv2 initiator, it sends its AUTH payload containing the password hash in the IKE_AUTH request to an unauthenticated and thus untrusted VPN server. If an attacker inserts herself into the IKE connection between client and server she can intercept the AUTH payload and start an offline dictionary or brute force attack on the PSK.

Thus it is of utmost importance that cryptographically strong PSKs are used with PSK-based authentication. Since in most cases this cannot be enforced, we highly recommend to use EAP-based authentication instead where the VPN server is authenticated first based on a X.509 server certificate, so that the VPN client can then send its [potentially weak] password hash later on to a trusted peer.

Certificate-based Authentication

Certificate-based authentication is inherently stronger than PSK-based authentication. A properly built PKI architecture has usually one root CA and one or several intermediate CAs, where the private key of the intermediate CA is used to sign the end entity certificates and the private key of the root CA can be kept on a smartcard stored in a safe or at lease on a system disconnected from the Internet. The private root CA key is never stored on an insecure or online system. Securing the root CA enables the PKI administrator to revoke any certificates and recreate the PKI from scratch, if any intermediate CAs are compromised.

Using the default revocation plugin, Certificate Revocation Lists (CRLs) and the Online Certificate Status Protocol (OCSP) can be used to check if a given certificate has been revoked for some reason. strongSwan supports locally-stored CRLs, as well as fetching fresh CRLs and OCSP information via the fetcher plugins curl, soup or winhttp.

CRL Distribution Points (CDPs) are either retrieved from the certificate or can be added manually using an authorities section in swanctl.conf.

X.509 certificates should be based on RSA public keys with a modulus of at least 2048 bits (preferably 3072 bits for end entity certificates and 4096 bits for CA certificates). Alternatively ECDSA public keys with at least 256 bits (preferably 384 bits) can be used. For certificate signatures at least SHA-256 must be used since both SHA-1 and MD5 are hopelessly broken. All X.509 certificates must conform to the PKIX Internet standard (RFC 5280).

Perfect Forward Secrecy

Perfect Forward Secrecy (PFS) is strongly recommended to make IPsec peers negotiate an independent session key for each IPsec or CHILD SA. This protects the long-term confidentiality of the IPsec traffic if the IKE shared secret is leaked. Note that the session keys of the first CHILD_SA of a new IKEv2 connection are derived from the IKE shared secret. However, subsequent CHILD_SAs will use independent keys if PFS is used.

PFS is enabled by appending a DH group to the ESP or AH cipher proposal. Using PFS introduces no significant performance overhead, unless you rekey more than about 80 CHILD_SAs per second.

Tunnel Shunting

As IPsec connections on Linux are usually policy-based, there is no tunnel interface over which packets are routed. Instead XFRM policies and states transform the packet transparently.

Note that any traffic for which there is no matching IPsec policy will not be subject to IPsec processing. This can cause traffic leakage into your LAN and into the attached WAN. Such a scenario can occur when your site-to-site tunnel is configured with start_action = none and your firewall rules do not drop packets that should be protected with IPsec but actually aren’t.

Usually it is highly undesired to let such traffic just pass. Take care to shunt the connections correctly using the policy match module in iptables.

It is strongly advised to use start_action = trap in site-to-site setups to make sure that the kernel tells the charon daemon to establish a CHILD_SA when there is no SA for a security policy. It is advisable to take a look at the strongswan.conf setting charon.ignore_acquire_ts when doing this.

RFC1918 private networks and others that are not allowed to be used on the public Internet must not occur in the source or destination fields of an IP packet. A suitable method to prevent that is to use an iptables rule that rejects or drops packets with such a destination without a matching IPsec policy using the policy match module. An alternative is to use a DROP policy in the configuration with a higher priority than the normal IPsec policies. If you do not know the priorities of your normal rules, check them with ip xfrm policy. If the priorities automatically computed by the charon daemon based on the traffic selectors do not fit (see kernel_netlink_ipsec.c) then the priority of the XFRM policies can be set manually in swanctl.conf via the <child>.priority attribute.

If you NAT traffic into the tunnel by using DNAT, SNAT or MASQUERADE, the traffic selector of the DROP policy must be adjusted accordingly. The IPsec SPD in the kernel or the charon daemon are not aware of your firewall’s NAT rules. Again the priority of the DROP policy must be higher than the one of your normal policies.

DROP Policy Example

connections {
  shunts {
    rekey_time = 0
    local_addrs = 127.0.0.1
    remote_addrs = 127.0.0.1

    children {
      # prevent unprotected traffic from any network to the roadwarriors
      drop-rwv4 {
        # internet
        local_ts  = 0.0.0.0/0
        # roadwarrior subnet
        remote_ts = 172.16.20.0/24
        mode = drop
        start_action = trap
      }
      # enabling policies_fwd_out is necessary for other children to avoid forwarded traffic from getting dropped
    }
  }
}

In the following example, the REJECT target is used to give the user a clear error message.

iptables -A FORWARD -d 10.0.0.0/8 -m policy --pol none --dir out -j REJECT --reject-with icmp-admin-prohibited

Generally it is important to understand how iptables/Netfilter work together with XFRM to design suitable firewall rules that protect your network in case tunnels go down or can not be brought up. When NAT is brought into the discussion, it can be impossible to design a general rule in iptables that just drops the unprotected packets and specific rules need to be inserted for your specific NATed addresses.

Of course, there are more networks than 10.0.0.0/8 that fulfill the aforementioned criteria, including IPv6 subnets. More information on these address ranges can be found RFC 1918, RFC 3927 and RFC 6890.