Today I want to go over the steps to establish a Site-to-Site IPSec route-based vpn tunnel between an onPremise network and a virtual network (VNet) in Azure. For the onPremise site I will use a pfSense appliance as VPN device.

Please also read my following updated version from May 2024.








Create a VNet and Subnets

First we have to create a virtual network in Azure which we will be later connected over a S2S vpn tunnel with our onPremise network.


This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense001-1024x597.png





This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense002-300x300.png


Inside this VNet we create an subnet in which our virutal machines will reside and therefore be connected over the vpn tunnel with our onPremise network.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense009-1024x345.png


As we create a dynamic route based S2S vpn tunnel, I will add a further address space to the VNet. I don’t really need this but we can see later how these several address spaces will be automatically advertised by the BGP protocol and so we do not have to create hidden policy-based forwarding rules with several phase 2.

As mentioned we do not need to add an IKEv2 phase 2 for each subnet which should be tunneled over the vpn connection, instead we only need one phase 2 for the transit network, over this all subnets will be routed through the tunnel.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense004-300x300.png


Next we have to add a gateway subnet to the VNet, in this subnet resides the ip addresses of the virtual network gateway which we create later. The name of this subnet must be GatewaySubnet and connot be changed. Further you should not place any virtual machines or other services in this subnet.

For this subnet we must use a minimum of a /29 subnet, Microsoft recommends to calculate a reserve and better use a /27 subnet.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense010-1024x363.png





This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense011-1024x247.png






Create Virtual Machine optional to do some testing later

Now we create a virtual machine so that we later can test the vpn tunnel with it. If we create the vm in the same resource group as the VNet, in this case braintesting.de, then the vm will be automatically given an ip address from our previous created VNet and subnet 172.26.10.0/24.

We do not add a network security group to the vm so that we later can easily test different protocols over the vpn tunnel and do not have to configure allow rules. Therefore the vm becomes no public ip address and we only access the vm over the vpn tunnel.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense012.png





This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense013-1024x288.png






Create a Virtual Network Gateway

To connect our VNet with the onPremise network we need to create a Virtual Network Gateway in Azure.

The Virtual Network Gateway consists of two or more virtual machines which will be created in our previously created GatewaySubnet. These virtual machines provides routing tables and services for the gateway.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense014-1024x503.png




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

What is VPN Gateway?
A VPN gateway is a specific type of virtual network gateway that is used to send encrypted traffic between an Azure virtual network and an on-premises location over the public Internet. You can also use a VPN gateway to send encrypted traffic between Azure virtual networks over the Microsoft network. Each virtual network can have only one VPN gateway. However, you can create multiple connections to the same VPN gateway. When you create multiple connections to the same VPN gateway, all VPN tunnels share the available gateway bandwidth.

What is a virtual network gateway?
When you configure a virtual network gateway, you configure a setting that specifies the gateway type. The gateway type determines how the virtual network gateway will be used and the actions that the gateway takes. The gateway type ‘Vpn’ specifies that the type of virtual network gateway created is a ‘VPN gateway’. This distinguishes it from an ExpressRoute gateway, which uses a different gateway type. A virtual network can have two virtual network gateways; one VPN gateway and one ExpressRoute gateway. For more information, see Gateway types.

Creating a virtual network gateway can take up to 45 minutes to complete. When you create a virtual network gateway, gateway VMs are deployed to the gateway subnet and configured with the settings that you specify. After you create a VPN gateway, you can create an IPsec/IKE VPN tunnel connection between that VPN gateway and another VPN gateway (VNet-to-VNet), or create a cross-premises IPsec/IKE VPN tunnel connection between the VPN gateway and an on-premises VPN device (Site-to-Site). You can also create a Point-to-Site VPN connection (VPN over OpenVPN, IKEv2, or SSTP), which lets you connect to your virtual network from a remote location, such as from a conference or from home.



For the Gateway type we use VPNand the VPN type is Route-based.
Also we must choose a SKU (Stock keeping Unit | Pricing Tier) for the virtual network gateway, to support route-based vpn we use VpnGw1, below you will find more about the different SKUs.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense015-1024x773.png





Be aware of what type of SKU (Stock keeping Unit | Pricing Tier) you choose below for the virtual network gateway. By default the Basic SKU is a legacy SKU and has feature limitations like no support for routed-based vpn with BGP.

Working with virtual network gateway SKUs
https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-skus-legacy

Supported configurations by SKU and VPN type
https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-skus-legacy#config

Because we create a Route-based VPN which determines dynamically the routes, we must enable and configure here the BGP protocol. For the Azure site is the private ASN 65515 reserved.

https://en.wikipedia.org/wiki/Autonomous_system_(Internet)

