I’m connected to local area network with access to the Internet through gateway. There is DNS server in local network which is capable of resolving hostnames of computers from local network.
I would like to configure systemd-resolved and systemd-networkd so that lookup requests for local hostnames would be directed (routed) exclusively to local DNS server and lookup requests for all other hostnames would be directed exclusively to another, remote DNS server.
Let’s assume I don’t know where the configuration files are or whether I should add more files and require their path(s) to be specified in the answer.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
In the configuration file for local network interface (a file matching the name pattern /etc/systemd/network/*.network) we have to either specify we want to obtain local DNS server address from DHCP server using DHCP= option:
[Network] DHCP=yes
or specify its address explicitly using DNS= option:
[Network] DNS=10.0.0.1
In addition we need to specify (in the same section) local domains using Domains= option
Domains=domainA.example domainB.example ~example
We specify local domains domainA.example domainB.example to get the following behavior (from systemd-resolved.service, systemd-resolved man page):
Lookups for a hostname ending in one of the per-interface domains are
exclusively routed to the matching interfaces.
This way hostX.domainA.example will be resolved exclusively by our local DNS server.
We specify with ~example that all domains ending in example are to be treated as route-only domains to get the following behavior (from description of this commit) :
DNS servers which have route-only domains should only be used for the
specified domains.
This way hostY.on.the.internet will be resolved exclusively by our global, remote DNS server.
Note
Ideally, when using DHCP protocol, local domain names should be obtained from DHCP server instead of being specified explicitly in configuration file of network interface above. See UseDomains= option. However there are still outstanding issues with this feature – see systemd-networkd DHCP search domains option issue.
We need to specify remote DNS server as our global, system-wide DNS server. We can do this in /etc/systemd/resolved.conf file:
[Resolve] DNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844
Don’t forget to reload configuration and to restart services:
$ sudo systemctl daemon-reload $ sudo systemctl restart systemd-networkd $ sudo systemctl restart systemd-resolved
Caution!
Above guarantees apply only when names are being resolved by systemd-resolved – see man page for nss-resolve, libnss_resolve.so.2 and man page for systemd-resolved.service, systemd-resolved.
See also:
- Description of routing lookup requests in systemd related man pages is unclear
- How to troubleshoot DNS with systemd-resolved?
References:
- Man page for systemd-resolved.service, systemd-resolved
- Man page for resolved.conf, resolved.conf.d
- Man page for systemd-network
Method 2
Just to expand on @piotrDobrogost ‘s excellent answer, don’t forget to config /etc/nsswitch.conf to use systemd-resolved as a DNS resolution source. Your hosts directive should look as follows for your particular use case:
/etc/nsswitch.conf
hosts: files resolve dns
So if you limit the resolution to only those domains specified in the Domains directive in /etc/systemd/resolved.conf as Piotr details above, DNS should next be consulted in the order of name resolution sources specified /etc/nsswitch.conf when domains are NOT found in Domains directive:
The following link references the requirement to specify resolve in /etc/nsswitch.conf so systemd-resolved is consulted during name resolution:
https://github.com/systemd/systemd/issues/940
SystemD documentation I’ve found to be dire. I had to piece together an understanding from multiple links, including Piotr’s answer above 😉
Method 3
If you are doing this because you have an connection configured with OpenVPN, you need to use https://github.com/jonathanio/update-systemd-resolved as per https://wiki.archlinux.org/index.php/OpenVPN#The_update-systemd-resolved_custom_script
Specifically, once, you have the update-systemd-resolved script installed and active in your OpenVPN client config, you’ll also add dhcp-option DOMAIN-ROUTE yourdomain.com to the same client config.
You should see the following output from OpenVPN:
<14>Apr 22 16:10:31 update-systemd-resolved: Link 'tun0' coming up <14>Apr 22 16:10:31 update-systemd-resolved: Adding DNS Routed Domain yourdomain.com <14>Apr 22 16:10:31 update-systemd-resolved: Adding DNS Domain yourdomain.com <14>Apr 22 16:10:31 update-systemd-resolved: Adding IPv4 DNS Server 192.168.XYZ.XYZ <14>Apr 22 16:10:31 update-systemd-resolved: SetLinkDNS(640 1 2 4 192 168 XYZ XYZ) <14>Apr 22 16:10:31 update-systemd-resolved: SetLinkDomains(640 2 yourdomain.com false yourdomain.com true)
And you can verify the DNS configuration with resolvectl status:
Link 3 (wlp0s....)
Current Scopes: DNS
DefaultRoute setting: yes
LLMNR setting: yes
MulticastDNS setting: no
DNSOverTLS setting: no
DNSSEC setting: no
DNSSEC supported: no
Current DNS Server: 192.168.XYZ.XYZ
DNS Servers: 192.168.XYZ.XYZ
DNS Domain: ~.
lan
Link 640 (tun0)
Current Scopes: DNS
DefaultRoute setting: no
LLMNR setting: yes
MulticastDNS setting: no
DNSOverTLS setting: no
DNSSEC setting: no
DNSSEC supported: no
Current DNS Server: 192.168.XYZ.XYZ
DNS Servers: 192.168.XYZ.XYZ
DNS Domain: ~yourdomain.com
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0