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.