VPN: Virtual Private Network
Strongswan: IPsec-based VPN
IKEv2: VPN encryption protocol
MS-CHAPv2 (MSCHAPv2): authentication protocol
VPNs can be used for various reasons: the need to securely connect to a company's local network resources; the need to bypass geolocation restrictions; to route our internet traffic through a secured gateway. Whatever the reason, we have to be able to spawn a tunnel for that (connection to a VPN provider/server).
How do we connect to these VPN providers using Ubuntu Linux
With OpenVPN everything is damn simple, install the OpenVPN NetworkManager plugin (sudo apt install network-manager-openvpn) then import an OpenVPN connection by double click on a .ovpn file (provided by the VPN provider). With Strongswan VPNs (configured with IKEv2 encryption and MSCHAPv2 authentication) things gets a little bit complicated ...
... it didn't work, always authentication failure notices. We can connect to the VPN using CLI, it work, except ... the CLI solution doesn't provide Gnome visual feedbacks. So I wrote a small shell script that wraps CLI connections (and NM ones), added it to the Argos Gnome Extension, and here we are, we can connect/disconnect/see the status of our CLI based IKEv2 IPsec-VPN connection, using the Gnome interface.
... meanwhile, I didn't forget that there is a Network Manager extension that should work, and thanks to Tobias from Strongswan, who was kind enough to provide me direct assistance, I've managed to connect to my VPNs using the NetworkManager interface, even to "use the connection only for resources on its network".
Step 1: compile strongswan from source
wget https://download.strongswan.org/strongswan-5.9.10.tar.bz2 tar -xf strongswan-5.9.10.tar.bz2 cd strongswan-5.9.10 ./configure --sysconfdir=/etc --prefix=/usr --libexecdir=/usr/lib \ --enable-aesni --enable-acert --disable-aes --disable-des --disable-md5 --disable-sha1 --disable-sha2 \ --disable-fips-prf --disable-gmp --enable-openssl --enable-nm --enable-agent \ --disable-eap-gtc --disable-eap-md5 --disable-eap-peap --enable-eap-mschapv2 --enable-eap-identity make sudo make install
5.9.10 with one up to date at the time; remove the --enable-aesni flag if your CPU or kernel doesn't support AES-NIStep 2: compile strongswan network-manager plugin from source
wget https://download.strongswan.org/NetworkManager/NetworkManager-strongswan-1.6.0.tar.bz2 tar -xf NetworkManager-strongswan-1.6.0.tar.bz2 cd NetworkManager-strongswan-1.6.0 ./configure --sysconfdir=/etc --prefix=/usr --libexecdir=/usr/lib --without-libnm-glib make sudo make install
Step 3: disable peap, md5, and gtc plugins for charon-nm (strongswan network-manager plugin)
Edit /etc/strongswan.confsudo nano /etc/strongswan.conf
charon {
load_modular = yes
plugins {
include strongswan.d/charon/*.conf
}
}
charon-nm {
plugins {
eap-peap {
load = no
}
eap-md5 {
load = no
}
eap-gtc {
load = no
}
}
}
include strongswan.d/*.conf
At this step we shall be able to establish connections to IPsec/IKEv2 VPNs via NetworkManager.
| hide.me VPN IPSec/IKEv2 connection using NetworkManager |
|
|
| *pem from https://hide.me/downloads/hide.me.pem |
Using a VPN connection only for resources on its network
The default "Use this connection only for resources on its network" checkbox (within the NM VPN setting IPv4 panel) does nothing. That's why I've initially written the extra steps 4-6 tutorial, but recently discovered the "dispatcher" options of the NetworkManager and decided to give it a try, and it works.
How to make it work: just install ipcalc sudo apt install ipcalc and add the following code snippet to the /etc/NetworkManager/dispatcher.d/01-ifupdown dispatcher script
# VPN: use this connection only for resources on its network
if [ "$2" = "vpn-up" ]; then
CONN_INTERNAL_ONLY=$(grep 'never-default' $CONNECTION_FILENAME)
if [ -n "$CONN_INTERNAL_ONLY" ]; then
VPN_IP4_ADDRESS=$(echo $VPN_IP4_ADDRESS_0 | sed -n 's/\([0-9\.]*\).*/\1/p')
VPN_IP4_NETWORK=$(ipcalc $VPN_IP4_ADDRESS | grep Network | awk '{print $2}')
ip rule add not from all to $VPN_IP4_NETWORK table main priority 219
fi
fi
if [ "$2" = "vpn-down" ]; then
ip rule del pref 219
fi
[UPDATE] Further steps (4-6) still work and offer a nice and seamless Gnome integration, but they are no longer necessary
| Gnome VPN custom extension |
|
|
Step 4-CLI: copy VPN server or CA provided certificate to /etc/ssl/certs
sudo cp /path/to/vpn-server.pem /etc/ssl/certs/ sudo rm -r /etc/ipsec.d/cacerts/ sudo ln -s /etc/ssl/certs /etc/ipsec.d/cacerts
Step 5-CLI: declare your VPN connections on /etc/ipsec.conf
Edit ipsec.confsudo nano /etc/ipsec.conf
conn road-warrior-base
keyexchange=ike
fragmentation=yes
dpdaction=clear
dpdtimeout=90s
dpddelay=30s
conn contoso.localnet #adjust this to better reflect the VPN connection name
also=road-warrior-base
eap_identity=catalin #adjust this as required
leftauth=eap-mschapv2
left=%defaultroute
leftsourceip=%config
right=vpn.contoso.net #adjust this as required
rightsubnet=10.10.1.0/24 #adjust this as required (only trafic to 10.10.1.0/24 network is routed via this tunnel)
type=tunnel
auto=add
conn hide.me #this is a real VPN provider that works on both CLI and NM
also=road-warrior-base
eap_identity=b247 #adjust this as required
leftauth=eap-mschapv2
left=%defaultroute
leftsourceip=%config
right=free-nl.hide.me #for a free hide.me VPN account
rightauth=pubkey
rightsubnet=0.0.0.0/0 #all trafic is routed via this tunnel
rightid="C=MY, L=Labuan, O=eVenture Limited, CN=*.hide.me"
type=tunnel
auto=add
Step 6-CLI: declare your EAP passwords on /etc/ipsec.secrets
Edit ipsec.secretssudo nano /etc/ipsec.secrets
contosousername : EAP "the password for contoso.localnet" hidemeusername : EAP "the password for hide.me"
sudo ipsec restart and try to connect to any of ipsec.conf declared VPNs, using CLI (sudo ipsec up contoso.localnet, sudo ipsec up hide.me).The Gnome VPN custom extension
First we will need to install the argos gnome extension (https://extensions.gnome.org/extension/1176/argos/), using either Firefox or Chromium/Chrome, then we have to patch it for Gnome 3.36+ compatibility
git clone --single-branch --branch gnome-3.36 https://github.com/rammie/argos.git && cp -r argos/argos@pew.worldwidemann.com /home/$USER/.local/share/gnome-shell/extensions/
Create vpn.5s.sh nano /home/$USER/.config/argos/vpn.5s.sh
#!/usr/bin/env bash
STARTER_VPNS=( $(cat /etc/ipsec.conf | grep conn | awk '{print $2}') ) # get a list of starter vpns
BLACKLISTED_STARTER_VPNS=( "road-warrior-base" ) # blacklist (remove from the menu)
NM_VPNS=( $(nmcli con show | grep vpn | awk '{print $1}') ) # get a list of NM vpns
for i in "${BLACKLISTED_STARTER_VPNS[@]}"; do
STARTER_VPNS=(${STARTER_VPNS[@]//*$i*})
done
VPN_IP=$(ip r show table 220 | grep 'src' | awk '{print $9}') # get VPN IP from routing table
NM_VPN_NAME=$(nmcli con show --active | grep -i vpn | awk '{print $1}') # get VPN conn name from nmcli
STARTER_VPN_ACTIVE=$(cat /tmp/savpn.tmp) # use a temporary file to store active vpn from starter
VPN_ICON="network-vpn"
if [[ $NM_VPN_NAME ]]; then
VPN_INFO="$NM_VPN_NAME $VPN_IP | iconName=$VPN_ICON"
else
VPN_INFO="$STARTER_VPN_ACTIVE $VPN_IP | iconName=$VPN_ICON"
fi
echo ${VPN_INFO}
echo "---"
for i in "${STARTER_VPNS[@]}"
do
if [[ $STARTER_VPN_ACTIVE == $i ]]; then
action="cat /dev/null > /tmp/savpn.tmp && pkexec ipsec down $i"
icon=network-wired
else
if [[ -z $STARTER_VPN_ACTIVE ]]; then
action="echo $i > /tmp/savpn.tmp && pkexec ipsec up $i"
else
action=
fi
icon=
fi
echo "$i | iconName=$icon bash='$action' terminal=false refresh=true"
done
for i in "${NM_VPNS[@]}"
do
if [[ $NM_VPN_NAME == $i ]]; then
action="nmcli con down $i"
icon=network-wired
else
if [[ $NM_VPN_NAME ]]; then
action="nmcli con down $NM_VPN_NAME && nmcli con up $i"
else
action="nmcli con up $i"
fi
icon=
fi
echo "$i | iconName=$icon bash='$action' terminal=false refresh=true"
done
It wasn't easy to achieve this functionality, but I need it (mainly because of the "work from home" - COVID-19 prevention strategies). It works as expected, I'm using this extension to connect/disconnect/see the connection status for both NM managed VPNs (charon-nm) and the charon managed ones (CLI).
Thank You for reading this article.