If you are reading this, you probably already know what Azure Private Link is: a representation of a service such as Azure Storage, Azure SQL Database, Azure Application Service, or even some application running in a different Virtual Network, in your own Virtual Network with a private IP address of your own.
This is a fantastic feature, many organizations have been waiting for this for a long time. Now that say your Azure Storage account is accessible via a private IP address, what if you want to restrict traffic to it, so that not everybody in your organization has IP connectivity to it?
Please realize that not everybody will want to do this, since for many organizations authentication is enough security to control who can and who cannot access a certain service. However, others will like to combine authentication security with networking security.
Your first option to filter network traffic inside of a Virtual Network would be Network Security Groups (NSGs). Unfortunately, private link endpoints do not support NSGs (see Private Endpoint Limitations). Mmmh.
Of course, if you cannot apply NSGs at the destination (the private endpoint), you can apply at the source to apply those network restrictions. Wait a second: that would be a perfectly valid measure for other Azure workloads, but what is the source is not in Azure, but on-premises? Right, no NSGs on-premises. Our next tactics will be using a traffic filtering device such as the Azure Firewall. We will see a couple of tricks that we will need for this to work.
Sending traffic through an Azure Firewall (or any Network Virtual Appliance) in Azure is a two-step process: for a flow between the private endpoint and on-premises we need to send packets from on-prem to the Azure Firewall, as well as the return traffic from the private endpoint.
The first part is relatively easy: traffic coming from on-premises will land in either a VPN or an ExpressRoute gateway. In both cases, in your GatewaySubnet (unless you are using a 3rd-party network appliance to terminate your VPN, but the concept is the same). This means that to redirect traffic from on-prem to the Azure Firewall you need a route table on the GatewaySubnet.
There is one thing you need to know: creating private link endpoints injects /32 routes into your Azure subnets. Hence you want to create User-Defined Routes for your endpoint using specific /32 prefixes too (otherwise, the most specific prefix will win). Unfortunately you cannot verify the effective route table of your gateways, but believe me, there are few things out there that can beat a static /32 route.
Now for the return traffic, it depends on which Azure service you are routing to. For example, for Azure Storage it is going to be easier than you think. Private Link is not your grandma’s NIC, but it is using flow-based networking: when answering packets it will send them to the same place they came from. In English: in private endpoints for Azure Storage we don’t need UDRs for the return traffic, and no route tables in the private link subnet.
However, other Azure Services might behave differently and cause asymmetric routing, so SNATting your traffic at the NVA is probably a good idea. This way you can be sure that you have no asymmetric routing, regardless which Azure service your private link refers to.
You don’t believe me? Test Azure SQL and Azure Storage private link with Azure Firewall with my Azure CLI script here!