Opened 9 years ago

Closed 8 years ago

Last modified 7 years ago

#605 closed Bounty task (fixed)

Windows 10 DNS Leak

Reported by: debbie10t Owned by: Samuli Seppänen
Priority: major Milestone:
Component: Generic / unclassified Version: OpenVPN git master branch (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords: Windows10 DNS
Cc:

Description

Windows 10 DNS resolver always uses local DNS server, which defeats the point of --redirect-gateway / Road-Warrior scenario.

See:
https://forums.openvpn.net/post54826.html#p54826

This looks like something that will really be worth resolving, hopefully, somebody with good Windows skills can find a solution.

Attachments (1)

testfw-d1.zip (131.4 KB) - added by ValdikSS 8 years ago.

Download all attachments as: .zip

Change History (27)

comment:2 Changed 8 years ago by ValdikSS

Interesting fact # 1: leak could be avoided if route-gateway is used without def1 parameter AND network (internet) interface uses DNS not from local segment. This way OpenVPN removes default internet gateway and adds default route via tunnel. It works because Windows 8.1+ binds to the interface before sending DNS request and if we don't have route via specific interface, the request won't be sent. But Windows 10 re-adds default route via internet adapter after some time (I suppose this somehow bound to lease time but I'm not sure) with lower metric (always!) which causes all your traffic to bypass VPN even if it is connected and visually everything looks fine.

Interesting fact # 2: Built-in VPN configuration (tested with IPsec IKEv2) somehow sets system up to avoid DNS leaks if your DNS on internet adapter is out of local segment. We have the same situation with two default gateways, one (VPN) with lower metric and another (internet) with higher, but Windows doesn't do DNS queries like it does with OpenVPN connection. If we can force this behavior for OpenVPN, we fix this issue.

comment:3 Changed 8 years ago by Samuli Seppänen

We've noticed this in OpenVPN Connect also and have a guy looking into this. I'll report back when we have more info.

comment:4 Changed 8 years ago by Gert Döring

Owner: set to Samuli Seppänen
Status: newassigned

Assigning to samuli for the time being. When Connect has a solution, please let me know and I'll see how we can integrate it.

(Or have someone send a patch :-) )

I hope it's "just another netsh.exe command" to increase DNS interface priorities...

comment:5 Changed 8 years ago by Gert Döring

see also #596, but it seems to be more complicated than "just" interface metrics. *grumble*

Thanks, ValdikSS for the background info on Win8/Win10 DNS flow. Win8 seems to be fixable by the interface metric thing, Win10 confuses me.

Last edited 8 years ago by Gert Döring (previous) (diff)

comment:6 Changed 8 years ago by ValdikSS

I'm afraid this issue is wider than just interface metrics. OpenVPN by default creates interface with the lowest default metric (10 AFAIK) and it's not likely that any other interface would get lower metric by default as 10 is the lowest default value. But after some time, as I wrote earlier, if you don't use def1 option in redirect-gateway, Windows will spot deleted default interface route (which has been deleted ‎by OpenVPN) and add it again with LOWER by one point metric ALWAYS. If you had OpenVPN default gateway with metric 10 without Internet gateway, Windows would add one with metric 9 a bit later (a bit earlier than IP lease time I suppose).
I can't remember this right now, but as far as I remember, lowering OpenVPN interface metric to 1 and setting Internet interface metric to 10000 didn't help.
With def1 it works fine, but there is no proper way to mitigate DNS leak then. The only way is to set DNS to 127.0.0.1 on all other interfaces but this is permanent modification which survives reboot. It's not acceptable to leave user with broken DNS and, from user perspective, broken Internet connection in case of sudden power loss or OpenVPN crash.‎

comment:7 Changed 8 years ago by ValdikSS

Windows sets interface metrics according to their interface speed. The faster speed the lower metric, the lowest default value is 10 for gigabit links and faster. When you connect to VPN (IKEv2 in my tests) with build-in VPN client, Windows increases interface metrics on all interfaces up to ‎4000 as a base value and VPN gets the lowest metric. Although Windows doesn't remove default route via Internet link (there are two default routes and vpn has lower metric), there is no DNS leak if your DNS on Internet interface doesn't belong to local segment (8.8.8.8 works fine). This doesn't work with OpenVPN. I suppose Windows set some kind of parameter to the default Internet route to prevent DNS queries to use it. That explains why it doesn't work in OpenVPN and why leaks still happen if you use local segment DNS (as it would use not the default route but local route).

comment:8 Changed 8 years ago by debbie10t

This looks promising (worth including here):
http://superuser.com/questions/966832/windows-10-dns-resolution-via-vpn-connection-not-working

Happy I do not have access to W10 to test.

Last edited 8 years ago by debbie10t (previous) (diff)

comment:9 in reply to:  8 Changed 8 years ago by ValdikSS

Replying to debbie10t:

This looks promising (worth including here):
http://superuser.com/questions/966832/windows-10-dns-resolution-via-vpn-connection-not-working

Happy I do not have access to W10 to test.

Just tried it — it works with built-in Windows VPN client but not with OpenVPN.

comment:10 Changed 8 years ago by ValdikSS

I've looked into AirVPN open-source client
https://github.com/AirVPN/airvpn-client
They have 2 advanced options: to disable all DNS on all interfaces except tun (called Force DNS) and to switch all DHCP adapters to static mode and revert back on disconnect (called Switch DHCP to Static).
https://airvpn.org/faq/software_advanced/

It seems that Avast SecureLine? suffers from exactly this problem too
https://www.avast.com/faq.php?article=AVKB233
I'm very sure this article has been created after my article, not before. And it's misleading since this fix doesn't work on Windows 10.

comment:11 Changed 8 years ago by ValdikSS

