I have to connect to a remote network using wireguard. The remote network has a DNS server to resolve all the internal hosts in the net. On Linux, I had a nice setup using systemd-resolved which would only ask the DNS server to resolve me hosts from that network but would still use my DNS server for all other requests. One reason might be that you also have internal hostnames on your own DNS and thus would loose ability to resolve them. Or, the VPN DNS server can not resolve AAAA records but you want to have a IPv6 connection as well. For Windows 10, I also had the issue that the DNS client would "loose" track which DNS server to ask and suddenly, I was not able to resolve the internal domains - even though the DNS server was set as the primary one.

The Linux setup is easy. Say there are the two DNS servers and in the remote network and the internal hosts are all in the domain internal.domain.name. Then specify in the wireguard config:

# ...
PostUp = resolvectl dns %i
PostUp = resolvectl dnssec %i no  # optional: enable, if the DNS server has DNSSec.
PostUp = resolvectl default-route %i no
PostUp = resolvectl domain %i internal.domain.name
# ...

You do not need a PostDown here, because resolvectl removes the entries on the interface automatically, if the interface is going down. Of course, this requires you to actually use systemd...

However, now I have to use a Windows 10 machine. The key component is the NRPT - the network resolution policy table. Windows provides some PowerShell commands to edit this table. With this tool, you can do exactly what we want: specify certain domains which are exclusivly resolved via another DNS server than the system's one.

First, enable script execution in Wireguard in the registry:

Windows Registry Editor Version 5.00


Read more about that in the Wireguard for Windows Documentation. Then, you can use PostUp and PostDown in the wireguard config:

PostUp = powershell -command "Add-DnsClientNrptRule -Namespace 'internal.domain.name','.internal.domain.name' -NameServers '',''"
PostDown = powershell -command "Get-DnsClientNrptRule | Where { $_.Namespace -match '.*internal\.domain\.name' } | Remove-DnsClientNrptRule -force"

Note, that we have to give the domain name twice: the first time to be able to resolve internal.domain.name and then with a prefixed dot, in order to resolve all hosts below. Also make sure that you comment out the DNS=, line in the wireguard config, as it would interfer with the powershell scripts.

One problem is, that you can not use nslookup to test if the setup works. You can use ping, which should be able to resolve correctly. Or you can use the powershell command Resolve-DnsName, which also gives a explaination how the name was resolved.