In the Private Link post last month I said DNS is where private endpoint implementations go to die, and promised the resolution architecture. Here it is. The historical fix was a pair of Windows or BIND VMs in the hub forwarding queries between on premises and Azure, VMs someone had to patch, monitor, and resurrect at 3 AM. Azure DNS Private Resolver deletes those VMs from your architecture.
The Two Directions of Hybrid DNS
Hybrid DNS is two problems. Direction one: on premises clients need to resolve Azure private names, your privatelink zones, so a query for stcorpdataprod.blob.core.windows.net from a datacenter server must reach Azure DNS and return the private endpoint IP. Direction two: Azure workloads need to resolve on premises names, corp.contoso.local living on domain controllers in the datacenter. The Private Resolver handles both with two endpoint types. An inbound endpoint gives Azure DNS a private IP inside your VNet that on premises DNS servers can forward to. An outbound endpoint, paired with forwarding rulesets, sends queries for your on premises domains from Azure to your datacenter DNS servers.
resource "azurerm_private_dns_resolver" "this" {
name = "dnspr-hub-weu"
resource_group_name = azurerm_resource_group.dns.name
location = "westeurope"
virtual_network_id = azurerm_virtual_network.hub.id
}
resource "azurerm_private_dns_resolver_inbound_endpoint" "this" {
name = "in-ep"
private_dns_resolver_id = azurerm_private_dns_resolver.this.id
location = "westeurope"
ip_configurations {
private_ip_allocation_method = "Dynamic"
subnet_id = azurerm_subnet.dns_inbound.id
}
}
resource "azurerm_private_dns_resolver_outbound_endpoint" "this" {
name = "out-ep"
private_dns_resolver_id = azurerm_private_dns_resolver.this.id
location = "westeurope"
subnet_id = azurerm_subnet.dns_outbound.id
}
resource "azurerm_private_dns_resolver_dns_forwarding_ruleset" "this" {
name = "ruleset-hybrid"
resource_group_name = azurerm_resource_group.dns.name
location = "westeurope"
private_dns_resolver_outbound_endpoint_ids = [
azurerm_private_dns_resolver_outbound_endpoint.this.id
]
}
resource "azurerm_private_dns_resolver_forwarding_rule" "corp" {
name = "corp-contoso-local"
dns_forwarding_ruleset_id = azurerm_private_dns_resolver_dns_forwarding_ruleset.this.id
domain_name = "corp.contoso.local."
enabled = true
target_dns_servers {
ip_address = "10.200.1.10"
port = 53
}
target_dns_servers {
ip_address = "10.200.1.11"
port = 53
}
}
resource "azurerm_private_dns_resolver_virtual_network_link" "spokes" {
name = "link-hub"
dns_forwarding_ruleset_id = azurerm_private_dns_resolver_dns_forwarding_ruleset.this.id
virtual_network_id = azurerm_virtual_network.hub.id
}
The resolver needs dedicated delegated subnets for its endpoints, a /28 each is enough. Rulesets link to VNets, and any linked VNet using Azure provided DNS automatically applies the forwarding rules, no per VM DNS settings.
The Reference Flow
Putting it together for the whole estate. Spoke VNets either use Azure DNS directly with ruleset links, or, in designs where the firewall proxies DNS, point at the firewall which forwards to the inbound endpoint. All privatelink zones stay linked to the hub VNet as before, so any query arriving at Azure DNS through the inbound endpoint resolves private endpoints correctly. On premises DNS servers get one conditional forwarder per Azure consumed zone, blob.core.windows.net and friends, aimed at the inbound endpoint IP over ExpressRoute or VPN. Azure workloads querying corp.contoso.local match the forwarding rule and egress via the outbound endpoint to the domain controllers. Both directions, no VMs, and the resolver is a zone redundant managed service so the resilience conversation is over.
Details That Matter
Forward the parent public zones from on premises (blob.core.windows.net, not privatelink.blob.core.windows.net), because the CNAME chain resolves inside Azure DNS and forwarding the privatelink zone directly misses records for resources without private endpoints. Keep one ruleset for the estate rather than per team copies. Watch the resolver metrics for query volume against the per endpoint limits, high tens of thousands of QPS per inbound endpoint, and scale with additional IP configurations if a busy estate approaches them. And once this is in place, delete the forwarder VMs with ceremony. They served, and they are done.
Cheers
Osama
Leave a comment