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).
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:
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
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!
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.
At last I deploy an Azure SQL with the following setup in networking:
- Public access disabled completely
- Private access using private endpoint
- Connectivity policy set to the
The authentication is set to Microsoft Entra ID only.
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.
On this point I was brought on a complete confusing and unnecessary track. Here are some steps I went:
Set-NetIPInterface -InterfaceIndex "INDEX_OF_VPN" -InterfaceMetric "X”where X is a value lower than every other in the list.
gpedit.mscand enabling rules in
Computer -> Administrative Templates -> Network -> DNSwhich are related to LLMNR (Local Multicast Name Resolution).
- Trying to manipulate interface metrics using this suggestion.
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.
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.