In my case I get a wired error message at validation that the ASN 65515 is reserved for Microsoft and cannot be used ? , after retyping the number 65515 the validation passed, no idea why this happens, must be a bug at the moment.



This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense016.png





This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense070.png

The deployment of the Virtual Network Gateway can take up to 45 minutes! So grab a coffee ☕ …

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense018-1024x518.png


Here you can see the finished Virtual Network Gateway, under Settings – Configuration you can see the BGP peer IP which we need later for the vpn configuration at pfSense.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense060.png




Create a Local Network Gateway

Next we have to create the Local Network Gateway which represents your onPrem VPN Gateway in Azure. It is a specific object in Azure to provide some informations of your onPrem Gateway like IP address and Prem subnets you want to route over this Tunnel.

Each virtual network can have only one virtual network gateway, but one virtual network gateway can be used to configure multiple VPN connections.



Add a Site-to-Site connection to a VNet with an existing VPN gateway connection
https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-howto-multi-site-to-site-resource-manager-portal#before

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense020-1024x513.png



Under IP address you must use the public IP address from pfSense on the onPremise network. In my case 62….

Under Address space we type the IP from our BGP peer in pfSense. This is the IP from the internal interface from pfSense.

We also need to type this IP in the BGP peer IP address field below and a private ASN number for our on-Premise BGP peer, I will use here 65505 which later also have to be configured on pfSense.

You can use here a number from the reserved private use range which is from 6451265534, besides 65515 which is reserved for the Azure VNets as mentioned above.

More about Autonomous system (Internet)
https://en.wikipedia.org/wiki/Autonomous_system_(Internet)

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense028.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense023.png


This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense029.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense030.png





This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense031.png



Now we have to add a new connection to our Local network gateway object, which represents the actual tunnel to our onPrem Gateway.

This image has an empty alt attribute; its file name is local_gw01-1024x414.png




This image has an empty alt attribute; its file name is local_gw02.png




This image has an empty alt attribute; its file name is local_gw03-1-1024x413.png


If we click on the connection, we can adjust the configuration from the tunnel.

The default IPSec / IKE policy settings for the SKU VpgGw1 you can see further down, so can adjust your onPrem Gateway (pfSense) to use the same or you can define your own policy settings if you switch the button to Custom as follows.

Default Settings

This image has an empty alt attribute; its file name is local_gw04.png


Custom settings

This image has an empty alt attribute; its file name is local_gw05-1024x853.png




Configure the IPSec Tunnel and BGP on pfSense

In order to configure the last step in Azure, the actual IPSec Connection, we will first create on pfSense in our onPremise network the IPSec tunnel, Border Gateway Protocol and the transit network.

First we will install with the Package Manager the OpenBGPD daemon, which will provide us the BGP Protocol at pfSense.




OpenBGPD is since pfSense version 2.4.5 depricated and since version 2.5.0 no longer available in pfSense!

Therefore you should move to FRR. How to install and configure FRR you will find in my following post.




BGP is advertising the routing informations between the connected peers. So with BGP we do not need to configure manual static routes for the remote site and peer, as they will automatically advertised from them with BGP.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense027-1024x635.png


After the installation of OpenBGPD we can configure it under Services – OpenBGPD – Settings.

For the ASN Number I use the private 65505 which we previous set at the Local Network Gateway in Azure. For the Listen and Router IP I use the internal IP from the pfSense Interface.

https://en.wikipedia.org/wiki/Autonomous_system_(Internet)

At Network you can select which networks should be advertised to the VNet in Azure. I used here inet static which advertises the static routes on the pfSense.



Be aware of adding the inet connected to the advertised networks, both networks from the local adapters (WAN/LAN) will be advertised as route to the Azure BGP peer.

In this case, also the complete WAN Subnet in which the adapter resides, will be advertised as route to the Azure BGP peer.

Because of this, all interfaces in this VNet will get this route included in their routing table.

Therefore the VMs would try to reach all public IPs from this Subnet, through the vpn tunnel instead the default gateway for the internet traffic, which would be not desirable and working.

This image has an empty alt attribute; its file name is pf_pf_dynamic_routed024-1024x738.png


At the Groups tab we set the ASN from the Azure VNet which will be our remote site.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense033-1024x398.png


Last for the BGP configuration we must add the BGP Neighbor. Set here the BGP Neighbor IP from the Azure BGP peer. You will find this IP in Azure under the settings from the Virtual Network Gateway and is in my case the 172.16.1.30. Under Groups select the previous created remote ASN Group from Azure.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense034-1024x611.png


Under Raw Config you can review the complete BGP configuration.

This image has an empty alt attribute; its file name is pf_pf_dynamic_routed025-1024x535.png



The tab Status we will examine later.



