Connectivity check fails when using systemd-resolved and a VPN with exclusive DNS
I'm using: NetworkManager-1.38.4-1.fc36.x86_64 NetworkManager-openvpn-1.8.18-1.fc36.x86_64
I have an OpenVPN setup for my Fedora 36 system. The VPN connections have "dns-search=~.;" in the IPV4 section. This is intentional, for security reasons, we want all DNS to go over the VPN. I noticed that when I'm on the VPN, my ethernet device shows limited connectivity. In GNOME, I see a question mark over the ethernet connection.
$ nmcli networking connectivity check
limited
I set the logging to have level=TRACE and domains=CONCHECK under [logging] in /etc/NetworkManager/NetworkManager.conf.
When I'm on the the VPN, when NetworkManager tries to do a connectivity check on my ethernet interface, I see this in the logs:
Oct 05 10:42:02 myhostname NetworkManager[2609]: <debug> [1664980922.6595] connectivity: (enp0s13f0u1u1,IPv4,194) start request to 'http://fedoraproject.org/static/hotspot.txt' (try resolving 'fedoraproject.org' using systemd-resolved)
Oct 05 10:42:02 myhostname NetworkManager[2609]: <debug> [1664980922.6612] connectivity: (enp0s13f0u1u1,IPv4,194) can't resolve a name via systemd-resolved: GDBus.Error:org.freedesktop.resolve1.NoNameServers: No appropriate name servers or networks for name found
Oct 05 10:42:02 myhostname NetworkManager[2609]: <debug> [1664980922.6613] connectivity: (enp0s13f0u1u1,IPv4,194) check completed: LIMITED; resolve-error
That's weird, my DHCP is providing DNS servers, and when I'm not on the VPN, they're provided. But then I remembered that in Fedora 36, we're using systemd-resolved. So I checked out the output of 'resolvectl dns':
Before VPN activation:
$ resolvectl dns
Global:
Link 2 (enp0s13f0u1u1): 192.168.1.1
Link 3 (wlp0s20f3):
(you can ignore my wifi interface, it's not active)
After VPN activation:
$ resolvectl dns
Global:
Link 2 (enp0s13f0u1u1):
Link 3 (wlp0s20f3):
Link 5 (tun0): 10.11.5.19 10.2.32.1
Well, what do you know? It doesn't have any DNS servers anymore on the ethernet interface.
I think what is happening is because there's the '~.' in the dns-search settings, NetworkManager is removing the DNS servers from the ethernet interface. The way that the NetworkManager connectivity check works is that it runs a check using libcurl, forcing it to use the interface's DNS servers, to ensure connectivity checks are using that interface. Because systemd-resolved has no DNS servers being returned via the dbus call, NetworkManager is unable to perform a connectivity check.
Perhaps NetworkManager's connectivity check needs to be updated for situations where a VPN is disabling the DNS on the interface? It looks like NetworkManager still knows about what DNS servers were provided to the interface when it came up initially, so when systemd-resolved returns that it doesn't have a DNS entry, it can fall back to what NetworkManager has already stored.