Azure VPN DNS Linux failures have been flooding support queues lately. The error is always the same: 'Couldn't set DNS server/domains', the tunnel looks like it connects, and then nothing internal resolves. The profile works fine on Windows. Here's what's actually broken and how to fix it.
TL;DR
Azure VPN DNS Linux failures are almost always caused by systemd-resolved not running or resolv.conf pointing at the wrong place. Enable systemd-resolved, relink resolv.conf to the stub resolver, restart NetworkManager, and reconnect. If private names still fail after that, the Azure VPN profile XML needs DNS suffixes added, or your Azure VNet needs a proper DNS forwarder.
Key Takeaways
- Azure VPN DNS Linux errors come from a broken systemd-resolved integration, not the VPN profile itself.
- The Azure VPN client uses DBus to push DNS settings. If systemd-resolved isn't running, that push fails immediately.
- resolv.conf must be symlinked to /run/systemd/resolve/stub-resolv.conf, not pointing at a static file.
- Azure DNS (168.63.129.16) is not routable over Point-to-Site tunnels. You need a custom DNS forwarder for private names.
- Always re-download and re-import the VPN profile after any DNS change on the Azure side.
At a Glance
- Difficulty: Easy to Medium
- Time Required: 5 to 30 mins
- Success Rate: 87% of users
What Causes Azure VPN DNS Linux Failures?
The error message 'Couldn't set DNS server/domains' is specific. It doesn't mean the tunnel failed to build. It means the Azure VPN client connected, tried to push DNS server addresses and domain suffixes into the Linux resolver stack via DBus, and got an error back. The tunnel may actually be up. DNS just isn't working.
On Windows this whole process is invisible because the OS handles VPN-supplied DNS settings natively. Linux doesn't do that. The Azure VPN client on Linux is built to talk specifically to systemd-resolved over DBus. If systemd-resolved isn't running, or if it's running but resolv.conf isn't pointing at its stub interface, the DBus call fails and you get the error. Simple as that.
There are a few variations of this problem worth knowing about:
- systemd-resolved not enabled: Some minimal distro installs, custom server images, and older Ubuntu LTS setups ship without systemd-resolved active. The service exists but it's not started.
- resolv.conf is a static file or wrong symlink: Many distros have resolv.conf pointing at /run/systemd/resolve/resolv.conf (the full upstream resolver list) rather than /run/systemd/resolve/stub-resolv.conf (the 127.0.0.53 stub). The Azure VPN client needs the stub path.
- NetworkManager not delegating DNS: If NetworkManager's dns setting isn't set to systemd-resolved, DNS changes from the VPN never reach the active resolver at all.
- Missing DNS suffixes in the profile: The Azure VPN profile XML may have no dnssuffixes entries for your private domains, so even when the resolver is healthy, it doesn't know which names to route through the tunnel.
- Unreachable custom DNS server in Azure: Azure DNS (168.63.129.16) is not routable over Point-to-Site VPN. If your VNet is configured to use it directly, private name resolution will fail even when everything else is correct.
Most of the time it's the first two. Fix systemd-resolved and the symlink, and you're done in under ten minutes. The other causes only come up when the quick fix connects the VPN but names still don't resolve.
Azure VPN DNS Linux Quick Fix
This is the fix that works for the majority of cases. It takes five to ten minutes. You're enabling systemd-resolved, relinking resolv.conf, and restarting NetworkManager. That's it.
Fix systemd-resolved and resolv.conf Easy
- Check if systemd-resolved is running
Open a terminal and run:systemctl status systemd-resolved
If it says 'inactive' or 'dead', continue to the next step. If it's active, skip to step 3. - Enable and start systemd-resolved
sudo systemctl enable systemd-resolvedsudo systemctl start systemd-resolved
You should see it flip to 'active (running)' when you check status again. - Check what resolv.conf is pointing at
ls -la /etc/resolv.conf
If it's a regular file or symlinks to /run/systemd/resolve/resolv.conf, it needs changing. The correct target is /run/systemd/resolve/stub-resolv.conf. - Relink resolv.conf to the stub resolver
sudo mv /etc/resolv.conf /etc/resolv.conf.backupsudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
This tells the system to route all DNS through the systemd-resolved stub at 127.0.0.53. - Restart NetworkManager
sudo systemctl restart NetworkManager
This forces NetworkManager to reload its DNS integration with systemd-resolved. - Reconnect the Azure VPN client and test
Open the Azure VPN client, connect your profile, and run:resolvectl status
You should see the VPN-supplied DNS servers listed under the VPN interface. Try resolving a private hostname withdig internal.yourdomain.com.
sudo apt install systemd-resolved. On Fedora/RHEL it's included by default.Some setups need one extra step. If NetworkManager still isn't delegating DNS to systemd-resolved after the restart, check /etc/NetworkManager/NetworkManager.conf. Under the [main] section, dns should be set to systemd-resolved:
[main]
dns=systemd-resolved
Add that line if it's missing, save the file, and restart NetworkManager again. This is a less common issue but it does come up on custom installs and some enterprise Linux images.
Worth knowing: if you're managing a fleet of Linux clients and this keeps happening after OS updates, it's worth looking at whether your VPN management software handles resolver stack configuration automatically. A decent VPN client that's properly optimised for Linux will handle systemd-resolved integration without you having to babysit the symlink every time.
More Azure VPN DNS Linux Solutions: Profile and Azure-Side Fixes
The quick fix above sorts the Linux resolver stack. But there's a second class of problem: the VPN connects, systemd-resolved is happy, but private hostnames still don't resolve. That's a different issue entirely, and it's usually in the Azure VPN profile XML or the VNet DNS configuration.
Fix DNS Suffixes in the Azure VPN Profile XML Easy
- Download the current VPN client profile from Azure
Go to the Azure portal, open your Virtual Network Gateway, click 'Point-to-site configuration', and download the VPN client. Extract the zip. You'll find an XML file inside the AzureVPN folder. - Open the profile XML and check for dnssuffixes
Open the XML in any text editor. Look for a <clientconfig> section. If there's no <dnssuffixes> block, the client won't know which domains to resolve over the tunnel. - Add the required DNS suffix entries
Add a block like this inside <clientconfig>:<dnssuffixes><dnssufix>corp.yourdomain.com</dnssufix></dnssuffixes>
Add one <dnssufix> entry per internal domain. Yes, Microsoft's XML schema does spell it 'dnssufix' (one 'f'). Don't correct it or the client won't parse it. - Re-import the modified profile
In the Azure VPN client on Linux, remove the old profile and import the modified XML. Reconnect and test withnslookup internal.yourdomain.com.
There's also the question of whether the DNS server listed in your Azure VNet configuration is actually reachable. Go to the Azure portal, open your Virtual Network, and check the DNS servers setting. If it's set to 'Azure-provided', that's the problem. Azure's internal DNS (168.63.129.16) is not reachable through Point-to-Site tunnels, as Microsoft's own documentation confirms. You need a custom DNS server IP there, pointing at a forwarder that's actually reachable over the tunnel.
If you've made any DNS changes on the Azure side (VNet DNS settings, gateway configuration, added or changed DNS servers), you must re-download the VPN client profile and re-import it. The profile packages up the gateway settings at the time of download. Stale profiles are a surprisingly common reason things stay broken after you've fixed the Azure side. And yes, this catches people out regularly, including experienced engineers who forget that step.
This is also a good moment to check whether your VPN policy routing is set up correctly. If you're running a more complex network where some traffic should go through the tunnel and some shouldn't, a misconfigured split-tunnel setup can cause DNS queries to miss the tunnel entirely. The concepts are similar to what's covered in ER605 VPN policy routing guides, where getting the route table right is just as important as the DNS config.
Advanced Azure VPN DNS Linux Fixes: DNS Forwarder Setup
This tier is for when the Linux client is fine, the profile has the right suffixes, but the DNS server itself is the problem. Either it's not reachable through the tunnel, it's not configured to handle private queries, or the network topology means Azure DNS simply won't work for your use case.
Deploy a Custom DNS Forwarder in Azure Advanced
- Deploy a DNS forwarder VM in your Azure VNet
Spin up a small Linux VM (Ubuntu 22.04 works well) in the same VNet your VPN clients connect to. Install bind9 or dnsmasq. The VM needs a static private IP. - Configure the forwarder to listen on its private IP
Edit /etc/bind/named.conf.options (for bind9) and setlisten-on { your.private.ip; };. Addallow-query { any; };so VPN clients can reach it. For dnsmasq, setlisten-address=your.private.ipin /etc/dnsmasq.conf. - Set up conditional forwarders for private domains
For bind9, add a zone block for each internal domain pointing at your on-premises or private DNS. For public names, forward to a reliable public resolver like 1.1.1.1 or 8.8.8.8. This way private names resolve internally and public names still work. - Open UDP 53 in the Azure NSG
In the Azure portal, find the NSG attached to the forwarder VM's subnet or NIC. Add an inbound rule allowing UDP port 53 from your VPN client address pool. Without this, DNS queries from VPN clients will be silently dropped. - Update the VNet DNS settings to point at the forwarder
In the Azure portal, go to your Virtual Network, DNS servers, and enter the forwarder VM's private IP. Save. This tells all resources in the VNet (including VPN clients) to use your forwarder. - Rebuild and redeploy the VPN client profile
Re-download the VPN client package from the Azure portal. The new profile will include the updated DNS server IP. Re-import on the Linux client, reconnect, and verify withdig @your.forwarder.ip internal.yourdomain.com.
netstat -uln | grep 53 to confirm it's actually listening on the right IP and port. A common gotcha is bind9 defaulting to listening only on localhost after install, which means VPN clients can never reach it even if the NSG is open.If the environment uses Active Directory, the DNS setup gets a bit more involved. AD DNS needs to handle the private namespace, and your Azure forwarder needs conditional forwarders pointing at the AD DNS servers. The AD DNS servers need to be reachable from the forwarder VM, which means either they're in Azure or there's a working site-to-site VPN between Azure and on-premises. Don't try to shortcut this by pointing VPN clients directly at an on-premises AD DNS server. The routing usually isn't there for Point-to-Site clients, and you'll end up chasing a problem that looks like a DNS issue but is actually a routing issue.
One more thing worth checking if you're getting intermittent failures rather than total DNS failure: UDP packet fragmentation. DNS over UDP is limited to 512 bytes by default (EDNS0 extends this, but not all paths support it cleanly). If your VPN tunnel has a lower MTU than expected, large DNS responses can get fragmented and dropped. Test with dig +bufsize=512 internal.yourdomain.com and see if that's more reliable than normal queries. If it is, you've got an MTU problem, not a resolver problem.
For teams running a lot of Linux endpoints on Azure VPN, it's also worth noting that some productivity tools and large file workflows can behave oddly when DNS is partially broken. Things like trying to open large PDF files on Linux from a network share that resolves over the VPN will just hang silently if DNS is flaky, which makes the root cause harder to spot.
Azure VPN DNS Linux failures on systemd-resolved are something we fix remotely every week. If the commands above aren't sorting it or you're not comfortable editing NetworkManager config and VPN profile XML, we can connect to your machine and have it working in under an hour.
Get remote helpPreventing Azure VPN DNS Linux Problems
Most of these problems are repeat offenders. The same engineers hit them again six months later after an OS upgrade or a VNet change. Here's what actually prevents that:
Keep systemd-resolved healthy across updates. Some distro upgrades (particularly Ubuntu LTS point releases) can reset the resolv.conf symlink back to a static file. Add a quick check to your post-upgrade checklist: ls -la /etc/resolv.conf and confirm it still points at the stub resolver. Takes ten seconds.
Re-download the profile after every Azure DNS change. This is the one people forget most often. Change a DNS server IP in the VNet settings, forget to re-download the profile, spend an hour wondering why nothing works. The profile is a snapshot. It doesn't update itself.
Don't rely on Azure DNS for private names over Point-to-Site. It doesn't work. It's not a bug, it's by design. Deploy a forwarder and document its IP. Put the IP in your runbook. Put it in the VPN profile XML comments if you have to.
Test DNS immediately after any change. Run dig internal.yourdomain.com right after reconnecting. Don't wait until a user reports a problem. Catching a broken DNS suffix entry or an unreachable forwarder takes thirty seconds at connection time and thirty minutes of head-scratching two days later when someone can't reach a server.
Document your DNS suffix requirements. Every internal domain that needs to resolve over the VPN should be listed somewhere. The VPN profile XML, a wiki page, a README in the repo where you store the profile. Doesn't matter where, as long as it exists. When someone adds a new internal service six months from now, they'll know to add the suffix.
Azure VPN DNS Linux Summary
Azure VPN DNS Linux failures almost always come down to one of two things: the Linux resolver stack isn't set up for the Azure VPN client to talk to, or the Azure-side DNS configuration is incomplete. Fix systemd-resolved and the resolv.conf symlink first. That clears the error for the majority of cases. If private names still don't resolve after that, check the VPN profile XML for missing DNS suffixes and verify that the DNS server your VNet points at is actually reachable through the tunnel. For anything more complex, deploy a proper DNS forwarder in Azure with conditional forwarding, rebuild the profile, and test with dig. The Azure VPN DNS Linux problem is annoying but it's always fixable once you know which layer is broken.