First we have to configure the IPSec tunnel.

To configure the IPSec Tunnel with all the correct IPSec/IKE parameters on the onPrem VPN device in your local network, there are several options available.


For route based VPNs with the following gateway SKUs, you can adjust the IPSec/IKE parameters to meet your requirements of the onPrem Gateway.



  • VpnGw1 – 5
  • VpnGw1AZ – 5AZ
  • Standard and HighPerformance


In this case you can adjust the parameter directly at the connection from the local network gateway under Configuration as follows:

This image has an empty alt attribute; its file name is ipsec_policy-1024x749.png




Another option is to download the default azure configuration script from the local network gateway overview page in Azure if your device is supported and a script is available.

This image has an empty alt attribute; its file name is s2s_policy_based_033-1-1024x432.png



To see if for your device a script is available you can check this on https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-devices#devicetable

A detailed instruction of how to download and configure the script you will find on https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-download-vpndevicescript

For pfSense there is no script available and its also not validated by Microsoft, doesn’t matter 🙂 , it works smoothly with pfSense.

So if we want to use the default Azure IPSec/IKE parameter, we can look on https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-devices#ipsec for them.

The public IP of the Azure VPN peer you will find on the overview page from the virtual network gateway page or from the local network gateway page under the SettingsConnections menu and there when you click on your S2S connection.



The tables below contain the combinations of algorithms and parameters Azure VPN gateways use in default configuration. For route-based VPN gateways created using the Azure Resource Management deployment model, you can specify a custom policy on each individual connection. Please refer to Configure IPsec/IKE policy for detailed instructions.

In addition, you must clamp TCP MSS at 1350. Or if your VPN devices do not support MSS clamping, you can alternatively set the MTU on the tunnel interface to 1400 bytes instead.

By default pfSense uses for MSS 1400, you can change it under VPN – IPSec – Advanced Settings. Here you can check Enable Maximum MSS and set it to 1350.

https://docs.netgate.com/pfsense/en/latest/vpn/ipsec/advanced-ipsec-settings.html



In the following tables:

  • SA = Security Association
  • IKE Phase 1 is also called “Main Mode”
  • IKE Phase 2 is also called “Quick Mode”





This image has an empty alt attribute; its file name is s2s_policy_based_043-1024x539.png




This image has an empty alt attribute; its file name is s2s_policy_based_044-1024x560.png





Now select from the menu VPN – IPSec and first create a Phase 1.

Under Key Exchange Version select IKEv2 which will use Azure. As Remote Gatway we use the public IP from the Azure Virtual Network Gateway which you will find in the overview of it.

As Pre-Shared Key (PSK) we will let pfSense create one for us.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense036v-1-1024x637.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense037-1024x174.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense038-1024x527.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense039-1024x508.png


Now as we finished Phase 1 we can create the Phase 2. As we create a Route-based VPN we only needone Phase 2 for the transit network over this our local subnets will be routed to Azure. If we would create a Policy-based VPN, we had to create for each subnet we want to route over the Tunnel, a Phase 2.

Therefore you must select at Phase 2 Mode Routed(VTI). VTI stands for Virtual Tunnel Interface. The default setting is Tunnel IPv4 for Policy-based VPN.

As you select the Routed(VTI) Mode, at pfSense is created a further interface which we will see and assign later.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense040-1024x472.png


This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense060.png


After selecting Routed(VTI) under Local Network, this will be automatically set to Network with a Subnet Mask of /30 which can contain 2 IP addresses. This Network will be our transit network over them the local subnets will be routed to Azure and vice versa.

Because the BGP peer IP from Azure is the 172.26.1.30 and we have a /30 subnet for the transit network wich contains two ip addresses, we must set at pfSense for the Local Network the IP 172.26.1.29/30 and under Remote Network the BGP peer IP from Azure with 172.26.1.30.

After this we had created the transit network wich will be represented through the Phase 2 and will be used to route our local subnets through this tunnel.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense042-1024x456.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense043-1024x596.png


As we finished the creation of the IPSec tunnel in pfSense we now have to create it also in Azure.

Therefore we go to the Azure Portal and the Local Network Gateway. Under Settings select Connections.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense044.png


Under Virtual Network Gateway we select the previous created VpnGW-braintesting.de and under Shared key (PSK) we copy and paste the PSK which was generated from pfSense.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense045.png





This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense046-1024x241.png


After selecting the connection, we can go to the overview and download the configuration from the IPSec tunnel. Here you can see the used parameters and settings for the Phase 1 and Phase 2 which we must use in pfSense also.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense047-1024x252.png


In pfSense under Status – IPSec, we see that the VPN tunnel is successfully established. In the Azure Portal it can last some minutes till you can see the status connected.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense048-1024x478.png


