Securing any infrastructure means, amongst other things, protecting machines from unnecessary exposure, and restricting remote administration access. While having an SSH port open to the world is sometimes a necessary evil, a preferable approach is to restrict access, via a firewall or security group, to a smaller, more controlled network.

If you always administer your systems from a single location - home, office, etc - it is practical to simply whitelist those IP addresses. However, if you are ever working remotely it’ll become necessary to either manually add your current IP address, or use a VPN.

The VPN solution on Azure is the topic of this post. But more specifically, how to make it accessible from a Linux system. There are plenty of how-tos around about how to setup a VPN on Azure, so this post will focus on the specifics of making it compatible with Linux.

VPN Selection

The first thing to understand is the different SKU for the VPN product, and what they mean:

SKU S2S/VNet-to-VNet Tunnels P2S SSTP Connections P2S IKEv2/OpenVPN Connections Aggregate Throughput Benchmark BGP Zone-redundant
Basic Max. 10 Max. 128 Not Supported 100 Mbps Not Supported No
VpnGw1 Max. 30* Max. 128 Max. 250 650 Mbps Supported No
VpnGw2 Max. 30* Max. 128 Max. 500 1 Gbps Supported No
VpnGw3 Max. 30* Max. 128 Max. 1000 1.25 Gbps Supported No
VpnGw1AZ Max. 30* Max. 128 Max. 250 650 Mbps Supported Yes
VpnGw2AZ Max. 30* Max. 128 Max. 500 1 Gbps Supported Yes
VpnGw3AZ Max. 30* Max. 128 Max. 1000 1.25 Gbps Supported Yes

Table 1: https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpngateways

There are to Point-to-site (P2S) options:

  • SSTP - Secure Socket Tunnelling Protocol
  • IKEv2/OpenVPN

OpenVPN is more widely supported, and is easier to configure, but SSTP is the only option available on the Basic Azure VPN SKU.

Key Pairs

(Updated 2020-10-03)

You will need a user key pair to use to authenticate. This need to end up as a key and certificate PEM file, and can either be converted to these using OpenSSL, or you can generate these yourself if you are setting up the the VPN yourself.

Converting a Provided P12

# Extract the certificate
openssl pkcs12 -in nigel.p12 -out nigelCert.pem  -clcerts -nokeys

# Extract the private key
openssl pkcs12 -in nigel.p12 -nocerts -nodes | openssl rsa -aes256 > nigelKey.pem

Generating Your Own

This is super brief, and I recommend finding a better tool or tutorial if you get stuck.

First you need a CA key pair

openssl rsa -in caKey.pem -outform PEM -pubout -out caCert.pem

The contents of public.pem, minus the BEGIN CERTIFICATE barriers, can be copied into the Azure Portal VPN Setup.

Now you need to generate a signed user key pair. The following script creates an encrypted user key pair. It will prompt for 2 passwords, first the user password, then the CA password.

#!/bin/bash

read -p 'Please provide a user key password' PASSWORD
export USERNAME=$1

ipsec pki --gen --outform pem > "${USERNAME}Key.pem"
ipsec pki --pub --in "${USERNAME}Key.pem" | ipsec pki --issue --cacert caCert.pem --cakey caKey.pem --dn "CN=${USERNAME}" --san "${USERNAME}" --flag clientAuth --outform pem > "${USERNAME}Cert.pem"


openssl pkcs12 -in "${USERNAME}Cert.pem" -inkey "${USERNAME}Key.pem" -certfile caCert.pem -export -out "${USERNAME}.p12" -password "pass:${PASSWORD}"

SSTP

(Updated 2020-01-11)

SSTP is a PPP over HTTPS protocol that is used primarily by Azure. It has official clients for Windows and OSX. There is a project to provide a Linux client, which which with a little bit of work, can be used on Ubuntu. Currently you’ll need to set this up using a PPA and a pppd config, although there is a Network Manager UI coming.

Debian Packages

From https://github.com/enaess/network-manager-sstp

You can import the gpg key using the following command:
	sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 61FF9694161CE595

