Welcome back to my series on forced tunneling Azure Firewall using pfSense. In my last post I covered the background of the problem I wanted to solve, the lab makeup I’m using, and the process to setup the S2S (site-to-site) VPN with pfSense and exchange of routes over BGP. Take a few read through that post before jumping into this one.
At this point you should a working S2S VPN from your Azure VNet to your pfSense router and the two should be exchanging a few routes over BGP. If you didn’t complete all the steps in the first post, go back and do them now.
Now that connectivity is established, it’s time to incorporate Azure Firewall. Azure Firewall was introduced back in 2018 as a managed stateful firewall that can act as an alternative to rolling your own NVAs (network virtual appliances) like a Palo Alto or Checkpoint firewall. Now I’m not going to lie to you and tell you it has all the bells and whistles that a 3rd party NVA has, but it can provide a reasonable alternative depending on what your needs are. The major benefit is it’s a managed service to Microsoft owns the responsibility of managing the health of the service, its high availability and failover, it’s closely integrated with the Azure platform, more than likely cheaper than what you’d pay for a 3rd-party NVA license.
Recently, Microsoft has introduced support for forced tunneling into public preview. This provides you with the ability to send all of the traffic received by Azure Firewall on to another security stack that may exist within Azure, on-premises, or in another cloud. It helps to address some of the capability gaps such as lack of support for (DPI) deep packet inspection for Internet-bound traffic. You can leverage Azure Firewall to transitively route and mediate traffic between on-premises and Azure, hub-spoke, and spoke to spoke while passing Internet bound traffic on to another security stack with DPI capabilities.
With that out of the way, let’s continue with the lab.
The first thing you’ll want to do is to deploy an instance of Azure Firewall. To support forced tunneling, you’ll need to toggle the option to enabled. You then need to provide another public IP address. What’s happening here is the nodes are being created with two NICs (network interface cards). One NIC will live in the AzureFirewallSubnet and one will live in the AzureFirewallManagementSubnet. Traffic dedicated to Microsoft’s management of the nodes will go out to the Internet (but remains on Microsoft’s backbone) through the NIC in the AzureFirewallManagementSubnet. Traffic from your VMs will exist the NIC in the AzureFirewallSubnet. This split also means you can now attach a UDR (user defined route) to the AzureFirewallSubnet to route that traffic to your own security stack.
The Azure Firewall instance will take about 10-20 minutes to provision. While you’re waiting you need to prepare the Virtual Network Gateway for forced tunneling.
Now if you go Googling, you’re going to come across this Microsoft article which describes setting a GatewayDefaultSite for the VPN Gateway. While you can do it this way and you opt for an active/active both on-premises and for the VPN Gateway configuration, you’ll need to need to flip this setting to the other local network gateway (your other router) in the event of a failover.
As an alternative solution you can propagate a default route via BGP from your on-premises router into Azure. ECMP will be used by default and will spread the traffic across all available tunnels. If one of your on-premises routers goes down, traffic will still be able to flow back on-premises without requiring you to fail anything over on the Azure end. Note that if you want make one of your routers preferred, you’ll have to try your luck with AS Path Prepending.
For this lab scenario, I opted to broadcast a default route via BGP. My OpenBGPD config file is pictured below. Notice I’ve added a default route to be propagated.
Hopping over to Azure and enumerating the effective routes shows the new routes being propagated into the VNet via the VPN Gateway.
With this configuration, all traffic without a more specific route (like all our Internet traffic) will be routed back to the VPN Gateway. Since this lab calls for this traffic to be sent to Azure Firewall first, you’ll need to configure a UDR (user defined route). As described in this link, when multiple routes exist for the same prefix, Azure picks from UDRs first, then BGP, and finally system routes.
For this you’re going to need to set up three route tables.
One routing table will be applied to the primary subnet the VM is living in. This will contain a UDR for the default route (0.0.0.0/0) with a next hop type of Virtual appliance and next hop address of the Azure Firewall instance’s NIC in the AzureFirewallSubnet. By order of
The second routing table will be applied to the AzureFirewallSubnet. This will contain a UDR for the default route with a next hop of the Virtual network gateway. This forces Azure Firewall to pipe all the VM traffic bound for the networks outside the VNet to the Virtual Network Gateway which will then tunnel it through the VPN tunnel.
Last but not least, you have an optional route table you can add. This route table will be applied to the AzureFirewallManagementSubnet and will be configured with Virtual Network Gateway route propagation disabled. It will have a single UDR with a default route and next hop type of Internet. The reason I like adding this route table is it avoids the risk of someone propagating a default route from on-premises. If this route were to be propagated to the AzureFirewallManagementSubnet, the management plane would see it down and may deallocate the instance.
The last thing you need to do in Azure is create a rule in Azure Firewall to allow traffic to the web. For this I created a very simple application rule allowing all HTTP and HTTPS traffic to any domain.
At this point the Azure end of the configuration is complete. We now need to hop over to pfSense and finish that configuration.
Remember back in the last post when I had you configure the phase 2 entry with a local network of 0.0.0.0/0? That was the traffic selector which allows traffic destined for any network from the VNet to flow through our VPN tunnel.
Now you have a requirement to NAT traffic from the VNet out the WAN interface on the pfSense box. For that you have to navigate to the Firewall drop-down menu and choose the NAT menu item. From there you’ll navigate to the Outbound option and ensure your Outbound NAT Mode is set to Hybrid Outbound NAT rule generation since we’ll continue to leverage the automatic rules pfSense creates as well as this new custom rule.
Add a new mapping by clicking the Add button. For this you’ll want to configure it as seen in the screenshot below. Once complete save the new rule and new mappings.
Last but not least, we need to open flows within the pfSense firewall to allow the traffic to go out to the Internet over HTTP and HTTPS as seen below.
You’re done! Now time to test the configuration. For this you’ll want to RDP into your VM, open up a web browser, and try to hit a website.
Excellent, so you made it out to the web, but how do you know you were force tunneled through? Simple! Just hit a website like https://whatismyipaddress.com and validate the IP returned is the IP associated with your pfSense WAN interface.
One thing to note is that if you deallocate and reallocate your Azure Firewall or delete and recreate your Azure Firewall after everything is in place, you may run into an issue where forced tunneling doesn’t seem to work. All you need to do is bring down the VPN tunnel and bring it back up again. There is some type of dependency there, but what that is, I don’t know.
Well that’s it folks. Hope you enjoyed the series and got some value out of it. Azure Firewall is a solid alternative to a self-managed NVA. Sure you don’t get all the bells and whistles, but you get key capabilities such as transitive routing and features that build on NSGs such as filtering traffic via FQDN, centralized rule management, and centralized logging of what’s being allowed and denied through your network. As an added bonus, you can always leverage the forced tunneling feature you learned about today to tunnel traffic to a security stack which can perform features Azure Firewall can’t such as deep packet inspection.