I am using NextDNS, which works just fine at home (both for wired and wi-fi). I have followed their advice and configured DNS at /etc/systemd/resolv.conf.d/10-nextdns.conf like this:
So far, so good. The problem is that when I connect to my work VPN, I need it to use their own DNS (at least as a fallback), because some of their servers are local. To make matters worse, their DNS server can’t do DNSOverTLS.
I managed to workaround this creating a /etc/systemd/network/20-tun.network with:
This solves the home x work problem, but won’t work for other VPNs because it imposes a fixed DNS configuration to all of them.
There is also another problem: when I use a wired connection at work, I cannot use NextDNS, for the same reasons explained above.
So, my questions are: how can I detect during network configuration if I am at home or work? And how can I choose different configuration files for each scenario?
I know I could use some post-configuration script to do the job, but I was hoping there is some more elegant (or proper) way to handle this.
The IP address assigned to your interface is probably different at home vs work and can assist. Activating the VPN to work should automatically switch the dns and routing for you.
You use a VPN? What type?
Does not the default dns config work for you at either location? It would seem the dhcp server should assign the proper dns config at both sites.
What necessitates adding in the extra layer of NextDNS? Personal choice or other problems? Adding in additional complexities results in extra configs when one is not at a fixed location or using a fixed network config.
Hi @computersavvy ! Yes, the IP is different on each scenario, but I couldn’t see how I could use it on the [Match] section of /etc/systemd/network/20-tun.network (AFAICS I can match by interface name, type, kind and many other characteristics, but not the assigned IP )
Not sure if that’s what you are asking, but my work VPN configuration uses password over certificates (TLS) for authentication. It has been provided by our IT staff.
It is not really a necessity, I decided to try NextDNS after a couple of friends talked wonders about it. It is pretty cool, actually.
Ok folks, time for some updates. TL;DR: it is working for the scenario where I am at home and connect via VPN. Following @vgaetera 's advice, I wrote a script that will hopefully do the necessary tweaks when I am at work (will test it next week).
What I did was:
Removed the global configuration at /etc/systemd/resolved.conf.d/10-nextdns.conf
Changed /etc/systemd/network/10-tun.network to be:
[Match]
Kind=tun
[Network]
# Work DNS configuration
# ...
Domains=<work domain>
DNSOverTLS=false
Changed /etc/systemd/network/20-eth-wifi.network to be:
Last but not least, I wrote this /etc/NetworkManager/dispatcher.d/10-eth-work.sh :
#!/bin/bash
WORK_DNS=...
WORK_DOMAIN=...
NEXTDNS_DNS=...
LOG="/tmp/dns-config"
if [[ "${IP4_GATEWAY}" =~ <work dns gateway> ]]; then
case ${NM_DISPATCHER_ACTION} in
up)
resolvectl dns ${DEVICE_IFACE} ${WORK_DNS}
resolvectl domain ${DEVICE_IFACE} ${WORK_DOMAIN}
resolvectl dnsovertls ${DEVICE_IFACE} no
echo "gateway: ${IP4_GATEWAY}" >> $LOG
echo "using work DNS" >> $LOG
;;
down)
resolvectl dns ${DEVICE_IFACE} ${NEXTDNS_DNS}
resolvectl domain ${DEVICE_IFACE} "~."
resolvectl dnsovertls ${DEVICE_IFACE} yes
echo "using NextDNS" >> $LOG
;;
esac
fi
I still have some doubts, and there is most likely a better way to handle this (eg. I know I will need to adapt it if I start using other VPNs aside from work), but I’m optimistic this might do the job for the time being Tips and advice are more than welcome
On second thought, I guess it might not make much sense to configure DNS when an interface goes down, so maybe this is an improved version of the core logic:
if [[ ${NM_DISPATCHER_ACTION} == "up" ]]; then
if [[ "${IP4_GATEWAY}" =~ <work gateway> ]]; then
resolvectl dns ${DEVICE_IFACE} ${WORK_DNS}
resolvectl domain ${DEVICE_IFACE} ${WORK_DOMAIN}
resolvectl dnsovertls ${DEVICE_IFACE} no
echo "gateway: ${IP4_GATEWAY}" >> ${LOG}
echo "using work DNS" >> ${LOG}
else
resolvectl dns ${DEVICE_IFACE} ${NEXTDNS_DNS}
resolvectl domain ${DEVICE_IFACE} "~."
resolvectl dnsovertls ${DEVICE_IFACE} yes
echo "using NextDNS" >> ${LOG}
fi
fi
I think you should specify these settings including DoT per connection with NetworkManager, and systemd-resolved should be smart enough to properly split and route DNS traffic, so perhaps you don’t even need a dispatcher script.
That’s cool, I thought I was limited to the GUI options, but nmcli gives me so much more. Thanks for pointing me that!
So, indeed I moved a lot of the particular details to the corresponding profiles. One problem, though, is that I would need two different profiles for wired (one for work, and one for home). But I don’t see how to make NM automatically choose the right one. So far, I created two different profiles for ethernet, but I have to manually choose which one I want to use. Am I missing something here?
If not, then I might not be able to avoid using NM’s dispatcher scripts after all – which is not really a problem, I was just hoping I could switch to handling everything entirely through NM.
When using nmcli one may name the connection and have several different connections named using the same interface but different configs. This may be the approach one should use.
Yes, that’s what I did. I now have two different wired profiles, one named “Wired - NextDNS” and the other named “Wired - Work”, both targeting the ethernet interface enp3s0 but each of them specifically tailored to its needs. It works, my only (and minor) complaint is that I have to manually choose the work profile when I am at work, and manually switch back to the home profile when I come back home, unless I rely on dispatcher scripts. I’ll play around with it a little to see how it goes.
Yep, the system cannot check even the IP until the connection has been made and it seems you might need some way to first boot with no connection then the user selects the required connection based on location. Thus it may not be possible to fully automate it in your situation.
Though it would be quite possible to have a script that runs during user login to ask the user which connection is desired then activate the proper one. The script could be called from /etc/bashrc or from /home/USER/.bashrc. Not quite automatic but almost.
Hi everyone, I made some progress, this is the current status:
Moved all the static configuration from resolved to NetworkManager – at first I tried mixing some bits, but resolved would override NM’s configuration
Tweaked NM’s profiles to better represent the use cases (nmcli helps a lot with that providing access to every possible setting – thanks @vgaetera !)
Tweaked NM dispatcher scripts to do some post configuration, using resolvectl instead of nmcli to avoid an infinite loop
I still need to test the “wired at work” use case, but I am confident it will work. My only problem right now is that, for some reason, resolved is still overriding some changes, even though it has no more specific settings of its own. For example:
Aug 09 12:19:23 fedoracosta systemd-resolved[950]: enp3s0: Bus client set DNS server list to: ...
Aug 09 12:19:23 fedoracosta systemd-resolved[950]: enp3s0: Bus client set search domain list to: ~.
Aug 09 12:19:23 fedoracosta systemd-resolved[950]: enp3s0: Bus client set default route setting: yes
Aug 09 12:19:23 fedoracosta systemd[1]: iscsi.service: Unit cannot be reloaded because it is inactive.
Aug 09 12:19:25 fedoracosta systemd-resolved[950]: enp3s0: Bus client reset search domain list.
Aug 09 12:19:25 fedoracosta systemd-resolved[950]: enp3s0: Bus client set default route setting: no
Aug 09 12:19:25 fedoracosta systemd-resolved[950]: enp3s0: Bus client reset DNS server list.
The last 3 lines have undone the top 3 ones
The result in practice is harmless, what I was trying to accomplish was to route the name resolution of my work domain through VPN (tun0), and all the rest to NextDNS through enp3s0. If I do the same modifications through the command line after the VPN is up, it works as intended:
As it is right now, everything goes through my work’s DNS servers while the VPN is up, which is not ideal, but perfectly acceptable. Still, I feel I am missing something here…
Link 2 (enp3s0)
Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
Protocols: +DefaultRoute LLMNR=resolve -mDNS +DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 45.90.28.0#fedora-xxx.dns.nextdns.io
DNS Servers: 45.90.28.0#fedora-xxx.dns.nextdns.io 2a07:a8c0::#fedora-xxx.dns.nextdns.io
45.90.30.0#fedora-xxx.dns.nextdns.io 2a07:a8c1::#fedora-xxx.dns.nextdns.io
DNS Domain: ~.
IPv4 NextDNS servers are reachable through tun0, while IPv6 servers are reachable through enp3s0, but this is ok since I am directing to work DNS only queries of its own domain. NextDNS confirms that I am using their DNS, and I can also reach internal work servers.
So, if I can only manage to prevent resolved (or NM) from undoing these last changes to en3ps0, I will be in heaven
I removed all NetworkManager dispatcher scripts. And that’s it! The good old KISS principle strikes again
I believe the key points were: providing a global DNS config, setting DNSOverTLS to opportunistic, and setting the default Domains to ~.
With this, DNS queries with the work domain are being directed to work DNS, and all others to NextDNS (regardless if am physically at home or work)
I don’t claim this is the proper way to do it, but I am glad this is (finally!) working I’ll mark this as the solution, but if anyone has any improvement to contribute, I will be more than happy to include it here.