Stumbling into Azure Part I: Building a site-to-site VPN tunnel for testing
- - 3 min read
So we want to play with ARO (Azure Red Hat OpenShift) private clusters. A private cluster is not reachable from the internet (surprise) and is only reachable via a VPN tunnel from other networks.
This blog post describes how we created a site-to-site VPN between a Hetzner dedicated server running multiple VM's via libvirt and Azure.
An upcoming blog post is going to cover the setup of the private ARO cluster.
Azure Setup
The diagram below depicts our planned setup:
On the right hand side can see the resources required for our lab:
- a virtual network (vnet 192.168.128.0/19). This vnet will be split into 3 separate subnets
- a master subnet (192.168.129.0/24) holding the ARO control plane nodes
- a node subnet (192.168.130.0/24) holding ARO worker nodes
- and finally a subnet call
GatewaySubnet
where we are going to deploy our Azure VPN gateway (called avnet-gateway
)The subnet where the Azure VPN gateway is located needs to have the name
GatewaySubnet
. Otherwise creating the Azure VPN gateway will fail. - we also need a
publicIP
resource that we are going to connect to ourvnet-gateway
(the VPN gateway) - and finally a
local-gateway
resource that tells thevnet-gateway
which networks are reachable on the left, in our case the Hetzner server.
Creating the required Azure resources
First we are going to set some environment variable. Those variables are used in the upcoming commands:
export RESOURCEGROUP=aro-rg export GATWAY_SUBNET="192.168.128.0/24" export MASTER_SUBNET="192.168.129.0/24" export WORKER_SUBNET="192.168.130.0/24" export HETZNER_VM_NETWORKS="10.0.0.0/24 192.168.122.0/24 172.16.100.0/24"
Next create a VNET resource holding our sub networks:
az network vnet create \ --resource-group $RESOURCEGROUP \ --name aro-vnet \ --address-prefixes 192.168.128.0/18
Create the
GatewaySubnet
subnetaz network vnet subnet create \ --resource-group $RESOURCEGROUP \ --vnet-name aro-vnet \ --name GatewaySubnet \ --address-prefixes $GATEWAY_SUBNET
Create the master subnet
az network vnet subnet create \ --resource-group $RESOURCEGROUP \ --vnet-name aro-vnet \ --name master-subnet \ --address-prefixes $MASTER_SUBNET \ --service-endpoints Microsoft.ContainerRegistry
Create the worker subnet
az network vnet subnet create \ --resource-group $RESOURCEGROUP \ --vnet-name aro-vnet \ --name worker-subnet \ --address-prefixes $WORKER_SUBNET \ --service-endpoints Microsoft.ContainerRegistry
Create a
public IP
resourceaz network public-ip create \ --name GatewayIP \ --resource-group $RESOURCEGROUP \ --allocation-method Dynamic
Create a
local-gateway
resourceaz network local-gateway create \ --name playground \ --resource-group $RESOURCEGROUP \ --local-address-prefixes $HETZNER_VM_NETWORKS \ --gateway-ip-address 95.217.42.98
Create a
vnet-gateway
resource (takes around 30 minutes)az network vnet-gateway create \ --name vpn-gateway \ --public-ip-address GatewayIP \ --resource-group $RESOURCEGROUP \ --vnet aro-vnet \ --gateway-type Vpn \ --vpn-type RouteBased \ --sku Basic \ --no-wait
Define a
vpn-connection
az network vpn-connection create \ --name VNet1toSite2 \ --resource-group $RESOURCEGROUP \ --vnet-gateway1 vpn-gateway \ --local-gateway2 playground \ --location westeurope \ --shared-key thepassword
Required iptables (nf tables) hacks for libvirt
Skip NAT rules if the destination network is in Azure and the client network deploy via libvirt
iptables -I LIBVIRT_PRT 2 -t nat -d 192.168.129.0/24 -j RETURN
iptables -I LIBVIRT_PRT 2 -t nat -d 192.168.130.0/24 -j RETURN
Skip NAT rules if the destination network is in Azure and the client is connected via tailscale
iptables -I ts-postrouting 1 -t nat -d 192.168.129.0/24 -j RETURN
iptables -I ts-postrouting 1 -t nat -d 192.168.130.0/24 -j RETURN
Libreswan setup on CentOS Stream
Install the Libreswan packages
dnf install libreswan
Create a Azure configuration for Libreswan in ~/etc/ipsec.d/azure.conf
conn masterSubnet also=azureTunnel leftsubnet=192.168.129.0/24 rightsubnet=172.16.100.0/24 auto=start conn workerSubnet also=azureTunnel leftsubnet=192.168.130.0/24 rightsubnet=172.16.100.0/24 auto=start conn azureTunnel authby=secret auto=start dpdaction=restart dpddelay=30 dpdtimeout=120 ike=aes256-sha1;modp1024 ikelifetime=3600s ikev2=insist keyingtries=3 pfs=yes phase2alg=aes128-sha1 left=51.137.113.44 leftsubnets=192.168.128.0/24 right=%defaultroute rightsubnets=172.16.100.0/24 salifetime=3600s type=tunnel ipsec-interface=yes
Create a Libreswan secrets file for Azure in
/etc/ipsec.d/azure.secrets
:%any %any : PSK "abc123"
Enable and start the IPsec service
systemctl enable --now ipsec
We had to explicitly load the IPsec configuration via
ipsec addconn --config /etc/ipsec.d/azure.conf azureTunnel
Libreswan IPSEC debugging tips
Check the state of the IPsec systemd service
systemctl status ipsec
Check the full log of the IPsec systemd service
journalctl -e -u ipsec
Check the state of the tunnels with the
ipsec
command line toolipsec status
Check for the following lines
000 Total IPsec connections: loaded 5, active 2 000 000 State Information: DDoS cookies not required, Accepting new IKE connections 000 IKE SAs: total(1), half-open(0), open(0), authenticated(1), anonymous(0) 000 IPsec SAs: total(2), authenticated(2), anonymous(0) 000 000 #130: "azureTunnel/1x1":500 STATE_V2_ESTABLISHED_CHILD_SA (IPsec SA established); EVENT_SA_REKEY in 2003s; newest IPSEC; eroute owner; isakmp#131; idle; 000 #130: "azureTunnel/1x1" esp.56cf4304@51.137.113.44 esp.6f49e8d3@95.217.42.98 tun.0@51.137.113.44 tun.0@95.217.42.98 Traffic: ESPin=0B ESPout=0B! ESPmax=0B 000 #129: "masterSubnet/0x0":500 STATE_V2_ESTABLISHED_CHILD_SA (IPsec SA established); EVENT_SA_REKEY in 1544s; newest IPSEC; eroute owner; isakmp#131; idle; 000 #129: "masterSubnet/0x0" esp.6e81e8da@51.137.113.44 esp.6f72bbc8@95.217.42.98 tun.0@51.137.113.44 tun.0@95.217.42.98 Traffic: ESPin=0B ESPout=0B! ESPmax=0B 000 #131: "masterSubnet/0x0":500 STATE_V2_ESTABLISHED_IKE_SA (established IKE SA); EVENT_SA_REKEY in 2121s; newest ISAKMP; idle;
IPsec specifies properties of connections via security associations (SA). The parent SA is describes the IKEv2 connections, the child SA is the ESP (encapsulated security payload) connection.
Check IPsec transformation policies
ip xfrm policy
Check the state of IPsec transformation policies
ip xfrm state
Check for dropped packages on the IPsec interface (ipsec1 in our case)
ip -s link show dev ipsec1
Additonal Resources
Copyright © 2020 - 2024 Toni Schmidbauer & Thomas Jungbauer