VPN to Azure on PI

From Coolscript
Revision as of 17:54, 20 November 2020 by Admin (talk | contribs) (Created page with "{|align=right | |__TOC__ |} <br> '''This is howto setup an OpenVPN within Azure in less than 10 Minutes!!!''' <br><br> =Introduction= This Howto is about to create a [...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search



This is howto setup an OpenVPN within Azure in less than 10 Minutes!!!



Introduction

This Howto is about to create a VPN running OpenVPN between your Home-LAN (On-premises) and Azure.

This will allow you to route any traffic from your Home-LAN into Azure and vice versa.

The setup is using SNAT on both VPN Server which is the quickest way to solve routing and security issues (eg NSG) and is therefore less secure and has a lower performance because of NAT, but depending on the proposed solution it is possible to skip the SNAT / Netfilter setup.

Optional it is possible to use the Home-OpenVPN Server as default gateway for Home-Clients, this way the home client is adapting the Azure Public IP Address. This is very useful if a public IP address is needed within another country. Note that this configuration requires SNAT for sure. Also note that this can result in a high traffic usage for which you get charged extra by Azure.

The setup is using Port 443 to communicate between the VPN Server because this port is almost alwyas open on WLans but any other port can be chosen too.




Requirements

  • Your Home LAN
  • Raspberry-PI or alternative another Linux Server
  • Azure Subscription
  • Azure CLI Tools installed somewhere





Quick installations steps

  • The following steps needed to setup the VPN:
    • Create an Azure Network using the Azure CLI
    • Create Routing between networks using the Azure CLI
    • Create VM using the Azure CLI
    • Install OpenVPN on a VM within Azure
    • Setup both OpenVPN Server
    • Setup Home LAN
    • Setup the Home LAN routing





Overview








Azure

Create a custom Resurce-ID

Create the Resource-ID VPN-Test. This Resource-ID is used through all command samples below.

az group create --name VPN-Test --location eastus
root@rb01:~# az group create --name VPN-Test --location eastus
{
  "id": "/subscriptions/727d7068-94e3-494a-965a-xxxxx/resourceGroups/VPN-Test",
  "location": "eastus",
  "managedBy": null,
  "name": "VPN-Test",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}

Setup Vnet

Create a Custom Virtual Net

Create the Virtual-Net VNet01. This Name is used through all command samples below.

az network vnet create --name VNet01 \
--resource-group VPN-Test \
--location eastus \
--address-prefix 10.0.0.0/16
root@rb01:~# az network vnet create --name VNet01 --resource-group VPN-Test --location eastus --address-prefix 10.0.0.0/16
{
"newVNet": {
  "addressSpace": {
    "addressPrefixes": [
      "10.0.0.0/16"
    ]
  },
  "bgpCommunities": null,
  "ddosProtectionPlan": null,
  "dhcpOptions": {
    "dnsServers": []
  },
  "enableDdosProtection": false,
  "enableVmProtection": false,
  "etag": "W/\"38ff6021-dede-4633-a431-de744603f625\"",
  "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/virtualNetworks/VNet01",
  "ipAllocations": null,
  "location": "eastus",
  "name": "VNet01",
  "provisioningState": "Succeeded",
  "resourceGroup": "VPN-Test",
  "resourceGuid": "ab5d3b7d-4c7e-4243-aba5-a30a72017666",
  "subnets": [],
  "tags": {},
  "type": "Microsoft.Network/virtualNetworks",
  "virtualNetworkPeerings": []
 }
}







Create a Subnet SN01

az network vnet subnet create \  
--address-prefix 10.0.1.0/24 \
--name SN01 \
--resource-group VPN-Test \
--vnet-name VNet01 
root@rb01:~# az network vnet create --name VNet01 --resource-group VPN-Test --location eastus --address-prefix 10.0.0.0/16
{
 "newVNet": {
   "addressSpace": {
     "addressPrefixes": [
       "10.0.0.0/16"
     ]
   },
   "bgpCommunities": null,
   "ddosProtectionPlan": null,
   "dhcpOptions": {
     "dnsServers": []
   },
   "enableDdosProtection": false,
   "enableVmProtection": false,
   "etag": "W/\"38ff6021-dede-4633-a431-de744603f625\"",
   "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/virtualNetworks/VNet01",
   "ipAllocations": null,
   "location": "eastus",
   "name": "VNet01",
   "provisioningState": "Succeeded",
   "resourceGroup": "VPN-Test",
   "resourceGuid": "ab5d3b7d-4c7e-4243-aba5-a30a72017666",
   "subnets": [],
   "tags": {},
   "type": "Microsoft.Network/virtualNetworks",
   "virtualNetworkPeerings": []
 }
}






Create a Subnet SN02

az network vnet subnet create \  
--address-prefix 10.0.2.0/24 \
--name SN02 \
--resource-group VPN-Test \
--vnet-name VNet01 
root@rb01:~# az network vnet subnet create --address-prefix 10.0.2.0/24 --name SN02 --resource-group VPN-Test --vnet-name VNet01
{
 "addressPrefix": "10.0.2.0/24",
 "addressPrefixes": null,
 "delegations": [],
 "etag": "W/\"1930d1f7-7d54-4642-bc87-c73173238b76\"",
 "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/virtualNetworks/VNet01/subnets/SN02",
 "ipAllocations": null,
 "ipConfigurationProfiles": null,
 "ipConfigurations": null,
 "name": "SN02",
 "natGateway": null,
 "networkSecurityGroup": null,
 "privateEndpointNetworkPolicies": "Enabled",
 "privateEndpoints": null,
 "privateLinkServiceNetworkPolicies": "Enabled",
 "provisioningState": "Succeeded",
 "purpose": null,
 "resourceGroup": "VPN-Test",
 "resourceNavigationLinks": null,
 "routeTable": null,
 "serviceAssociationLinks": null,
 "serviceEndpointPolicies": null,
 "serviceEndpoints": null,
 "type": "Microsoft.Network/virtualNetworks/subnets"
}






Create a Route Table

az network route-table create \
 --name MyRouteTable \
--resource-group VPN-Test
root@rb01:~# az network route-table create \
>  --name MyRouteTable \
>  --resource-group VPN-Test
{- Finished ..
 "disableBgpRoutePropagation": false,
 "etag": "W/\"3fca8554-5b01-4201-9ed2-1c55dc55244d\"",
 "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/routeTables/MyRouteTable",
 "location": "eastus",
 "name": "MyRouteTable",
 "provisioningState": "Succeeded",
 "resourceGroup": "VPN-Test",
 "routes": [],
 "subnets": null,
 "tags": null,
 "type": "Microsoft.Network/routeTables"
}








Create VPN Route


az network route-table route create \ 
 --name ToVPNTun \ 
 --resource-group VPN-Test \ 
 --route-table-name myRouteTable \  
 --address-prefix 10.9.0.0/24 \ 
 --next-hop-type VirtualAppliance \ 
 --next-hop-ip-address 10.0.1.4 
root@rb01:~# az network route-table route create \
>   --name ToVPNTun \
>   --resource-group VPN-Test \
>   --route-table-name myRouteTable \
>   --address-prefix 10.9.0.0/24 \
>   --next-hop-type VirtualAppliance \
>   --next-hop-ip-address 10.0.1.4

{- Finished ..
 "addressPrefix": "10.9.0.0/24",
 "etag": "W/\"00429bd4-3e32-440d-8163-c543d9781c56\"",
 "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/routeTables/myRouteTable/routes/ToVPNTun",
 "name": "ToVPNTun",
 "nextHopIpAddress": "10.0.1.4",
 "nextHopType": "VirtualAppliance",
 "provisioningState": "Succeeded",
 "resourceGroup": "VPN-Test",
 "type": "Microsoft.Network/routeTables/routes"
}






Create Home Route

az network route-table route create \
 --name ToPrivateSubnet \
 --resource-group VPN-Test \
 --route-table-name myRouteTable \
 --address-prefix 192.168.178.0/24 \
 --next-hop-type VirtualAppliance \
 --next-hop-ip-address 10.0.1.4
root@rb01:~# az network route-table route create \
>   --name ToPrivateSubnet \
>   --resource-group VPN-Test \
>   --route-table-name myRouteTable \
>   --address-prefix 192.168.178.0/24 \
>   --next-hop-type VirtualAppliance \
>   --next-hop-ip-address 10.0.1.4

{- Finished ..
 "addressPrefix": "192.168.178.0/24",
 "etag": "W/\"6f85a76c-1969-4f9e-9190-ba419c7f4436\"",
 "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/routeTables/myRouteTable/routes/ToPrivateSubnet",
 "name": "ToPrivateSubnet",
 "nextHopIpAddress": "10.0.1.44",
 "nextHopType": "VirtualAppliance",
 "provisioningState": "Succeeded",
 "resourceGroup": "VPN-Test",
 "type": "Microsoft.Network/routeTables/routes"
}






Associate Subnet SN01

az network vnet subnet update \ 
 --name SN01 \ 
 --vnet-name Vnet01 \ 
 --resource-group VPN-Test \ 
 --route-table MyRouteTable 
root@rb01:~# az network vnet subnet update \
>   --name SN01 \
>   --vnet-name Vnet01 \
>   --resource-group VPN-Test \
>   --route-table MyRouteTable
{
 "addressPrefix": "10.0.1.0/24",
 "addressPrefixes": null,
 "delegations": [],
 "etag": "W/\"437692a4-54c5-4cb9-b9c5-8216f36ed6da\"",
 "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/virtualNetworks/Vnet01/subnets/SN01",
 "ipAllocations": null,
 "ipConfigurationProfiles": null,
 "ipConfigurations": [
   {
     "etag": null,
     "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/networkInterfaces/vm-az-vpngw01VMNic/ipConfigurations/ipconfigvm-az-vpngw01",
     "name": null,
     "privateIpAddress": null,
     "privateIpAllocationMethod": null,
     "provisioningState": null,
     "publicIpAddress": null,
     "resourceGroup": "VPN-Test",
     "subnet": null
   }
 ],
 "name": "SN01",
 "natGateway": null,
 "networkSecurityGroup": null,
 "privateEndpointNetworkPolicies": "Enabled",
 "privateEndpoints": null,
 "privateLinkServiceNetworkPolicies": "Enabled",
 "provisioningState": "Succeeded",
 "purpose": null,
 "resourceGroup": "VPN-Test",
 "resourceNavigationLinks": null,
 "routeTable": {
   "disableBgpRoutePropagation": null,
   "etag": null,
   "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/routeTables/MyRouteTable",
   "location": null,
   "name": null,
   "provisioningState": null,
   "resourceGroup": "VPN-Test",
   "routes": null,
   "subnets": null,
   "tags": null,
   "type": null
 },
 "serviceAssociationLinks": null,
 "serviceEndpointPolicies": null,
 "serviceEndpoints": null,
 "type": "Microsoft.Network/virtualNetworks/subnets"
}






Associate Subnet SN02

az network vnet subnet update \
 --name SN02 \
 --vnet-name Vnet01 \
 --resource-group VPN-Test \
 --route-table MyRouteTable
root@rb01:~# az network vnet subnet update \
>   --name SN02 \
>   --vnet-name Vnet01 \
>   --resource-group VPN-Test \
>   --route-table MyRouteTable

{
 "addressPrefix": "10.0.2.0/24",
 "addressPrefixes": null,
 "delegations": [],
 "etag": "W/\"1fa47832-5492-4c2b-b7e4-ea0a7a4e2e7e\"",
 "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/virtualNetworks/Vnet01/subnets/SN02",
 "ipAllocations": null,
 "ipConfigurationProfiles": null,
 "ipConfigurations": [
   {
     "etag": null,
     "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/networkInterfaces/vm-sn02-client01VMNic/ipConfigurations/ipconfigvm-sn02-client01",
     "name": null,
     "privateIpAddress": null,
     "privateIpAllocationMethod": null,
     "provisioningState": null,
     "publicIpAddress": null,
     "resourceGroup": "VPN-Test",
     "subnet": null
   }
 ],
 "name": "SN02",
 "natGateway": null,
 "networkSecurityGroup": null,
 "privateEndpointNetworkPolicies": "Enabled",
 "privateEndpoints": null,
 "privateLinkServiceNetworkPolicies": "Enabled",
 "provisioningState": "Succeeded",
 "purpose": null,
 "resourceGroup": "VPN-Test",
 "resourceNavigationLinks": null,
 "routeTable": {
   "disableBgpRoutePropagation": null,
   "etag": null,
   "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/routeTables/MyRouteTable",
   "location": null,
   "name": null,
   "provisioningState": null,
   "resourceGroup": "VPN-Test",
   "routes": null,
   "subnets": null,
   "tags": null,
   "type": null
 },
 "serviceAssociationLinks": null,
 "serviceEndpointPolicies": null,
 "serviceEndpoints": null,
 "type": "Microsoft.Network/virtualNetworks/subnets"
}







Setup the OpenVPN Port (443) to our Azure Gateway

az vm open-port --resource-group VPN-Test \
 --name  vm-az-vpngw01 \
 --port 443 \
 --priority 910
root@rb01:~# az vm open-port --resource-group VPN-Test --name  vm-az-vpngw01 --port 443 --priority 910
{- Finished ..
 "defaultSecurityRules": [
   ....
   ....

   {
     "access": "Allow",
     "description": null,
     "destinationAddressPrefix": "*",
     "destinationAddressPrefixes": [],
     "destinationApplicationSecurityGroups": null,
     "destinationPortRange": "443",
     "destinationPortRanges": [],
     "direction": "Inbound",
     "etag": "W/\"5373a937-ddaf-4392-b364-5a720fdf3723\"",
     "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Network/networkSecurityGroups/vm-az-vpngw01NSG/securityRules/open-port-443",
     "name": "open-port-443",
     "priority": 910,
     "protocol": "*",
     "provisioningState": "Succeeded",
     "resourceGroup": "VPN-Test",
     "sourceAddressPrefix": "*",
     "sourceAddressPrefixes": [],
     "sourceApplicationSecurityGroups": null,
     "sourcePortRange": "*",
     "sourcePortRanges": [],
     "type": "Microsoft.Network/networkSecurityGroups/securityRules"
   }
 ],
 "subnets": null,
 "tags": {},
 "type": "Microsoft.Network/networkSecurityGroups"
}






Create Virtual Machines

Create vm-az-vpngw01 with Static Public IP

Note that this sample includes a static public IP address


az vm create --resource-group VPN-Test \ 
 --name vm-az-vpngw01 --location eastus \ 
 --image "Debian:debian-10:10:latest" \ 
 --vnet-name VNet01 \ 
 --subnet SN01 \ 
 --admin-username azadmin --admin-password xxxxxxxxx \ 
 --size Standard_B2s \ 
 --public-ip-address myPublicIpAddress \ 
 --public-ip-address-allocation static 


root@rb01:~# az vm create --resource-group VPN-Test \
>  --name vm-az-vpngw01 --location eastus \
>  --image "Debian:debian-10:10:latest" \
>  --vnet-name VNet01 \
>  --subnet SN01 \
>  --admin-username azadmin --admin-password xxxxxxxxxx \
>  --size Standard_B2s \
>  --public-ip-address myPublicIpAddress \
>  --public-ip-address-allocation static
{- Finished ..
 "fqdns": "",
 "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Compute/virtualMachines/vm-az-vpngw01",
 "location": "eastus",
 "macAddress": "00-0D-3A-8C-CC-FB",
 "powerState": "VM running",
 "privateIpAddress": "10.0.1.4",
 "publicIpAddress": "52.188.151.230",
 "resourceGroup": "VPN-Test",
 "zones": ""
}






Create a Client within SN02. No Static Public IP

Note that this sample does not includes a public IP address


 az vm create --resource-group VPN-Test \ 
 --name vm-sn02-client01 --location eastus \ 
 --image "Debian:debian-10:10:latest" \ 
 --vnet-name VNet01 \ 
 --subnet SN02 \ 
 --admin-username azadmin --admin-password xxxxxxxx \ 
 --size Standard_B2s \ 
 --public-ip-address  ""
root@rb01:~# az vm create --resource-group VPN-Test \
>  --name vm-sn02-client01 --location eastus \
>  --image "Debian:debian-10:10:latest" \
>  --vnet-name VNet01 \
>  --subnet SN02 \
>  --admin-username azadmin --admin-password xxxxxxxxxxx \
>  --size Standard_B2s \
>  --public-ip-address 
{- Finished ..
 "fqdns": "",
 "id": "/subscriptions/727d7068-94e3-494a-965a-XXXXX/resourceGroups/VPN-Test/providers/Microsoft.Compute/virtualMachines/vm-sn02-client01",
 "location": "eastus",
 "macAddress": "00-0D-3A-8B-C7-33",
 "powerState": "VM running",
 "privateIpAddress": "10.0.2.4",
 "publicIpAddress": "",
 "resourceGroup": "VPN-Test",
 "zones": ""
}







Setup the Azure OpenVPN Gateway

Install

Install and setup

Install openvpn, nftables and other required tools

sudo apt-get install openvpn nftables mc dnsutils net-tools dnsutils curl lynx

Setup IP Forward

  • Allow IP Forward next to other features. Edit /etc/sysctl.conf
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
net.ipv4.ip_forward=1
  • Run sysctl to apply the above changes
sysctl -p

Setup Nftables

#!/usr/sbin/nft -f

flush ruleset

table ip filter_v4 {
      chain INPUT {
              type filter hook input priority 0; policy accept;
      }

      chain OUTPUT {
              type filter hook output priority 0; policy accept;
      }

      chain FORWARD {
              type filter hook output priority 0; policy accept;
      }
}

table ip nat {
 
      chain PREROUTING {
              type nat hook prerouting priority -100; policy accept;
      }

      chain POSTROUTING {
              type nat hook postrouting priority 100; policy accept;
              ip saddr 10.9.0.0/24 oifname "eth0" counter snat to 10.0.1.4  comment "SNAT for TUN"
              ip saddr 192.168.178.0/24 oifname "eth0" counter snat to 10.0.1.4  comment "SNAT for HOME"
      }
}
  • Alternative you could set masquerade which is easier to configurate but has a less performance than snat
              ip saddr 10.9.0.0/24 oif "eth0" counter masquerade comment "VPN Masq Rule"
              ip saddr 192.168.178.0/24 oif "eth0" counter masquerade comment "Home Masq Rule"

Start/Stop/Enable Nftables

  • Run to manual start (apply) the script:
nft -f /etc/nftables.conf
  • Run to manual stop nft:
nft flush ruleset
  • To enable at system start run:
systemctl enable nftables

Setup OpenVPN

Server Key

Get the existing static key file or create a new one using:

openvpn --genkey --secret /etc/openvpn/static.key

Configuration

Setup the configuration in /etc/openvpn/server.conf

dev tun
proto tcp-server
port 443
ifconfig 10.9.0.1 10.9.0.2
route 192.168.178.0 255.255.255.0
cipher AES-256-CBC
comp-lzo
keepalive 10 60
persist-key
persist-tun
secret /etc/openvpn/static.key
log /var/log/openvpn.log
verb 6

Apply the new configuration to systemctl

systemctl daemon-reload 

Restart OpenVPN

systemctl restart openvpn


Setup the Raspery-PI OpenVPN Gateway

Install

Install and setup

Install openvpn, nftables and other required tools

sudo apt-get install openvpn nftables mc dnsutils net-tools dnsutils curl lynx

Setup IP Forward

  • Allow IP Forward next to other features. Edit /etc/sysctl.conf
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
net.ipv4.ip_forward=1
  • Run sysctl to apply the above changes
sysctl -p

Setup Nftables

#!/usr/sbin/nft -f

flush ruleset

table ip filter_v4 {
      chain INPUT {
              type filter hook input priority 0; policy accept;
      }

      chain OUTPUT {
              type filter hook output priority 0; policy accept;
      }

      chain FORWARD {
              type filter hook output priority 0; policy accept;
      }
}

table ip nat {
 
      chain PREROUTING {
              type nat hook prerouting priority -100; policy accept;
      }

      chain POSTROUTING {
              type nat hook postrouting priority 100; policy accept;
              ip saddr 10.0.0.0/16 oifname "eth0" counter snat to 10.0.1.4  comment "SNAT for Azure VNet01"
      }
}


  • Alternative you could set masquerade which is easier to configurate but has a less performance than snat
ip saddr 10.0.1.0/24 oif "eth0" counter masquerade comment "SN01 Masq Rule"
ip saddr 10.0.2.0/24 oif "eth0" counter masquerade comment "SN02 Masq Rule"

Start/Stop/Enable Nftables

  • Run to manual start (apply) the script:
nft -f /etc/nftables.conf
  • Run to manual stop nft:
nft flush ruleset
  • To enable at system start run:
systemctl enable nftables

Setup OpenVPN

Server Key

Get the existing static key file or create a new one using:

openvpn --genkey --secret /etc/openvpn/static.key

Configuration

Setup the configuration in /etc/openvpn/server.conf


remote 52.188.151.230
proto tcp-client
port 443
dev tun
ifconfig 10.9.0.2 10.9.0.1
cipher AES-256-CBC
comp-lzo
keepalive 10 60
persist-key
persist-tun
secret /etc/openvpn/static.key
log /var/log/openvpn.log
verb 6
#Routing option 1 by setup each subnet
route 10.0.1.0 255.255.255.0
route 10.0.2.0 255.255.255.0
#Routing option 2 by setup the vpn partner as default gateway
#redirect-gateway autolocal

Apply the new configuration to systemctl

systemctl daemon-reload 

Restart OpenVPN

systemctl restart openvpn

Setup Routing

The quickest way to setup routing within the Home-LAN is to do this on your ISP Router, the following is showing the static route table on a Fritz Box