Put the following two lines into the following file: /etc/apt/sources.list.d/sstp-client.list
	deb http://ppa.launchpad.net/eivnaes/network-manager-sstp/ubuntu eoan main
	deb-src http://ppa.launchpad.net/eivnaes/network-manager-sstp/ubuntu eoan main

Setting Up Connection

The first step is to get the client download from the Azure VPN portal. This contains the connection settings, and the VPN certificate.

The certificate will be in DER format, and this needs to be in PEM format. To convert, use openssl

openssl x509 -inform DER -in VpnServerRoot.cer -out VpnServerRoot.pem

Now, install the SSTP which can be done on Ubuntu/Debian by using the PPA provided by the author (see the site).

Finally, setup a provider in /etc/ppp/peers. I’ve named mine /etc/ppp/peers/azure-vpn.

remotename  REMOTE_NAME
linkname    azure-vpn
ipparam     azure-vpn
pty            "sstpc    --ipparam    azure-vpn   --nolaunchpppd --ca-cert /etc/ppp/VpnServerRoot.pem  VPN_IP"
name        CERT_CN
plugin      sstp-pppd-plugin.so
sstp-sock   /var/run/sstpc/sstpc-azure-vpn
require-mppe
require-eap
refuse-mschap-v2
refuse-pap
refuse-chap
refuse-mschap
nobsdcomp
nodeflate
noauth
password KEY_PASSWORD
ca CA_FILE
cert CERT_FILE
key CERT_KEY

You’ll need to substitute in some values as follows.

Substitute From
REMOTE_NAME VpnServer value in VpnSettings.XML. Remove the azuregateway- prefix. If this is wrong then the server certificate will not validate
VPN_IP The IP of the VPN server from the Azure console
KEY_PASSWORD This is the password to the user key
CERT_CN The CN from your client certificate. Get it using openssl x509 -subject -nocert < CERT_FILE (see below)
azure-vpn You can leave this, or change it, just make sure it is consistent as it is used to correlate all the parts of the PPP operation
CA_FILE Points to the server certificate we converted earlier. I put mine /etc/ppp/VpnServerRoot.pem
CERT_FILE Points to the user’s certificate
CERT_KEY Points to the user’s encrypted key

At this point you should be able to run pon azure-vpn and connect. However, out of the box nothing will route beyond the initial VPN subnet. The VpnServer.xml file also contains a Routes element that contains the list of router that should be exposed. To use these create a file in /etc/ppp/ip-up.d/9999azure-vpn:

#!/bin/sh

if [ "$PPP_IPPARAM" = "azure-vpn" ] ; then
	ip route add 10.4.0.0/16 via $PPP_LOCAL dev $PPP_IFACE
fi

Replace the 10.4.0.0/16 address with your own routes. Also, make sure you chmod +x /etc/ppp/ip-up.d/9999azure-vpn.

Now, disconnect (poff) and reconnect (pon azure-vpn) and you should have a working connection.

OpenVPN

OpenVPN however, is a more widely available VPN solution, with out-of-the-box support in Linux.

As you can see in Table 1 OpenVPN is not supported using the Basic SKU. Therefore, if you want the easy ride, use one of the others.

Setup

Microsoft have their own howto, but this was my approach. Start by installing the Network Manager extensions for OpenVPN

apt install network-manager-openvpn-gnome network-manager-openvpn

Next, download the VPN Client Config from the Azure VPN Portal.

Now, extract the config zip file, and [import the config] (https://www.cyberciti.biz/faq/linux-import-openvpn-ovpn-file-with-networkmanager-commandline/)

sudo nmcli connection import type openvpn file OpenVPN/vpnconfig.ovpn

This will create the VPN configuration called vpnconfig in your Network Manager VPN screen.

Edit the connection, fixing up the name, and supplying your user certificates.

Conclusion

If SSTP becomes available in the main Debian/Ubuntu repos then it would also be a good option, but in terms of return on time investment, OpenVPN is the best current option for Linux admins using Azure.