Windows 11 WSL2 DNS and OpenVPN Split Tunnel#
On modern Windows 11 + WSL 2, the reliable VPN-friendly DNS path is WSL DNS tunneling. If you want Linux tools inside WSL to follow the same DNS policy as Windows apps, keep /etc/resolv.conf auto-generated and let the Windows DNS Client make the routing and suffix decisions.
This post focuses on the current Windows 11 + WSL 2 model, not the older manual resolv.conf workaround. It also shows how to keep OpenVPN in split-tunnel mode while preserving internal DNS resolution in both Windows and WSL.
Modern WSL2 DNS on Windows 11#
Recommended Configuration#
In Windows, configure %UserProfile%\.wslconfig:
In WSL, keep /etc/wsl.conf simple:
[network]
# Optional, already the default; keep it enabled for WSL DNS tunneling
# generateResolvConf=true
If you also want systemd, enable it separately:
Then restart WSL from PowerShell:
Notes:
dnsTunneling=trueis the feature that makes WSL DNS follow Windows DNS Client behavior. Microsoft specifically recommends it when you use a VPN, because many VPN clients rely on NRPT rules, and those rules are only applied to WSL DNS queries when DNS tunneling is enabled.- What matters for DNS tunneling is that you do not disable
generateResolvConf, because Microsoft notes DNS tunneling will not be successfully enabled ifgenerateResolvConf=false. systemd=trueis optional. It is useful for services and timers, but it does not need to "own"/etc/resolv.confin this setup.
What /etc/resolv.conf Should Look Like#
With DNS tunneling enabled, WSL generates resolv.conf and points it at the Windows-side DNS tunnel IP:
$ cat /etc/resolv.conf
# This file was automatically generated by WSL.
nameserver 10.255.255.254
search home.lan corp.example
Notes:
10.255.255.254is WSL'sdnsTunnelingIpAddress.- In NAT mode with DNS tunneling enabled, WSL brings over Windows DNS suffixes into the
searchline. The order follows Windows DNS behavior: global suffixes first, then supplemental suffixes, then per-interface suffixes. - The exact
searchvalues change when your network or VPN state changes.
The Resolution Path#
When a WSL app resolves app.corp.example, the flow is:
- The Linux app reads
/etc/resolv.confand sends the query to10.255.255.254. - WSL tunnels the request directly to Windows instead of sending a normal DNS packet from the VM to the host.
- The Windows DNS Client applies Windows DNS policy: NRPT rules, DNS suffix search order, per-interface DNS servers, and Windows-side DoH or DoT settings.
- Windows forwards the query to the appropriate resolver, such as your home router or the VPN's internal DNS servers.
This is the key change on modern WSL 2: Windows, not a hand-configured Linux stub resolver, makes the final DNS policy decision.
Manual resolv.conf Mode (generateResolvConf=false)#
You can still disable WSL's generated resolv.conf and point Linux at systemd-resolved or another local resolver, but for modern Windows 11 + WSL 2 + VPN setups that is an advanced custom path, not the recommended one.
If you set generateResolvConf=false:
- you opt out of the WSL-generated DNS tunnel configuration;
- you become responsible for upstream DNS servers and suffix search behavior inside Linux;
- WSL will no longer automatically mirror Windows VPN DNS behavior for you.
So if your main goal is "WSL should behave like Windows when the VPN connects," keep generateResolvConf=true.
OpenVPN Split Tunnel with DNS#
A split tunnel means only company routes go through the VPN. Your normal internet traffic keeps using the local connection, while internal company names still resolve correctly.
OpenVPN Client Configuration#
Use a client config like this:
# Prevent the VPN from replacing your normal internet route
route-nopull
# Send only company networks through the VPN
route 10.0.0.0 255.0.0.0 vpn_gateway
route 172.16.0.0 255.240.0.0 vpn_gateway
# Use company DNS on the VPN adapter
dhcp-option DNS 10.0.0.1
dhcp-option DNS 10.0.0.2
# Set the VPN adapter's connection-specific DNS suffix
dhcp-option DOMAIN corp.example
# Optional: if your company uses more than one internal suffix
# dhcp-option DOMAIN-SEARCH eng.corp.example
# dhcp-option DOMAIN-SEARCH corp.example
The key line here is route-nopull. Without it, many company VPN profiles push a full-tunnel default route, often via redirect-gateway, which sends all traffic through the VPN gateway instead of only company traffic.
That usually makes normal internet access slower and more fragile. Public traffic such as Microsoft Teams calls, public Docker image pulls, package downloads, and ordinary web browsing can all end up going through the corporate VPN path even though they do not need to.
With route-nopull, you keep the VPN tunnel itself, but you only add the private routes you actually want to send through it.
Manual routes required
The tradeoff is that you need to know the company private subnets in advance and add them manually. If you miss one, that internal network will stay on your normal local route and will not be reachable through the VPN.
Why dhcp-option DOMAIN Matters#
dhcp-option DOMAIN corp.example does not create Windows NRPT rules by itself. What it does is set the VPN adapter's connection-specific DNS suffix.
That matters for two reasons:
- short names like
appcan expand toapp.corp.example; - with WSL DNS tunneling enabled, Windows DNS suffixes are propagated into WSL's
searchline, so Linux tools benefit from the same suffix.
If your VPN already deploys NRPT rules, Windows will still use those rules for *.corp.example. The DOMAIN option complements NRPT by making suffix search consistent instead of leaving Windows and WSL to guess.
This is also why .local is a poor example for corporate DNS. .local is typically treated as mDNS, not normal unicast DNS, so it can make a healthy VPN setup look broken.
How to Find Your VPN DNS Servers#
To get the correct internal DNS IPs:
- Connect to the VPN using the original working profile.
- In PowerShell, run
ipconfig /all. - Find the OpenVPN adapter.
- Copy the IPs listed under
DNS Servers. - Reuse those IPs in your split-tunnel config.
OpenVPN 2.7+ and pull-filter#
route-nopull tells the client not to install server-pushed routes and DHCP-style DNS options. That is what prevents the VPN from silently turning your split tunnel back into a full tunnel. In OpenVPN 2.7+, you may still see warnings because the server did push those directives and your client is overriding them.
pull-filter ignore is the cleanup step: it drops matching server-pushed directives before OpenVPN processes them. That keeps the logs quieter and makes it explicit that your local client config is authoritative.
Notes:
pull-filteruses prefix matching.pull-filter ignore "route"drops pushedroute,route-gateway, and other route-related directives.pull-filter ignore "dhcp-option "drops pushed DNS and domain suffix options so they do not conflict with the values you set locally.- Only add these filters if the server really is pushing overlapping directives and you want the local client config to win.
Verification#
Inside WSL, confirm that DNS tunneling is active:
grep -E '^(nameserver|search)' /etc/resolv.conf
# nameserver 10.255.255.254
# search home.lan corp.example
Then test name resolution and routing:
getent hosts app.corp.example: confirms that a fully qualified internal name resolves.getent hosts app: if you rely on short names, this confirms that the DNS suffix search list is working.nc -zv app.corp.example 443: confirms both DNS resolution and reachability over the VPN, if the target app is actually listening on TCP port 443.curl ifconfig.me: should still show your normal local public IP, proving that internet traffic is not being forced through the VPN.
If /etc/resolv.conf points at 127.0.0.53 or a manually configured public DNS server instead of 10.255.255.254, you are not using the modern WSL DNS tunneling path described above.