Migrating from Self-Managed DNS to Azure Private DNS - Marcin Gastol
15815
post-template-default,single,single-post,postid-15815,single-format-standard,bridge-core-3.0.7,bridge,qode-page-transition-enabled,ajax_fade,page_not_loaded,,qode-title-hidden,qode-child-theme-ver-1.0.0,qode-theme-ver-29.4,qode-theme-bridge,qode_header_in_grid,wpb-js-composer js-comp-ver-6.10.0,vc_responsive

Migrating from Self-Managed DNS to Azure Private DNS

Intro

Azure Private DNS provides a reliable way to resolve private endpoint and internal service names inside Azure virtual networks. However, as hub-and-spoke networks grow, DNS becomes a security boundary as much as a name-resolution service. If workloads can query any resolver directly, teams lose visibility into what is being resolved and may accidentally bypass central inspection.

This article walks through a practical approach for restricting and monitoring DNS traffic with Azure Firewall and Network Security Groups (NSGs), then shows how to apply the pattern at scale with PowerShell.

The Challenge: DNS Bypass and Limited Visibility

In complex Azure environments, especially those using Private Link, shared services, and hybrid DNS forwarding, you may encounter:

Direct DNS egress: Workloads query public resolvers or Azure-provided DNS directly instead of using the approved path.

Inconsistent resolution: Firewall FQDN rules and client DNS queries use different DNS answers.

Private endpoint troubleshooting gaps: Teams can see that port 53 is allowed or denied, but not always which FQDN was requested.

Configuration drift: Each spoke VNet, subnet, or NSG gradually develops its own DNS exceptions.

Audit blind spots DNS changes and DNS query patterns are not consistently sent to Log Analytics or SIEM tooling.

Contingency planning

To achieve seamless DNS failover, you need a solid contingency plan that covers both DNS configuration and monitoring. The diagram below illustrates the general idea: an active primary environment and a passive secondary environment. A DNS-based failover mechanism (such as Azure Traffic Manager for public DNS) constantly monitors the primary’s health and automatically directs clients to the secondary when the primary degrades. We can implement a similar concept using Azure Private DNS and an alternate provider through custom automation.

The Solution: Centralize DNS Through Azure Firewall

A resilient DNS security pattern is to make Azure Firewall the controlled DNS proxy path for workload subnets, then use NSGs as guardrails to prevent bypass.

At a high level:

– Enable **Azure Firewall DNS Proxy**.

– Configure workload VNets to use the firewall private IP as their DNS server.

– Use an upstream DNS service that can resolve your private zones, such as central DNS forwarders or Azure DNS Private Resolver inbound endpoints.

– Add NSG outbound rules that allow DNS only to Azure Firewall and deny direct DNS to other destinations.

– Enable Azure Firewall DNS logs and virtual network flow logs for monitoring.

Important: Azure Firewall DNS Proxy forwards downstream client queries to its configured upstream DNS servers. If clients need Private DNS zone answers, make sure the upstream DNS path can resolve those private zones.

Define endpoints and variables

Begin by specifying the primary and secondary IP addresses (or endpoints) for the service, the DNS record to update and any other parameters. You’ll also need the resource group and Private DNS zone name for Azure. For example:

PowerShell
$resourceGroup = "MyDNSResourceGroup"
$zoneName = "contoso.internal"
$recordName = "app"
$primaryIP = "10.1.2.5"       # Primary private endpoint IP
$secondaryIP = "52.4.6.8"    # Secondary public/alternate endpoint IP
$recordType = "A"
$ttl = 30  # desired TTL for the record (in seconds)

In a real script, these values could come from a config file or arguments.

Health check the primary service

