From: Daniel Lenski Date: Sat, 22 Jan 2022 21:48:16 +0000 (-0800) Subject: On newer versions of Windows, need `validate=no` when adding DNS servers X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=8c6dedcbd8563d0519594290e7840de77c3fb6ed;p=users%2Fdwmw2%2Fvpnc-scripts.git On newer versions of Windows, need `validate=no` when adding DNS servers This should fix https://gitlab.com/openconnect/openconnect/-/issues/375. It appears that on newer Windows systems, `netsh interface ipvX add dns` can take a long time to run, over 10 seconds. (See https://gitlab.com/openconnect/openconnect/-/issues/375#note_818616048 for examples.) This appears to be because of unwanted network I/O. Specifically, unless `validate=no` is specified, Windows will try to immediately connect to the server. Because OpenConnect is not yet exchanging packets over the tunnel when the vpnc-script is invoked, and hasn't even added IP *routes* for the tunnel yet, this connection cannot succeed in most configurations. If it can't connect: 1. It times out after ~10 seconds. 2. It prints a warning: "The configured DNS server is incorrect or does not exist." 3. It nevertheless adds the specified DNS server for the interface. 4. It returns success (exit status 0). This combination of effects explains why we weren't detecting and displaying the error. The `validate` option appears to be poorly documented; it appears in the help output of `netsh interface ipvX add dns` on Windows 10, but it doesn't appear in Microsoft's web documentation of `netsh interface ipvX add dns` for Windows 2008 (https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/cc731521(v=ws.10)#add-dnsserver), which is what their "netsh overview" documentation for Windows 2012 (https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/jj129394(v=ws.11)) refers readers to for comprehensive information. Furthermore, the `validate` option does not exist on older versions of Windows, but it's *enabled by default* on Windows 10. This means that we have to be sure to append `validate=no` on newer versions of Windows, but *not* to append it on older version. Bang-up job as usual, Microsoft. 🤬 Signed-off-by: Daniel Lenski --- diff --git a/vpnc-script-win.js b/vpnc-script-win.js index 29b53c8..982ca6d 100644 --- a/vpnc-script-win.js +++ b/vpnc-script-win.js @@ -97,6 +97,14 @@ case "pre-init": break; case "connect": var gw = getDefaultGateway(); + + var winVer = null; + if (run("ver").match(/version\s+((\d+\.)+\d+)/i)) { + winVer = RegExp.$1; + echo(INFO, "Running on Windows version: " + winVer); + } else + echo(ERROR, "Could not determine Windows version from 'ver' command"); + // Use INTERNAL_IP4_ADDRESS as the "gateway" address for the // VPN tunnel connection. As noted in the OpenConnect source, // "It's a tunnel; having a gateway is meaningless." Setting @@ -162,7 +170,12 @@ case "connect": var dns = env("INTERNAL_IP4_DNS").split(/ /); for (var i = 0; i < dns.length; i++) { var protocol = dns[i].indexOf(":") !== -1 ? "ipv6" : "ipv4"; - run("netsh interface " + protocol + " add dns " + env("TUNIDX") + " " + dns[i]); + // With 'validate=yes' (the default on newer Windows versions), Windows will try to + // connect to the DNS server, time out after ~10 seconds, and print a warning, but + // nevertheless add the specified server. Adding 'validate=no' is thus necessary. + // FIXME: determine the earliest Windows version that actually requires this flag. + run("netsh interface " + protocol + " add dns " + env("TUNIDX") + " " + dns[i] + + (winVer >= "10." ? " validate=no" : "")); } echo(INFO, "Configured " + dns.length + " DNS servers: " + dns.join(" ")); }