From 0b562b88731b785776b69fa24fea635e08918260 Mon Sep 17 00:00:00 2001 From: "xinpeng.wang" Date: Wed, 8 Apr 2026 17:58:19 +0800 Subject: [PATCH] dns: force default-route for VPNs without routing domains When a VPN connection is configured with "never-default=true" (e.g., the "Use this connection only for resources on its network" option is checked), NetworkManager currently does not mark the link as having a default route for DNS purposes. If the VPN also does not provide any specific search or routing domains, its DNS servers are effectively dropped and not passed to systemd-resolved. This results in a "split-tunneling trap": the user has routes to the internal network, but cannot resolve internal hostnames. This commit introduces a fallback: if a VPN has no specific routing domains, we force the has_default_route property to TRUE. This ensures that: 1 The VPN's DNS servers are registered with systemd-resolved. 2 systemd-resolved can perform parallel lookups (routing queries to both the physical link and the VPN link). 3 The VPN's higher DNS priority is respected for these queries without hijacking the actual IP routing for internet traffic. This fixes the issue where internal DNS becomes unreachable when split-tunneling is enabled on VPNs that don't explicitly push search domains. --- src/core/dns/nm-dns-manager.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index ec33c46427..ec40f195bc 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -1751,6 +1751,20 @@ _mgr_configs_data_construct(NMDnsManager *self) has_default_route_explicit || (priority < 0 && has_default_route_auto); ip_data->domains.has_default_route = ip_data->domains.has_default_route_exclusive || has_default_route_auto; + /* * Heuristic: If this is a VPN and it has no specific search or routing + * domains, it would normally be ignored by systemd-resolved unless it + * has a default route. + * + * When 'never-default' is TRUE (split-tunnel), we force 'has_default_route' + * here to ensure NM pushes these DNS servers to resolved. This allows + * resolved to perform parallel queries across both the physical and VPN + * links, ensuring internal hostnames can still be resolved without + * breaking global internet connectivity. + */ + if (ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN + && !nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, &num) + && !nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, &num)) + ip_data->domains.has_default_route = TRUE; { gs_free char *str1 = NULL;