Skip to content

Instantly share code, notes, and snippets.

  • Star 50 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Configure systemd-resolved to use a specific DNS nameserver for a given domain

Configure systemd-resolved to use a specific DNS nameserver for a given domain

Use case


  • I use a VPN to connect to my work network
  • I'm on a Linux computer that uses systemd-resolved
  • I have a work domain called
  • is hosted by both public and private DNS nameservers
  • Both public and private nameservers claim to be authoritative for
  • There are no public hosts in
  • The public resolvers for resolve all queries to a parked hosting webpage
  • The private resolvers for contain all correct DNS records for private hosts

I need to

  • Resolve private hosts in when connected to VPN

(Note that this should also work for pointing DNS-blocked domains at different, non-blocked nameservers)


systemd-resolved now has the ability to specify nameservers for specific domains. Until recently this was not the case, systemd-resolved leaned on NetworkManager, which used dnsmasq for this purpose.

If you were already doing something like this to accomplish this task, first undo all of that. We're not going to use NetworkManager/dnsmasq.

In your systemd-resolved config, which for me is at /etc/systemd/resolved.conf (Fedora), make sure you have this (assuming private nameservers are and


Note the tilde, that makes systemd-resolved do something special. According to the man page:

Specified domain names may optionally be prefixed with "~". In this case they do not define a search path, but preferably direct DNS queries for the indicated domains to the DNS servers configured with the system DNS= setting (see above), in case additional, suitable per-link DNS servers are known.

Restart systemd-resolved and you should be in business.

Copy link

Other domains use default resolvers.

But setting DNS= is a global configuration, its true for all queries.

We can check this by doing some tcpdumping and running drill queries.

Here is my config:

Domains=~tp.private ~telecomplus.internal

And resolvectl shows:

$ resolvectl
           Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
    resolv.conf mode: stub
  Current DNS Server:
         DNS Servers:
Fallback DNS Servers: 2606:4700:4700::1111 2620:fe::10 2001:4860:4860::8888
          DNS Domain: ~telecomplus.internal ~tp.private

Now I fire off a drill query: $ drill

And see it come though on my wireguard interface:

$ sudo tcpdump -n -i wg5 -v dst
tcpdump: listening on wg5, link-type RAW (Raw IP), snapshot length 262144 bytes
14:02:38.696029 IP (tos 0x0, ttl 64, id 58942, offset 0, flags [DF], proto UDP (17), length 71) > 25402+ A? (43)

Now I query some other domain: $ drill

And the query still goes to my globally set resolver:

14:03:04.832655 IP (tos 0x0, ttl 64, id 63171, offset 0, flags [none], proto UDP (17), length 70) > 37446+ [1au] A? (42)

If I drop my routes to, and try to query: $ drill

14:16:49.444783 lo    In  IP (tos 0x0, ttl 64, id 25792, offset 0, flags [DF], proto UDP (17), length 57) > 25378+ A? (29)
14:16:49.445140 wlan0 Out IP (tos 0x0, ttl 64, id 7787, offset 0, flags [none], proto UDP (17), length 57) > 36000+ A? (29)
14:16:49.445208 wlan0 Out IP (tos 0x0, ttl 64, id 61977, offset 0, flags [none], proto UDP (17), length 68) > 48708+ [1au] A? (40)
14:16:49.475123 wlan0 In  IP (tos 0x0, ttl 61, id 22812, offset 0, flags [none], proto UDP (17), length 100) > 48708 2/0/1 A, A (72)
14:16:49.475337 lo    In  IP (tos 0x0, ttl 1, id 64858, offset 0, flags [DF], proto UDP (17), length 89) > 25378 2/0/0 A, A (61)

We still try to resolve against, fail and try which is the resolved I get from my home router for the wifi link:

Link 4 (wlan0)
    Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
         Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server:
       DNS Servers: 2001:8b0::2021 2001:8b0::2020

Copy link

dreua commented Dec 20, 2021

Yeah I don't see how this will work which is quite unfortunate -.-

Copy link

You want a systemd-networkd.service, like this:


Domains=~telecomplus.internal ~tp.private

You still need to tie this config to an interface, but interface doesn't need to exist for the service to be "active".

Copy link

dreua commented Dec 21, 2021

@george-angel can you elaborate on how to set this up and why it works? What does wg5 stand for? I'm using NetworkManager and a dummy interface in the meantime which seems to work fine for my use case. It is important to me that only the matching requests are sent to that DNS server, when I tried the suggested setup with resolved.conf I could resolve the needed Domains but only because all DNS requests were sent to the specific DNS server. (It happily resolves everything but I don't want to use it for everything.)

Copy link

The way it works with networkd - the specific resolver is tied to an interface, I don't really like it, but thats the way it is.

In my case wg5 is the interface name for the wireguard interface I create that routes my private subnets. I think you can replace that name with your "dummy" reference.

More info here:

Copy link

leiless commented Dec 30, 2022

sudo resolvectl dns eth0
resolvectl dns eth0

Copy link

thanks, you save my day ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment