Preface
This article covers the setup of my hub VNET as well as the bug I experienced in Windows version of nslookup. If you are already familiar with setting up Azure Hub & Spoke and only interested in the Windows-bug you can skip to nslookup bug.
I’m testing all of this with Windows 11: Version 22H2 (Build 22621.24.28)
.
Screencast
Situation
While I was researching and trying out Azure Hub & Spoke architectures I one day needed to setup a P2S (point-to-site) connection between an Azure environment and my machine. This environment also had Azure Private DNS resolver running and configured on the VNET gateway so that you could have name resolution in your VPN tunnel. The test was about to be performed using an Azure SQL Server configured with Private Endpoints meaning that you should be able to reach this server from within Azure or over the VPN.
So here are some description on the resources involved.
Here is an overview:
Virtual Network
I’ve created a virtual network (VNET) named vnet-dd-spock-test
. Its sole address space is 10.0.0.0/8
and it has 4 subnets:
GatewaySubnet
(10.0.3.0/27) which is the subnet in which the VNET gateway lives.Vm
(10.0.2.0/24) which in the feature can hold network interfaces for VMs.PrivateLink
(10.0.1.0/4) which is reserved for private endpoint addresses.Inbound
(10.2.0.0/24) which is needed for DNS resolver (later)
The last special thing about this VNET is that it has a custom DNS server of 10.2.0.4
configured which as you can see lives in the range of the Inbound
subnet.
Gateway
The Virtual Network Gateway vgw-dd-spock-test
is configured to work route based and is bound to the dynamic public IP pip-dd-vgw-spock-pri-test
. The gateway also has set its authentication type to Azure Active Directory
(which is not renamed to Entra yet) and promotes addresses to clients from the CIDR range 192.168.4.0/24
. The last point means that when a client connects to this gateway using P2S it will get an IP address from that range on its network adapter. This gets important later!
DNS
To allow us to access resources by using DNS later we configure 2 main resources.
First we deploy an Azure Private DNS resolver. This allows us to generate a custom DNS server just for our VNET. Doing this requires us to connect this resolver to our VNET and create and inbound endpoint which we call ep-inbound
. This is connected to the Inbound
subnet of our VNET and gets the IP 10.2.0.4
. As you can see this is the same IP as the DNS server which was configured into the VNET!
Then the we deploy an Azure DNS Zone (private) to our tenant. In it we configure 1 A record with the name privatelink.database.windows.net
. This is needed for private endpoints later so that the Azure DNS will be able to resolve requests to Azure SQL databases configured to use private endpoints to be resolved to [SERVERNAME].privatelink.database.windows.net
. In this zone I added 1 A record with the following setting manually:
Name Type TTL Value Auto registred
sql-dd-spock-test A 3600 10.0.1.4 False
We will later deploy an Azure SQL with that name. See how the resolved IP address points to the Private Link subnet.
Azure SQL
At last I deploy an Azure SQL with the following setup in networking:
- Public access disabled completely
- Private access using private endpoint
pep-dd-sql-spock-test
. - Connectivity policy set to the
Default
option
The authentication is set to Microsoft Entra ID only.
nslookup bug
So after I established a P2S connection using the Azure VPN Client I tried to validate if the correct private address of 10.0.1.4
is getting resolved on DNS requests:
nslookup sql-dd-spock-test.database.windows.net
Server: MYROUTER
Address: IP_OF_MY_ROUTER
Not authorized answer:
Name: cr4.westeurope1-a.control.database.windows.net
Address: 104.**.**.**
Aliases: sql-dd-spock-test.database.windows.net
sql-dd-spock-test.privatelink.database.windows.net
dataslice9.westeurope.database.windows.net
dataslice9westeurope.trafficmanager.net
which is not the case as you can tell be the 104* address.
Bug hunt
On this point I was brought on a complete confusing and unnecessary track. Here are some steps I went:
- Using
Get-NetIPInterface
andSet-NetIPInterface -InterfaceIndex "INDEX_OF_VPN" -InterfaceMetric "X”
where X is a value lower than every other in the list. - Starting
gpedit.msc
and enabling rules inComputer -> Administrative Templates -> Network -> DNS
which are related to LLMNR (Local Multicast Name Resolution). - Trying to manipulate interface metrics using this suggestion.
Solution
After some investigation it turned out that using the PowerShell cmdlet which represents nslookup
will work correctly:
Resolve-DnsName sql-dd-spock-test.database.windows.net
Name Type TTL Section NameHost
---- ---- --- ------- --------
sql-dd-spock-test.database.win CNAME 300 Answer sql-dd-spock-test.privatelink.database.windows.net
Name : sql-dd-spock-test.privatelink.database.windows.net
QueryType : A
TTL : 1800
Section : Answer
IP4Address : 10.0.1.4
which now resolves correctly. Also the connection using SQL Management Studio worked without any issue. I just wasn’t aware that resolution of the IP was happening using nslookup so I never tried to connect.
A solution for me is to add this line to my POSH profile:
Set-Alias -Name nslookup -Value Resolve-DnsName
so that future calls of nslookup will always use the working POSH version.
Summary
So Microsoft added fixes for DNS resolution on Windows but “forgot” to update nslookup
accordingly. Because this tool is used a lot in samples and videos I just wanted to share my experience.