IPsec with Libreswan

Libreswan is a free software implementation of the most widely supported and standardized VPN protocol, IPsec.

On Android, the arrangement in this particular tutorial is called “IPsec XAUTH PSK.” On iOS, it is called simply “IPsec.”

IPsec uses fixed port numbers and is therefore easily blocked by censors. Nevertheless, there may be situations where ease-of-use is your top priority. Many client devices support IPsec without the installation of additional software.

This article shows you how to create an IPsec server on CentOS 8. Note that CentOS 8 goes end-of-life on December 31, 2021. For this reason, we include appendices discussing Debian/Ubuntu.

In the examples, your workstation is at IP address xx.xx.xx.xx, and the server is at IP address yy.yy.yy.yy. Wherever you see these values in the examples, you will need to change them to match your actual IP addresses. If you do not know your workstation’s IP address, you can determine it by opening a browser and visiting IPchicken.com.

We also give instructions for a sample mobile client. Mobile devices are easily tracked and strongly linked to an individual. Again, we assume in this scenario that ease-of-use is your main concern and that you are in a country where IPsec is not blocked.

1. Server

1.1. Install and Configure Firewall

We begin by installing a firewall and configuring it to accept IPsec. We also masquerade outgoing IP addresses. Issue the commands that follow:

yum update -y
yum install firewalld -y
systemctl enable firewalld
systemctl start firewalld
firewall-cmd --add-service=ipsec
firewall-cmd --add-masquerade
firewall-cmd --runtime-to-permanent

For better security, restrict port 22 access to trusted IP addresses only. For example, if you always log in from IP address xx.xx.xx.xx, make that the only IP address that will be trusted for SSH access:

firewall-cmd --zone=trusted --add-service=ssh
firewall-cmd --zone=trusted --add-source=xx.xx.xx.xx/32
firewall-cmd --zone=public --remove-service=ssh
firewall-cmd --zone=public --remove-service=cockpit
firewall-cmd --runtime-to-permanent

1.2. Allow Forwarding

Now enable packet forwarding in the Linux kernel. Create a new configuration file in /usr/lib/sysctl.d:

vi /usr/lib/sysctl.d/40-ipv4-forward.conf

Insert a single line:

net.ipv4.ip_forward=1

Save the file. Make this change effective immediately.:

sysctl -p /usr/lib/sysctl.d/40-ipv4-forward.conf

1.3. Install Package

Install Libreswan from the repository:

yum install libreswan -y

1.4. Set Up Preshared Key

Edit the IPsec secrets file:

vi /etc/ipsec.d/psk.secrets

Insert a line with your preshared key. We will use as an example a preshared key of ArnieBooksCello:

%any: PSK "ArnieBooksCello"

Save the file.

1.5. Set Up Usernames and Passwords

Suppose we have three users, alice, bob, and carol. Their passwords are Apple123, Bravo456, and Caper789 respectively.

Compute the SHA512 hash of the first password:

openssl passwd -6 Apple123

The result is displayed as $6$/X60NLa1wFgWDYIC$PYsPW.lsCALxSgRi0NmKcLVJPY.tPZwRZIs9OoYy3o/KimObc9GKkVfkpzhaA/jxM15eW.F6AcFqYdElsuJoO..

Compute the SHA512 hash of the second password:

openssl passwd -6 Bravo456

The result is displayed as $6$U7Z3b.871AFnz6M8$lUB18T5gwQS/yPxjPqeNbUNCWpDsCHxmRNZy6dURpEc6cteX8NwBSB4HboNMTer/a642XadEv.T3ses8c33Y3/.

Compute the SHA512 hash of the third password:

openssl passwd -6 Caper789

The result is displayed as $6$hbiPDOhJPoEBpAN2$IsKhAZvKLMuuICDafbkW5STmsBhC7HuWNZwmJ/l2z7CzcQbZNoie5i0ye5Lpusz43JEbhQR9.jR6In1yWyw1N0.

Create a password file:

vi /etc/ipsec.d/passwd

Insert usernames and passwords like this:

alice:$6$/X60NLa1wFgWDYIC$PYsPW.lsCALxSgRi0NmKcLVJPY.tPZwRZIs9OoYy3o/KimObc9GKkVfkpzhaA/jxM15eW.F6AcFqYdElsuJoO.:xauth-psk
bob:$6$U7Z3b.871AFnz6M8$lUB18T5gwQS/yPxjPqeNbUNCWpDsCHxmRNZy6dURpEc6cteX8NwBSB4HboNMTer/a642XadEv.T3ses8c33Y3/:xauth-psk
carol:$6$hbiPDOhJPoEBpAN2$IsKhAZvKLMuuICDafbkW5STmsBhC7HuWNZwmJ/l2z7CzcQbZNoie5i0ye5Lpusz43JEbhQR9.jR6In1yWyw1N0:xauth-psk

Save the file.

1.6. Configure Libreswan

Create a new file for IPsec connections with a preshared key:

vi /etc/ipsec.d/ipsec.conf

Insert lines specifying a configuration like this:

config setup
 protostack=netkey
 virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
 uniqueids=no
