As we move towards a more secure world Virtual Private Networks (VPNs) has become more popular as people try to protect their data going over the internet. But installing a VPN client on the OS level of an Azure Linux Virtual Machine (VM) can be tricky and frustrating.

This article covers a solution to a common scenario with Azure Linux VMs and VPN Clients.

Scenario

You have a Linux VM on Azure, you install a VPN client, configure it and connect to VPN server, all of a sudden you can no longer SSH to VM or access service on the VM. This happens because the VPN tunnel is now the default route, as it with most VPN Client.

Solution below will allow the VM to communicate as normal while VPN client is connected.

Steps below are done on an Ubuntu 16.04 LTS VM on Azure this might be different on other distribution or version but the principal are the same.

Solution

First step is to get network information from VM before the VPN Client connection.

curl ipinfo.io

hannel@VPN-VM1:~$ curl ipinfo.io { "ip": "52.246.250.69", "city": "Quincy", "region": "Washington", "country": "US", "loc": "47.2343,-119.8525", "org": "AS8075 Microsoft Corporation", "postal": "98848", "timezone": "America/Los_Angeles", "readme": "https://ipinfo.io/missingauth" }

route -n

hannel@VPN-VM1:~$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 10.0.0.1 0.0.0.0 UG 0 0 0 eth0 10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 168.63.129.16 10.0.0.1 255.255.255.255 UGH 0 0 0 eth0 169.254.169.254 10.0.0.1 255.255.255.255 UGH 0 0 0 eth0 hannel@VPN-VM1:~$

From the output take note of the interface, IP Addresses, Subnet and Gateway.

Backup route table and add a VPNBypass to existing table.

sudo su cp /etc/iproute2/rt_tables /etc/iproute2/rt_tables_orig echo "250 vpnbypass" >> /etc/iproute2/rt_tables exit

Use cat /etc/iproute2/rt_tables to confirm bypass entry in rt_table .

Make sure the entry is rt_table before you proceed.

Update the vpnbypass table to bypass VPN for subnet communication

Note that i am using the subnet and Ethernet name to add the rule to the vpnbypass table

sudo ip rule add from 10.0.0.0/24 table vpnbypass #Allow communication from Subnet sudo ip rule add to 10.0.0.0/24 table vpnbypass #Allow communication to Subnet sudo ip rule add to 169.254.169.254 table vpnbypass #Allow communication to Metadata Service sudo ip rule add to 169.63.129.16 table vpnbypass #Allow communication to Azure Fabric sudo ip route add table vpnbypass to 10.0.0.0/24 dev eth0 #Selecting route for vpnbypass table sudo ip route add table vpnbypass default via 10.0.0.1 dev eth0 #selecting gateway

You can now connect to VPN Client and it should not interrupted your current connectivity but any communication doing outside of VM (outside of subnet) will use the VPN connection, to confirm;

curl ipinfo.io

hannel@VPN-VM1:~$ curl ipinfo.io { "ip": "141.101.166.130", "city": "San Francisco", "region": "California", "country": "US", "loc": "37.7749,-122.4194", "org": "AS46562 Total Server Solutions L.L.C.", "postal": "94103", "timezone": "America/Los_Angeles", "readme": "https://ipinfo.io/missingauth" }

Confirm Azure Metadata is also working

curl -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-ve..."

hannel@VPN-VM1:~$ curl -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-08-01&format=text" 40.65.109.128







OPTIONALLY

If you have VPN Client connection at startup, you can edit the rc.local file to make sure rules are applied on reboot.

sudo vi /etc/rc.local

Add the following lines to the file