[Openvpn-devel,v1] iservice: set adapter DNS only with search domains

Message ID 20251210072951.25753-1-gert@greenie.muc.de
State New
Headers show
Series [Openvpn-devel,v1] iservice: set adapter DNS only with search domains | expand

Commit Message

Gert Doering Dec. 10, 2025, 7:29 a.m. UTC
From: Heiko Hund <heiko@ist.eigentlich.net>

With NRPT the adapter name server configuration is not needed
theoretically. However DNS config is not showing with traditional
tools like ipconfig if they are left out. More importantly if
there are no DNS servers configured for an adapter the adapter
specific search domains are not recognized by the Windows resolver.

However, adding the servers to the adapter has the side effect, that
general look-ups are now also done using this adapter, which might
come as unexpected and yield wrong results, if there is some trickery
happening with the default DNS, for example.

As a workaround, set the adapter DNS only when strictly needed.

Change-Id: I6debe8bbedd5a08da417bfee1243a43ef6df7980
Signed-off-by: Heiko Hund <heiko@ist.eigentlich.net>
Acked-by: Selva Nair <selva.nair@gmail.com>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1429
---

This change was reviewed on Gerrit and approved by at least one
developer. I request to merge it to master.

Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1429
This mail reflects revision 1 of this Change.

Acked-by according to Gerrit (reflected above):
Selva Nair <selva.nair@gmail.com>

Comments

Gert Doering Dec. 10, 2025, 9:44 a.m. UTC | #1
So this is a workaround for windows DNS "search domain" and NRPT interfering
in interesting ways - to make "search domain" work (aka "append these domains
to unqualified hostnames") the search domain + DNS server need to be
configured on the VPN interface.  To make "resolve domain" work in non-
surprising ways (aka "query that nameserver for these domains *and only*
for these domains") the DNS server must not be added to the VPN interface...

In mobile environments with DNS64 and other surprises, querying "all DNS
over the normal WAN, and only corp-internal resolve-domains via VPN" is
the expected behaviour - so what we did so far (resolve-domains go to 
the VPN only, everything else *goes to all DNS servers*) was surprising,
and breaks certain scenarios...

So this does
  - if there is a search-domain
  - or if there is *no* resolve-domain
  - set the DNS on the adapter ("to be used by normal windows DNS processing")

what is not affected by the patch is what we already have
  - if there is a resolve-domain, set up a NRTP rule ("for this domain,
    query these nameservers [only]")

More details in https://github.com/OpenVPN/openvpn/issues/473 ...

Thanks, Selva, for testing this so quickly :-) - I have only stared at the
code, thought about the logic, and tried to make this explanatory e-mail
as clear as possible.

Your patch has been applied to the master branch.

commit f7afbc511b9d30b27d0b6bbb3ee02dfb1abea646
Author: Heiko Hund
Date:   Wed Dec 10 08:29:44 2025 +0100

     iservice: set adapter DNS only with search domains

     Signed-off-by: Heiko Hund <heiko@ist.eigentlich.net>
     Acked-by: Selva Nair <selva.nair@gmail.com>
     Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1429
     Message-Id: <20251210072951.25753-1-gert@greenie.muc.de>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg34968.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering

Patch

diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c
index 6f04f6b..9327dfa 100644
--- a/src/openvpnserv/interactive.c
+++ b/src/openvpnserv/interactive.c
@@ -2869,11 +2869,19 @@ 
         goto out;
     }
 
-    /* Set name servers */
-    err = SetNameServerAddresses(iid, msg->addresses);
-    if (err)
+    /*
+     * Set DNS on the adapter for search domains to be considered.
+     * If split DNS is configured, do this only when search domains
+     * are given, so that look-ups for other domains do not go over
+     * the VPN all the time.
+     */
+    if (msg->search_domains[0] || !msg->resolve_domains[0])
     {
-        goto out;
+        err = SetNameServerAddresses(iid, msg->addresses);
+        if (err)
+        {
+            goto out;
+        }
     }
 
     /* Set search domains, if any */