Strongswan with Let’s Encrypt on CentOS and RHEL
I have been trying to set up a VPN on my Linode running RHEL 7. Many of the tutorials for this involve creating self-signed certificates, but why? I already have a perfectly valid Let’s Encrypt certificate available–I want to use that to secure my connection!
This is how I did it.
Assumptions
- Let’s Encrypt installed and certificate generated
- EPEL repository for CentOS / Red Hat Enterprise Linux installed and activated
- Server FQDN:
server.mydomain.com
- Certificates located in
/etc/letsencrypt/live/mydomain.com/
- Strongswan configuration located in
/etc/strongswan/
Install Strongswan
As root, yum install strongswan
. If the package can’t be found, you probably don’t have EPEL installed and activated. Go back and do that.
Link Let’s Encrypt certificates to Strongswan
Create symlinks from the Let’s Encrypt certificates to Strongswan’s certificate store.
ln -s /etc/letsencrypt/live/mydomain.com/fullchain.pem /etc/strongswan/ipsec.d/certs/fullchain.pem
ln -s /etc/letsencrypt/live/mydomain.com/privkey.pem /etc/strongswan/ipsec.d/private/privkey.pem
ln -s /etc/letsencrypt/live/mydomain.com/chain.pem /etc/strongswan/ipsec.d/cacerts/chain.pem
This way, when they renew every 90 days, Strongswan has access to the new certificates.
Configure Strongswan
In your favourite editor, open /etc/strongswan/ipsec.conf
, and add the following. Be sure to update leftid
with your server’s domain name.
config setup
uniqueids=no
charondebug = ike 3, cfg 3
conn %default
dpdaction=clear
dpddelay=35s
dpdtimeout=2000s
keyexchange=ikev2
auto=add
rekey=no
reauth=no
fragmentation=yes
compress=yes
### left - local (server) side
# filename of certificate chain located in /etc/strongswan/ipsec.d/certs/
leftcert=fullchain.pem
leftsendcert=always
leftsubnet=0.0.0.0/0,::/0
### right - remote (client) side
eap_identity=%identity
rightsourceip=10.1.1.0/24,2a00:1450:400c:c05::/112
rightdns=8.8.8.8,2001:4860:4860::8888
conn ikev2-mschapv2
rightauth=eap-mschapv2
conn ikev2-mschapv2-apple
rightauth=eap-mschapv2
leftid=server.mydomain.com
Add VPN username and passwords
In your favourite editor, open /etc/strongswan/ipsec.secrets
and add usernames and plain-text passwords for the user you want to use.
# filename of private key located in /etc/strongswan/ipsec.d/private/
: RSA privkey.pem
# syntax is `username : EAP "plaintextpassword"`
rusty : EAP "IAmRustyTheMoodle"
If you need help generating a random, secure password, you can use openssl rand -base64 24
to generate one.
Open firewalld
Red Hat and CentOS use firewalld
to configure iptables
firewall and routing. Assuming your default and active zone is public
, the following will open and forward the correct ports and protocols.
firewall-cmd --zone=public --permanent --add-rich-rule='rule protocol value="esp" accept'
firewall-cmd --zone=public --permanent --add-rich-rule='rule protocol value="ah" accept'
firewall-cmd --zone=public --permanent --add-port=500/udp
firewall-cmd --zone=public --permanent --add-port=4500/udp
firewall-cmd --zone=public --permanent --add-service="ipsec"
firewall-cmd --zone=public --permanent --add-masquerade
firewall-cmd --reload
Confirm the changes with firewall-cmd --list-all
.
Configure sysctl
to allow packet forwarding
In your favourite editor, open /etc/sysctl.conf
and add the following:
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
Apply changes with sysctl -p
, or with a restart.
Start Strongswan
As the super user, systemctl start strongswan
. If you are feeling confident, you can enable the service so it starts automatically at boot with systemctl enable strongswan
.
Confirm that certificates are loaded correctly with strongswan listcerts
, and ensure your Let’s Encrypt certificate appears, and shows “has private key” in the pubkey
section:
# strongswan listcerts
List of X.509 End Entity Certificates
subject: "CN=mydomain.com"
issuer: "C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3"
validity: not before Nov 13 10:51:00 2016, ok
not after Feb 11 10:51:00 2017, ok (expires in 70 days)
serial: aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99:aa
altNames: server.mydomain.com, mydomain.com
flags: serverAuth clientAuth
OCSP URIs: http://ocsp.int-x3.letsencrypt.org/
certificatePolicies:
2.23.140.1.2.1
1.3.6.1.4.1.44947.1.1.1
CPS: http://cps.letsencrypt.org
authkeyId: aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99:aa
subjkeyId: aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99:aa
pubkey: RSA 2048 bits, has private key
keyid: aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99:aa
subjkey: aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99:aa
Configure clients
Windows is able to auto-detect the type of VPN, and does a fine job of guiding the input of authentication details.
In OS X, be sure to select IKEv2 when adding a VPN, and the Remote ID
setting is the leftid
setting in ipsec.conf
. Don’t forget to add your username and password from ipsec.secret
in Authentication Settings
.
Troubleshooting
Something not working? tail -f /var/log/messages
as the superuser, and try connecting. Debug information will be output, which should guide resolution.
References
Changelog
- 2016-12-03: Simplified
ipsec.conf
. Updated references. Fixed newline issue with firewalld.