How connect a linux box to an azure point-to-site gateway?

My initial attempt was to try to use internet connection sharing and dedicate a machine to front-end the Linux box (just forward lots of ports), but connection sharing doesn't seem to work when connected to an azure VPN (I have tried windows 10, and win2008R2 so far).

I am also unable to find any VPN software for Linux that supports the necessary protocols.


Solution 1:

It is possible to connect Linux to Azure P2S using strongSwan (IKEv2). Microsoft just doesn't bother itself by this question and insist on taking "P2S for Linux is not supported" course (that is what they answered me in support tickets). Here is how you can configure IKEv2 based on the certificates' authentication.

Install dependencies

Here are the required packages for Ubuntu:

apt-get install strongswan-ikev2 strongswan-plugin-eap-tls
# in Ubuntu 16.04 install libstrongswan-standard-plugins for p12 keypair container support
apt-get install libstrongswan-standard-plugins

If you install libstrongswan-extra-plugins package in Ubuntu 16.04, it will break strongSwan. This package contains af-alg, ctr and gcrypt plugins and they conflict with the openssl plugin. In this case you have to either remove the libstrongswan-standard-plugins package containing openssl plugin, or disable openssl plugin:

sudo sed -i 's/\sload =.*/ load = no/g' /etc/strongswan.d/charon/openssl.conf

or af-alg, ctr and gcrypt plugins:

sudo sed -i 's/\sload =.*/ load = no/g' /etc/strongswan.d/charon/{af-alg,ctr,gcrypt}.conf

Generate keys and certificates

You have to generate your own CA first, then it is necessary to generate user's certificate with the X509v3 Subject Alternative Name (SAN) extension (strongSwan FAQ), which should correspond to the certificate subject's common name (CN). I.e. certificate with the CN=client subject must contain DNS:client SAN. This will allow you to specify EAP identity without CN= prefix in strongSwan. By default strongSwan transfers full certificate subject as EAP identity, but Azure VPN gateway doesn't support that. You can read more about CN vs SAN history: http://unmitigatedrisk.com/?p=381.

# Generate CA
ipsec pki --gen --outform pem > caKey.pem
ipsec pki --self --in caKey.pem --dn "CN=VPN CA" --ca --outform pem > caCert.pem
# Print CA certificate in base64 format, supported by Azure portal. Will be used later in this document.
openssl x509 -in caCert.pem -outform der | base64 -w0 ; echo

# Generate user's certificate and put it into p12 bundle.
export PASSWORD="password"
export USERNAME="client"
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"
# Generate p12 bundle
openssl pkcs12 -in "${USERNAME}Cert.pem" -inkey "${USERNAME}Key.pem" -certfile caCert.pem -export -out "${USERNAME}.p12" -password "pass:${PASSWORD}"

Then open Azure portal, find your "Virtual Network Gateway" and on its Point-to-site configuration page in Root certificates section paste base64 encoded CA printed above.

Configure the client

Find Download VPN client button on gateway's Point-to-site configuration page, then unzip the VpnServerRoot.cer CA from the downloaded ZIP archive:

sudo unzip -j downloaded.zip Generic/VpnServerRoot.cer -d /etc/ipsec.d/cacerts

You can verify it using the command below:

openssl x509 -inform der -in /etc/ipsec.d/cacerts/VpnServerRoot.cer -text -noout

Then extract VPN server DNS:

$ unzip -p downloaded.zip Generic/VpnSettings.xml | grep VpnServer
  <VpnServer>azuregateway-00112233-4455-6677-8899-aabbccddeeff-aabbccddeeff.cloudapp.net</VpnServer>

Use VpnServer value for the right value and for the rightid value prefixed with % in ipsec.conf below.

Then copy user's p12 bundle into corresponding directory:

sudo cp client.p12 /etc/ipsec.d/private/

Use the following /etc/ipsec.conf configuration:

config setup

conn azure
  keyexchange=ikev2
  type=tunnel
  leftfirewall=yes
  left=%any
  leftauth=eap-tls
  leftid=%client # use the DNS alternative name prefixed with the %
  right=azuregateway-00112233-4455-6677-8899-aabbccddeeff-aabbccddeeff.cloudapp.net # Azure VPN gateway address
  rightid=%azuregateway-00112233-4455-6677-8899-aabbccddeeff-aabbccddeeff.cloudapp.net # Azure VPN gateway address, prefixed with %
  rightsubnet=0.0.0.0/0
  leftsourceip=%config
  auto=add

and /etc/ipsec.secrets content:

: P12 client.p12 'password' # key filename inside /etc/ipsec.d/private directory

Then restart ipsec to reread the configuration and start the tunnel:

sudo ipsec restart
sudo ipsec up azure

MTU/MSS issue

IPsec VPN client can experience connectivity issues because of high MTU/MSS values and IKE Fragmentation. To resolve this issue you have to explicitly set 1350 value for MTU/MSS iside the kernel-netlink strongSwan's charon configuration (this configuration works only in strongSwan version >= 5.2.1). Set the mtu and mss values inside the /etc/strongswan.d/charon/kernel-netlink.conf configuration file:

mss = 1350
mtu = 1350

and restart the tunnel:

sudo ipsec restart
sudo ipsec up azure