This website uses Google Analytics and Advertising cookies, used to generate statistical data on how visitors uses this website (with IP anonymization) and to deliver personalized ads based on user prior visits to this website or other websites. [read more]
These cookies are disabled by default until your Accept/Reject Consent.
The Consent can be changed at any time by accesing the ePrivacy button located at the bottom of every page. Enjoy your visit!



Ubuntu, how to connect to IPsec/IKEv2 VPNs via NetworkManager

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).

info A lot of VPN providers are using at least one or both OpenVPN or Strongswan IPsec VPN solutions to provide secure tunnels between a client and their servers.

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

info Change the strongswan version 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-NI

Step 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.conf sudo 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.conf sudo 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

info We have here two connections (road-warrior-base it's a helper one) contoso.localnet connects to our company and is used only to access resources inside our company network (eg 10.10.1.0/24); hide.me is another connection, this time for the hide.me VPN provider. hide.me is used for all our internet traffic (0.0.0.0/0). hide.me is working too with NetworkManager - configured with this https://hide.me/downloads/hide.me.pem server certificate.

Step 6-CLI: declare your EAP passwords on /etc/ipsec.secrets

Edit ipsec.secrets sudo nano /etc/ipsec.secrets
contosousername : EAP "the password for contoso.localnet"
hidemeusername : EAP "the password for hide.me"

info Adjust usernames and passwords as required. Keep password inside double quotes. Restart ipsec (the charon wrapper) 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

info I applied the patch because of an incompatibility issue at the time (menu toggle not working on Gnome 3.36+). The patch may not be required for future extension releases.

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.

label_outline

Share this post on your favorite networks.
© Copyright 2017 b247.eu.org | Just another information technology blog - All Rights Reserved