Skip to content

Instantly share code, notes, and snippets.

@oikuda
Last active August 15, 2018 12:28
Show Gist options
  • Save oikuda/9707153e958c3e447f93ebe0e1a1352b to your computer and use it in GitHub Desktop.
Save oikuda/9707153e958c3e447f93ebe0e1a1352b to your computer and use it in GitHub Desktop.
Strongswan IPsec VPN server (RPi3, PC) setup

Intro

First off, the scenario I deployed is on a Linux machine sitting behind a home router (NAT box). The machine we're doing the setup will be called tux.

Clients ---- Internet ---- ISP ---- Router(NAT) ---- tux(Strongswan)

For this to work port 500 and 4500 on your Router(NAT) should be forwarded to tux.

If you don't have a static IP with yout provider, you should consider a dynamic DNS service that will update the DNS address every day, when the address changes.

NOTE: I preferred to build strongswan from source to get the newest algorithms and Ed25519 curve support instead of standard EC curves. Safecurves

Tools needed for installation from source

  • build tools and libraries (1_install_prerequisites.sh)
    • build-essential - for building from source
    • libgmp-dev - for EC algorithms
    • libssl-dev - for openssl support and pubkey authentication
    • syslog-ng - for easier debugging
  • strongswan source (used version 5.6.0) (2_get_and_build_ss.sh)
    • for the enabled options see Strongswan plugins
    • openssl is enabled for handling certificates
    • chapoly, sha3, gcm, ccm and ctr for support of modern ciphers and AEAD support
    • dhcp and farp for forwarding DHCP requests to the DHCP server, and farp to enable tux to represent the node on the network
    • eap plugins for various authentication modes
    • disabled unsecure algorithms: des, rc2 sha1, fips-prf

Installation from repository

apt-get install strongswan libstrongswan-extra-plugins libcharon-extra-plugins

Configuration

After installing prerequisites and building strongswan we need to configure strongswan and start the daemon.

Configuration is done in the following files:

  • /etc/ipsec.conf (3_ipsec.conf)
  • /etc/ipsec.d/ (4_gen_certs.sh)
    • cacerts/
    • private/
    • certs/
  • /etc/ipsec.secrets (5_ipsec.secrets) - configure other usernames and passwords
  • /etc/sysctl.conf - enable IP forwarding and other stuff:
net.ipv4.ip_forward = 1
net.ipv4.ip_no_pmtu_disc = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

After all this is configured, store the caKey somewhere safe and make the caCert.pem and CA.crt available to clients.

Now clients can connect using the defined credentials in ipsec.secrets conf.

Client key generation (only ECDSA for now, missing openssl support)

For this we could use the pregenarated CA key, BUT it is definately safer to generate a new CA key and deploy the caClientCert.pem in the cacerts folder on the tux. Generation of the clientCa.key and cert is done as follows:

ipsec pki --gen --type ed25519 --outform pem > caClientKey.pem
ipsec pki --self --in caClientKey.pem --dn "C=US, O=place, CN=strongSwan Client CA" --ca --outform pem > caClientCert.pem

To generate the client certificates use the 6_gen_user_certs.sh on the where caClientKey.pem and caClientCert.pem is aavaliable.

Connecting with clients

I have tested the Android strongswan client and Linux (arch, ubuntu, debian) with charon-cmd.

Android setup is straightforward after you transfer the caCert and put it into the application.

charon-cmd examples (need to be executed as root):