A few minutes later …

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense049-1024x240.png


That routing in pfSense finally works over the IPSec tunnel, we have to assign the IPSec Interface (VTI) which was automatically created after set the Tunnel Mode to Routed(VTI) in the Phase 2 settings.

Therefore go to the menu Interfaces – Assignments and add the ipsec Interface.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense050-1024x424.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense051-1024x486.png


After the assignment you will find this interface with the name OPT1. I changed the name to IPSecVTI for a better understanding.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense052-1024x181.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense053-1024x250.png


Per default the interface is not enabled, so don’t forget to enable it!

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense054-1024x243.png


As you can read, we cannot set manual an IP Configuration. The interface will get automatically an IP from the previous created transit network. This IP will represent the gateway to reach our Azure VNet.

Under System – Routing the Interface is automatically added as Gateway.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense055-1024x444.png


On the Dashboard of pfSense we can see under Interfaces the IPSec Interface and his IP.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense056.png


Now we will take a look at the previous mentioned point in the menu under Services – OpenBGPD – Status. Here we can check if the BGP protocol works and if both peers pfSense and Azure exchange his routing tables with the subnets.

As we can see there is no active connection to the BGP peer in Azure.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense058-1024x434.png
This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense059.png


In my case in Azure the BGP was disabled at the Local Network Gateway.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense057-1024x392.png


So after enabled the BGP in Azure and several minutes, the connection between the two peers was established successfully and the routing informations was exchanged between them.

Here you can see that the connection over the BGP protocol was established since 2:26 minutes between pfSense and the Azure BGP peer Neighbor and the AS number 65515.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense071-1024x434.png


Under OpenBGPD Routing we will see both address spaces from our Azure VNet wich will be advertised dynamically over the BGP protocol to pfSense.

Further we see the Gateway pfSense will use to route traffic for this VNet. This is the BGP peer IP from Azure.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense072-1024x195.png


Under OpenBGPD Forwarding we see our internal subnets from the onPremise Network and the corresponding gateway.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense073-1024x585.png


Under OpenBGPD Neighbors we will see the status of both peers.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense074-1024x518.png


Finally we must allow traffic flow from the Azure VNet to our onPremise network over the IPSec tunnel. The following rule will allow any IPv4 traffic from Azure VNet to the onPremise network. In productive business you should obviously for security reasons only allow required traffic.

Traffic flow from onPremise to Azure you control either from back firewalls in your network or on the LAN Interface at pfSense.

This image has an empty alt attribute; its file name is s2s_vpn_azure_pfSense075-1024x488.png


In Azure you can check over the CLI also the advertised routes from pfSense peer to the Azure peer.

This image has an empty alt attribute; its file name is pf_pf_dynamic_routed026-1-1024x586.png





$ az network vnet-gateway list-learned-routes -g MyResourceGroup -n MyVnetGateway

This image has an empty alt attribute; its file name is pf_pf_dynamic_routed027-1-1024x887.png
This image has an empty alt attribute; its file name is pf_pf_dynamic_routed028-2-1024x807.png
This image has an empty alt attribute; its file name is pf_pf_dynamic_routed029-2.png



Under https://docs.microsoft.com/en-us/cli/azure/network/vnet-gateway?view=azure-cli-latest you will find an overview of CLI commands for the Virtual Network Gateway.




Troubleshooting

Troubleshooting IPsec VPNs

Due to the finicky nature of IPsec, it isn’t unusual for trouble to arise. Thankfully there are some basic (and some not so basic) troubleshooting steps that can be employed to track down potential problems.

More you will find under https://docs.netgate.com/pfsense/en/latest/troubleshooting/ipsec.html




Duplicate IPsec SA Entries

In certain cases an IPsec tunnel may show what appear to be duplicate IKE (Phase 1) or Child (Phase 2) security association (SA) entries.

After lengthy testing and research, the main way this starts to happen is when both sides negotiate or renegotiate simultaneously. If both peers initiate, reauthenticate, or rekey Phase 1 at the same time, it can result in duplicate IKE SAs. If both peers rekey Phase 2 at the same time, it can result in duplicate child SAs.

Mitigating this problem involves ensuring that the chance of simultaneous negotiation is minimized or eliminated. The easiest way to reach that goal is to set higher Phase 1 and Phase 2 lifetimes on one peer, or at least make sure both sides are not set identically.

Source: https://docs.netgate.com/pfsense/en/latest/troubleshooting/ipsec-duplicate-sa.html









Set up IPSec route based S2S VPN for AWS and Google’s Cloud VPC

If you are also interested about how to set up the same for Amazon’s AWS VPC, you can read my following post.





For Google’s Cloud VPC you can read my following post.