conn xauth-psk
 authby=secret
 pfs=no
 auto=add
 rekey=no
 left=%defaultroute
 leftsubnet=0.0.0.0/0
 rightaddresspool=10.0.8.64-10.0.8.127
 right=%any
 cisco-unity=yes
 modecfgdns=8.8.8.8
 leftxauthserver=yes
 rightxauthclient=yes
 leftmodecfgserver=yes
 rightmodecfgclient=yes
 modecfgpull=yes
 xauthby=file
 ike-frag=yes
 ikev2=no
 ike=aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024
 esp=aes256-sha2_512,aes256-sha1,aes256-sha2_256,3des-sha1

Save the file.

1.7. Start Libreswan

Start Libreswan after every reboot, and also start it now:

systemctl enable ipsec
systemctl start ipsec

1.8. Check Libreswan

Check that Libreswan is active and running:

systemctl status ipsec

2. Android Client

The place where you add a VPN in Android varies from release to release. It may be under Settings > Network & Internet > Advanced > VPN or it may be under Settings > Connections > More networks > VPN.

Add a new VPN:

Click Save. Select the VPN, and click Connect.

3. iOS Client

Go to Settings > General > VPN.

Add a new VPN configurration:

Click Done. Select the VPN, and toggle it to the ON position.

4. Get Help and Report Issues

Examine the logs with:

grep pluto /var/log/secure

For your client device in general, seek support through the normal channels for that device.

For Libreswan, support arrangements are listed in the Libreswan wiki.

Appendix A. Notes for Debian/Ubuntu

Appendix A.1. Nftables Firewall for Debian/Ubuntu

A firewall for IPsec may be built with nftables as follows, with xx.xx.xx.xx representing your workstation’s IP address.

Install nftables:

apt install nftables -y
systemctl enable nftables
systemctl start nftables

Set up the basic rules:

nft add rule inet filter input ct state related,established counter accept
nft add rule inet filter input iif lo counter accept
nft add rule inet filter input ip protocol icmp icmp type echo-request counter accept
nft add rule inet filter input ip6 nexthdr icmpv6 icmpv6 type echo-request counter accept

Open port 22 for SSH. If you can restrict the port 22 rule so that only certain source IP addresses are whitelisted for SSH access, then so much the better.

nft add rule inet filter input t***** dport 22 ip saddr xx.xx.xx.xx/32 counter accept

Open ports 500/udp and 4500/udp and protocols 50 and 51 for IPsec:

nft add rule inet filter input udp dport 500 counter accept
nft add rule inet filter input udp dport 4500 counter accept
nft add rule inet filter input ip protocol ah counter accept
nft add rule inet filter input ip protocol esp counter accept

Drop all unexpected input:

nft add rule inet filter input counter drop

Masquerade outgoing IP addresses:

nft add table nat
nft add chain nat prerouting { type nat hook prerouting priority 0 \; }
nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule nat postrouting ip saddr 10.0.8.64/26 masquerade

Save all these rules so that they persist across reboots:

nft list ruleset > /etc/nftables.conf

Appendix A.2. Allow Forwarding on Debian/Ubuntu

On Debian/Ubuntu you create your sysctl configuration file in /etc/sysctl.d:

vi /etc/sysctl.d/40-ipv4-forward.conf

Insert a single line:

net.ipv4.ip_forward=1

Save the file. Make this change effective immediately.:

sysctl -p /etc/sysctl.d/40-ipv4-forward.conf

Appendix A.3. MODP1024 on Debian/Ubuntu

Libreswan version 3.30 (February 13, 2020) disabled support for DH2/modp1024 at compile time. Ubuntu 20.04 was the last release to include Libreswan 3.29; Debian 10 “buster” included Libreswan 3.27.

The problem is that some Windows and Android devices still require modp1024 to work.

On Ubuntu 20.10+ and Debian 11+ your choices are therefore:

A sample compile procedure for Libreswan on Debian/Ubuntu is as follows.

Install the prerequisites for the compile:

apt update && apt upgrade -y
apt install -y libnss3-dev libnspr4-dev pkg-config libpam-dev libcap-ng-dev libcap-ng-utils libselinux-dev libcurl3-nss-dev flex bison gcc make libldns-dev libunbound-dev libnss3-tools libevent-dev xmlto libsystemd-dev

Visit https://download.libreswan.org to determine which release you want to use. We will use release 4.4 as our example. Download the source tarball.

wget https://download.libreswan.org/libreswan-4.4.tar.gz

Extract the tarball:

tar -xf libreswan-4.4.tar.gz

Change into the top-level directory for the source:

cd libreswan-4.4

Build Libreswan with USE_DH2 defined:

make CFLAGS="-DUSE_DH2"

Install Libreswan:

make install

If you are going to use the certificate utility certutil, then initialize the Network Security Services (NSS) database:

ipsec initnss

The NSS database is created in /var/lib/ipsec/nss.

Configure your server’s firewall as described in appendix A.1 above to accept protocol 50, protocol 51, input 500/udp and 4500/udp, and also to masquerade the IP address on outbound packets.

Allow forwarding in the Linux kernel as in described in appendix A.2 above.

Set up your parameter files in the /etc/ipsec.d directory, as explained in the sections for CentOS 8, except that in /etc/ipsec.d/ipsec.conf the parameter ike-frag=yes has now been replaced by fragmentation=yes:

Once you’ve set everything up, start Libreswan:

systemctl start ipsec

Appendix A.4. Libreswan Log on Debian/Ubuntu

On Debian/Ubuntu, examine the logs with:

grep pluto /var/log/auth.log

Updated 2021-06-17