So I signed for AirVPN trial and their client also leaks DNS by default. They force DNS on the network interface with the same IP as DNS inside the tunnel and all the queries also go via network tunnel.

http://i.imgur.com/CrTpLfS.png

comment:12 Changed 8 years ago by ValdikSS

Ok so apparently VyprVPN made their own service which filters all outgoing traffic to port 53. This is done with C# library using WFP (Windows Filtering Platform) completely in userspace.

I see two way-outs:

  1. Write WFP filter which blocks all outgoing packets to port 53 and allows only packets that go inside the tunnel. In my opinion this is the best way to solve this issue. It is completely userspace, it stops blocking on OpenVPN process termination even if it was killed.
  2. Implement adding firewall rules into OpenVPN. Easy to do but would break Internet access if OpenVPN crashed or on sudden power loss because there's no way to add temporary rules to Windows firewall, only permanent.

I'm nighter a programmer nor a Windows guy, so it would be not easy to implement any of these for me. But if nobody, really nobody would pick this task, I'll do my best. There are some WFP examples which don't look very scary for me.

comment:13 Changed 8 years ago by debbie10t

@ValdikSS Thanks for your work

Perhaps, in the short term, we could add a W10-DNS-Howto using the WinFW with an example - I can do an example for W7

Last edited 8 years ago by debbie10t (previous) (diff)

comment:14 Changed 8 years ago by ValdikSS

@debbie10t, could you please test the following attachements (one is 32-bit and another is 64-bit but you can use 32-bit on 64-bit system too) on Windows 10? It works for me, I hope it will for you too.
This is a WFP user-space driver which:

  • rejects all packets from all interfaces to port 53
  • allows all packets from "TAP-Windows Adapter V9"

That rules works only while this program is running. If you close it or it crashes, you'll get the same firewall state as it was previously.

You can run it manually after VPN connection or you can make a script to use it on up/down in OpenVPN config. It should be run with administrator privileges (it doesn't escalate it automatically).
If it works for you, I'll think about how should I add this into OpenVPN.

Changed 8 years ago by ValdikSS

Attachment: testfw-d1.zip added

comment:15 Changed 8 years ago by debbie10t

I do not have access to W10 .. hopefully, somebody who does can test.

comment:16 Changed 8 years ago by ValdikSS

comment:17 Changed 8 years ago by debbie10t

@ValdikSS Great work :)

Following some users tests and feedback I will post links back to this [edit: Your ] solution.

I wonder how much this will piss off M$ et al ;)

Last edited 8 years ago by debbie10t (previous) (diff)

comment:18 in reply to:  16 Changed 8 years ago by Gert Döring

Replying to ValdikSS:

I wrote a plugin. Works good!
https://github.com/ValdikSS/openvpn-fix-dns-leak-plugin

This is tremendously great news - thanks a lot!

(I do not have a Win10 machine myself yet, but I'll find someone to test this - and I think we should bundle the plugin into the 2.4(-to-be) installers, so users can "just use this"... does the plugin build with MinGW or only MSVC? (Asking because the official installers are built on linux with MinGW)

comment:19 Changed 8 years ago by ValdikSS

I'm sure it won't compile with mingw right away but I'll look what can I do about this. Actually, I'd be very happy if it was built-in into OpenVPN. Not as a plugin, but as a standard function.

comment:20 Changed 8 years ago by Gert Döring

Hi ValdikSS,

we've discussed this topic at the Hackathon today, and we think this is the best alternative today - namely:

  • integrate the code into src/openvpn/win32.c
  • add an option ("block-outside-dns" or something more creative)
  • this option would enable this protection feature on Win32, and be pushable from the server
  • on other platforms that do not need this or do not have a capability to enable this, it would be a no-op or just print a warning, but not an error (so it can be always pushed)

would you be willing to port over your plugin into a patch for openvpn general? Patch for master, please :-) - I can see that we need to have this in 2.3.9 as well, but backporting "should" not be too complicated.

thanks

comment:21 Changed 8 years ago by ValdikSS

If anyone interested, I've made a patch for master which adds 'block-outside-dns' to the OpenVPN. You can get it here.

comment:22 Changed 8 years ago by Gert Döring

Patch has been integrated into master and release/2.3...

commit 38c8565810f892a41a2ea0d18a707676119f1af0
Author: ValdikSS <iam@…>
Date: Thu Dec 10 23:51:55 2015 +0300

Add Windows DNS Leak fix using WFP ('block-outside-dns')

... and released as part of 2.3.9.

For the record, put "setenv opt block-outside-dns" into your local configs to prevent fatal errors in case you're running on XP or non-windows - when pushing, just using "push block-outside-dns" is fine (as unknown/failing options on push only cause a warning anyway).

I think this one can be closed now, right?

Last edited 8 years ago by Gert Döring (previous) (diff)

comment:23 Changed 8 years ago by ValdikSS

Right.

comment:24 Changed 8 years ago by Gert Döring

Resolution: fixed
Status: assignedclosed

comment:25 Changed 7 years ago by ValdikSS

Windows 10 before Creators Update used to resolve DNS using all available adapters and IP addresses in parallel.
Now it still resolves addresses using all available adapters but in a round-robin way, beginning with random adapter.
This behaviour introduces significant delay when block-outside-dns is in use.
Fortunately, setting low metric for the TAP interface solves this issue, making Windows always pick with TAP adapter first.

I made a patch to lower interface metric when --block-outside-dns is in use. Hope it would be included in 2.4.2.
https://sourceforge.net/p/openvpn/mailman/message/35822231/

comment:26 Changed 7 years ago by ValdikSS

Patch is included in 2.4.2.

Note: See TracTickets for help on using tickets.