Use a cmdlet like Test-Connection or a web request to determine if the primary endpoint is healthy. For instance, if a ping or TCP connection to the primary IP fails, we consider the service down. Alternatively, use an HTTP probe if the service is a web application (e.g., Invoke-WebRequest -Uri http://app.contoso.com/health). Example with ping:

PowerShell
$primaryAlive = Test-Connection -ComputerName $primaryIP -Count 2 -Quiet
if ($primaryAlive) {
    Write-Host "Primary endpoint is reachable."
} else {
    Write-Warning "Primary endpoint is down. Initiating DNS failover..."
}

In this snippet, -Quiet returns a simple Boolean indicating success or failure of the ping.

Failover Logic – update DNS record

check indicates failure, the script will update the DNS record in the Private DNS zone to point to the secondary IP. This uses Azure PowerShell cmdlets to modify the DNS record set. A straightforward way is to retrieve the existing record set, modify it, and apply the update:

PowerShell
if (-not $primaryAlive) {
    # Get the current DNS record set
    $recordSet = Get-AzPrivateDnsRecordSet -ResourceGroupName $resourceGroup `
                -ZoneName $zoneName -Name $recordName -RecordType $recordType
    # Remove any existing A records and add the secondary IP
    $recordSet.RecordSets.Records.Clear()   # Clear current IPs
    Add-AzPrivateDnsRecordConfig -RecordSet $recordSet -Ipv4Address $secondaryIP
    # Update TTL if needed
    $recordSet.RecordSets.TTL = $ttl
    # Push the changes to Azure
    Set-AzPrivateDnsRecordSet -RecordSet $recordSet -Overwrite
    Write-Host "DNS record updated to secondary IP $secondaryIP"
}

The above snippet uses Get-AzPrivateDnsRecordSet to fetch the record (e.g., the A record for “app.contoso.internal”), then clears out the old IP and adds the new one and finally applies the update with Set-AzPrivateDnsRecordSet. (In Azure PowerShell, the Private DNS cmdlets allow you to build a record set object and then commit it); also adjust the TTL to a low value for rapid propagation. The -Overwrite flag ensures the update goes through even if the record has changed since we fetched it.

Note: In production, include error handling (try/catch) around these commands and possibly send notifications when a failover occurs.

(Optional) Update alternate provider

If you are also maintaining a secondary DNS provider (for example, a public Azure DNS zone or a third-party DNS), you would include API calls or cmdlets for that provider here. For Azure public DNS, you could use similar Azure PowerShell commands (Get-AzDnsRecordSet / Set-AzDnsRecordSet from the Az.Network module) to update the public DNS zone. For third-party services, you might call their REST API or use CLI tools.

The principle is the same: switch the A record (or alias) to the backup endpoint.

Failback monitoring

The script can loop (perhaps running on a schedule via Azure Automation or a Windows Scheduled Task). After failing over, it should keep checking the primary. Once the primary service is back up, the script can reverse the process: update the DNS record back to the primary IP. Be careful to only fail back when the primary is fully confirmed healthy to avoid flapping. You might implement a threshold (e.g. require 5 consecutive successful checks before failing back).

Wrapping it all up

Automating DNS failover between Azure Private DNS zones and alternate providers ensures that your internal and hybrid applications remain available even when disasters strike. We began by recognizing the importance of DNS failover and how Azure Private DNS, while powerful for internal name resolution, requires thoughtful planning to integrate into a failover strategy. By examining common failure scenarios highlighted why a dual-provider DNS setup (or backup DNS zone) can save critical downtime.

Planning is the backbone of successful DNS failover: adjust TTLs to balance rapid failover with stability, set up rigorous health monitoring and choose a secondary DNS solution that will be reachable when the primary is not; keep DNS records in sync across primary and secondary providers and to rehearse the failover process through drills

With a plan in place, we can use automation tools to do the heavy lifting. PowerShell scripts can interface directly with Azure Private DNS to update records on-the-fly, triggered by health check logic; showed how to use Azure PowerShell cmdlets to detect a failure and modify a Private DNS record set with a new IP address in real-time. For those preferring Azure CLI or working in Linux environments, a Bash script with az network private-dns commands achieves the same outcome, removing the failed endpoint’s DNS record and adding a new one that directs clients to the backup service. Both approaches rely on Azure’s APIs to quickly propagate changes and they can be extended to update other DNS providers’ records as well.

No Comments

Post A Comment

Verified by MonsterInsights