# EAP mschapv2 example - asks for password
charon-cmd --host some.place.net --identity alice --cert caCert.pem
# Pubkey example
charon-cmd --host some.place.net --identity alice --cert caCert.pem --p12 carol.p12
apt-get update
apt-get install wget apt-utils
apt-get install build-essential libgmp-dev libssl-dev
apt-get install syslog-ng
wget https://download.strongswan.org/strongswan-5.6.0.tar.bz2
tar xf strongswan-5.6.0.tar.bz2
cd strongswan-5.6.0
./configure --prefix=/usr --sysconfdir=/etc \
--enable-openssl --enable-chapoly --enable-sha3 \
--enable-gcm --enable-ccm --enable-ctr \
--enable-dhcp --enable-farp \
--enable-eap-identity --enable-eap-md5 \
--enable-eap-mschapv2 --enable-eap-tls \
--enable-eap-ttls --enable-eap-peap \
--disable-des --disable-rc2 --disable-sha1 --disable-fips-prf
make -j4
# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
# strictcrlpolicy=yes
# uniqueids = no
charondebug="ike 2, cfg 2, net 2, dmn 2"
conn %default
keyexchange=ikev2
### enable only if all clients support these algorithms
# ike=chacha20poly1305-prfsha512-curve25519,chacha20poly1305-prfsha384-curve25519,aes256gcm16-prfsha384-curve25519,aes128gcm16-prfsha256-curve25519!
dpdaction=clear
closeaction=clear
dpddelay=180s
left=%any
leftauth=pubkey
leftcert=serverCert.pem
# use this to limit the remote traffic selector, this enables access through all addresses
leftsubnet=0.0.0.0/0
right=%any
rightsourceip=%dhcp
### enable this only if you have kernel support (check `cat /proc/crypto`)
# esp=chacha20poly1305-x25519,aes256gcm128-x25519,aes192gcm128-x25519,aes128gcm128-x25519!
# connection using password authentication for alice and bob
conn rw-eap
rightauth=eap-mschapv2
eap_identity=%any
auto=add
# connection using pubkey authentication for generated client certificates signed with
# a new caKey used just for client certificates
conn rw-pubkey
rightauth=pubkey
auto=add
######
# NOTE: change H and IP and also dn (distinguished name) parameters in the rest of the script
######
export H="some.place.net"
export IP=$H
### IP definition needed only if no DNS entry has your static IP
# export IP="xxx.xxx.xxx.xxx"
# generate CA private key - store this somewhere else safe to prevent MITM attacks in the future
ipsec pki --gen --type ed25519 --outform pem > caKey.pem
# generate CA cert
ipsec pki --self --in caKey.pem --dn "C=US, O=place, CN=strongSwan CA" --ca --outform pem > caCert.pem
# generate server key
ipsec pki --gen --type ed25519 --outform pem > serverKey.pem
# generate server cert
ipsec pki --pub --in serverKey.pem | ipsec pki --issue --cacert caCert.pem --cakey caKey.pem \
--dn "C=US, O=place, CN=$H" --san="$IP" \
--flag serverAuth --flag ikeIntermediate --outform pem > serverCert.pem
# generate server cert in DER format
openssl x509 -inform PEM -outform DER -in caCert.pem -out CA.crt
# deploy certs
cp caCert.pem /etc/ipsec.d/cacerts/
cp serverCert.pem /etc/ipsec.d/certs/
cp serverKey.pem /etc/ipsec.d/private/
: PKCS8 serverKey.pem
alice : EAP "B2iFEm5pwcgNH1qb"
bob : EAP "qse0TU1p4y49LBSF"
#!/bin/bash
set -e
if [ -z "$1" ]; then
echo "No argument supplied. Specify username as first argument"
exit
fi
key="$1_key.pem"
cert="$1_cert.pem"
p12="$1.p12"
name="[email protected]"
key_type="ecdsa --size 384"
lifetime="730"
if [ -f $key ]; then
echo -n "Key $key exists. Overwrite[y/n]"
read -n 1 ans
echo
if [ ! $ans == "y" ]; then
exit
fi
fi
ipsec pki --gen --type $key_type --outform pem > $key
chmod 600 $key
echo "Key generated."
ipsec pki --pub --in $key | \
ipsec pki --issue --lifetime $lifetime \
--cacert caClientCert.pem \
--cakey caClientKey.pem \
--dn "C=US, O=place, CN=$name" \
--san $name \
--outform pem > $cert
echo "Cert generated."
openssl pkcs12 -export -inkey $key \
-in $cert -name "$1 VPN Certificate" \
-certfile caClientCert.pem \
-caname "strongSwan Client CA" \
-out $p12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment