This website uses cookies:
• from Cloudflare to identify trusted web traffic and protect this website. [read more]
• from Google Analytics to generate statistical data on how visitors uses this website. [read more]
• from Google AdSense (third party vendors, including Google) to deliver ads based on user prior visits to this website or other websites.
Do you agree that your data to be used to deliver you personalized website ads? You can change your mind at any time by accesing the ePrivacy button located at the bottom of every page. Enjoy your visit!

Ubuntu Desktop 20.04 LTS - how to connect to Strongswan IPsec-based VPNs

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

First time when I was dealing with an IPsec-based tunnel, I thought, "Well, I'm pretty sure there is a NetworkManager plugin that I can use for that". And I was right, except that ... it didn't work, always authentication failure notices. Ok then, I'm still on Linux, sure there is a way to connect to the VPN using CLI, and I was right again, it worked this time, except ... the CLI solution doesn't provide Gnome visual feedbacks. So I wrote a small shell script, 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. But again, found that using the NM interface, there is no way to use the connection only for resources on its network. Then I came with the final hybrid solution, the Gnome extension able to connect/disconnect/show status from both CLI and NM, and below are the steps and the necessary code to accomplish that.

Step 1: compile strongswan from source

wget https://download.strongswan.org/strongswan-5.9.1.tar.bz2
cd strongswan-5.9.1
./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.1 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.5.2.tar.bz2
./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 create (and connect to) IKEv2 MS-CHAPv2 IPsec-based VPNs using NetworkManager. Further steps are necessary only if you need to use a VPN connection only for resources on its network.

hide.me IKE IPsec connection using NetworkManager

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 connctions 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 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
The Gnome VPN extension

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