Community discussions

MUM Europe 2020
 
fflo
just joined
Topic Author
Posts: 16
Joined: Wed Jan 02, 2019 7:59 am

NordVPN IKEv2 EAP VPN tunnel: DNS leak

Mon Jan 06, 2020 4:25 am

Since firmware version v6.45, Mikrotik routers support dialing out an IKEv2 EAP VPN tunnel.
For configuration, it's necessary to create a new "/ip ipsec mode-config" with responder=no that will request configuration parameters from the VPN provider's server.

Example configuration: https://nordvpn.com/de/tutorials/mikrotik/ikev2/

On connect of the VPN tunnel, the VPN provider's DNS servers are automatically added to the Mikrotik DNS "Dynamic Servers" servers list.

As only selected packets ("Src. address list" or "Connection Mark") are routed and encrypted to the VPN tunnel, this results in the effect, that the Mikrotik router occasionally leaks DNS information to these DNS "Dynamic Servers" via unencrypted default routing path.

Is it possible to block the DNS configuration parameters for an IKEv2 EAP VPN tunnel setup with Mikrotik?

Hotfix I am using to mitigate this issue at the moment (for NordVPN using "Connection Mark" mode):
/ip firewall address-list
add address=103.86.96.100 list=NORDVPN-DNS
add address=103.86.99.100 list=NORDVPN-DNS
/ip firewall mangle
add action=mark-connection chain=output comment="mangle output to WAN AL:NORDVPN-DNS via NORDVPN" \
    connection-state=new dst-address-list=NORDVPN-DNS new-connection-mark=NORDVPN out-interface-list=WAN \
    passthrough=no
 
fflo
just joined
Topic Author
Posts: 16
Joined: Wed Jan 02, 2019 7:59 am

Re: NordVPN IKEv2 EAP VPN tunnel: DNS leak

Sat Jan 11, 2020 5:25 pm

@Mikrotik: Is it possible to block the DNS configuration parameters for an IKEv2 EAP VPN tunnel setup?
How does RouterOS select which DNS server is used from the list of available static and dynamic DNS servers?
 
611
newbie
Posts: 27
Joined: Wed Oct 17, 2018 10:12 am

Re: NordVPN IKEv2 EAP VPN tunnel: DNS leak

Sun Jan 12, 2020 6:33 pm

I'm not affiliated with MT :)

"DNS leak" in VPN scenario usually denotes "resolving names through DNS server other than VPN provider's".

If you'll route traffic from a "client group" (identified with network addresses, ports, L7 patterns used, whatever) to a VPN, but don't use VPN provider's DNS servers to resolve names for this client group (you're asking for it when you want to disable adding DNS servers received with IPsec mode-config to ROS DNS client), it would create a genuine DNS leak - the traffic goes though VPN, but names are resolved through your ISP's (or Google's/other) DNS servers.

Your "leak" is different, and your "hotfix" is just a required part of configuration for proper VPN use. (You really shouldn't expect a system to do this configuration for you.)
But this would work properly only if you have no other DNS servers in ROS DNS configuration. Otherwise you'll still get a DNS leak - ROS would also query DNS servers other than your VPN provider's.

DNS server in ROS is very basic. Merely a responder on top of built-in resolver (client). It doesn't have advanced features like source-based query forwarding and separate caches for different client groups. Without these features you can't use one DNS server to serve two or more client groups that have to be separated (like "normal clients" and "VPN clients").

So if you want two client groups to be separated, you shouldn't use ROS DNS server for at least one group.

Luckily, DNS protocol is generally server-agnostic (you may NAT or otherwise redirect a query to another server and in most cases nobody would notice), so the solution would be dst-NAT'ting DNS queries with proper selectors (the same as you're using to distinguish your client groups - network addresses, ports, L7 patterns used, whatever).
As you'll do it in prerouting chain, you'll effectively bypass ROS DNS server (as a side effect your local static DNS entries won't resolve).
/ip firewall nat add chain=dstnat action=dst-nat protocol=udp dst-port=53 <your "VPN clients" selectors> to-addresses=<right address>

Another problem that currently you can't disable adding DNS servers received with IPsec mode-config to ROS DNS client. It was discussed here since at least 2015, but I don't know if the feature was ever requested from MT (and, if it was requested, will it be ever added).

To make the matter worse, you can't dst-NAT in output chain, so you can't just redirect queries made to VPN provider's DNS servers back to your ISP's DNS servers.
There's a solution that is used to emulate cDNS (conditional DNS server selection - query domain-a from DNS-a, domain-b from DNS-b, etc.) in ROS DNS client, but it may not worth the comlexity added (and some users may find it quite mind-blowing :)) - as you can only dst-NAT in input and prerouting chains, you need to somehow get outbound packets from DNS client into these chains, and it could be done with a tunnel looped back, with corresponding connection-marks, some extra NAT and routing (original cDNS implementation courtesy of @Sob, based on similar config by @sindy):
# Make a (bridge) interface for loopback tunnels, and set an local address to it.
/interface bridge add name=bridge-loopback protocol-mode=none
/ip address add address=127.0.0.2 interface=bridge-loopback network=127.0.0.2
# Make two IPIP tunnels pointing at each other. Addresses on them are not required.
# Since some 6.4x version it's required to have allow-fast-path=no on at least one of these tunnels, or the packets won't pass through
/interface ipip add local-address=127.0.0.2 name=ip2t-loopback-in remote-address=127.0.0.1
/interface ipip add local-address=127.0.0.1 name=ip2t-loopback-out remote-address=127.0.0.2 allow-fast-path=no

# Step 0: DNS client sends query to a wrong server.

# Step 1: Outbound queries from DNS client to wrong server are routed to "out" tunnel with routing mark. In cDNS scenario level7 condition goes here.
/ip firewall mangle add chain=output action=mark-routing protocol=udp dst-port=53 dst-address=<wrong address> new-routing-mark=rm-loopback
/ip route add distance=1 gateway=ip2t-loopback-out routing-mark=rm-loopback

# Step 2: Queries src-NATted as they go out to the "out" tunnel to some address not used elsewhere, to recognize replies when they'll come back. Here we may use more addresses with corresponding conditions (useful in cDNS scenario if you have more than one conditional server). Routing to this subnet is added to get replies back to "in" tunnel. 
/ip firewall nat add chain=srcnat action=src-nat protocol=udp dst-port=53 out-interface=ip2t-loopback-out to-addresses=10.53.0.1
/ip route add distance=1 dst-address=10.53.0.0/16 gateway=ip2t-loopback-in

# Step 3: Queries coming in from "in" tunnel are dst-NATted as required (all the BS is for this line!). In cDNS scenario with more than one conditional server we'll add src-address condition with address used in #2 and corresponding to-addresses.
/ip firewall nat add chain=dstnat action=dst-nat protocol=udp dst-port=53 in-interface=ip2t-loopback-in to-addresses=<right address>

# Step 4: Source address in queries changed once again to proper one for the outbound interface as they are sent out.
/ip firewall nat add chain=srcnat action=masquerade protocol=udp dst-port=53 out-interface=<proper outbound interface> src-address=10.53.0.0/16

# Step 5: Replies coming in and their dst address is getting NATted (back to 10.53.0.1) per #4.
# Step 6: Replies (now to 10.53.0.1) are routed to "in" tunnel per routing in #2.
# Step 7: Src address in replies NAtted (back to <wrong address>) as they go out to the "in" tunnel per #3.
# Step 8: Dst address in replies NAtted (back to ROS address) as they come in from "out" tunnel per #1.

# Step 9: DNS client receive replies that appear to be from <wrong address>, but actually they're from <right address>.

If you'll use both kludges, your VPN clients will not leak DNS queries as they will be always forwarded to VPN provider's DNS, and your ROS DNS client will work normally, never resolving anything through VPN provider's DNS (even though it will have these servers in its list).
 
fflo
just joined
Topic Author
Posts: 16
Joined: Wed Jan 02, 2019 7:59 am

Re: NordVPN IKEv2 EAP VPN tunnel: DNS leak

Mon Jan 13, 2020 6:21 am

"DNS leak" in VPN scenario usually denotes "resolving names through DNS server other than VPN provider's".

If you'll route traffic from a "client group" (identified with network addresses, ports, L7 patterns used, whatever) to a VPN, but don't use VPN provider's DNS servers to resolve names for this client group (you're asking for it when you want to disable adding DNS servers received with IPsec mode-config to ROS DNS client), it would create a genuine DNS leak - the traffic goes though VPN, but names are resolved through your ISP's (or Google's/other) DNS servers.

Your "leak" is different, and your "hotfix" is just a required part of configuration for proper VPN use. (You really shouldn't expect a system to do this configuration for you.)
But this would work properly only if you have no other DNS servers in ROS DNS configuration. Otherwise you'll still get a DNS leak - ROS would also query DNS servers other than your VPN provider's.
The point is that the Mikrotik tutorial and the NordVPN tutorial are both missing this information: That's why my expectation is that the VPN tunnel configuration does not add any dynamic DNS servers to the DNS configuration without permission to pull and add this information dynamically.

There should be a way to control if dynamic mode-configuration from the VPN provider is allowed to be imported into the running ROS-configuration; like that's the case for all other dynamic outbound connection types on MT-equipment.
DNS server in ROS is very basic. Merely a responder on top of built-in resolver (client). It doesn't have advanced features like source-based query forwarding and separate caches for different client groups. Without these features you can't use one DNS server to serve two or more client groups that have to be separated (like "normal clients" and "VPN clients").
To make things even worse it seems that ROS is picking the decision which DNS server to pull by random. Or is there another algorithm running in the background?
So if you want two client groups to be separated, you shouldn't use ROS DNS server for at least one group.
Yes, I know about this limitation.
Luckily, DNS protocol is generally server-agnostic (you may NAT or otherwise redirect a query to another server and in most cases nobody would notice), so the solution would be dst-NAT'ting DNS queries with proper selectors (the same as you're using to distinguish your client groups - network addresses, ports, L7 patterns used, whatever).
As you'll do it in prerouting chain, you'll effectively bypass ROS DNS server (as a side effect your local static DNS entries won't resolve).
/ip firewall nat add chain=dstnat action=dst-nat protocol=udp dst-port=53 <your "VPN clients" selectors> to-addresses=<right address>
If possible, I don't like to redirect any outbound DNS information to one specific DNS server. It creates a single point of failure and does not respect individual DNS configuration preferences.
Another problem that currently you can't disable adding DNS servers received with IPsec mode-config to ROS DNS client. It was discussed here since at least 2015, but I don't know if the feature was ever requested from MT (and, if it was requested, will it be ever added).
Actually that's the problem which has to be resolved, FIRST.
ROS should not import dynamic mode-config information by default; or at least it must be possible to block this information.
To make the matter worse, you can't dst-NAT in output chain, so you can't just redirect queries made to VPN provider's DNS servers back to your ISP's DNS servers.
There's a solution that is used to emulate cDNS (conditional DNS server selection - query domain-a from DNS-a, domain-b from DNS-b, etc.) in ROS DNS client, but it may not worth the comlexity added (and some users may find it quite mind-blowing :)) - as you can only dst-NAT in input and prerouting chains, you need to somehow get outbound packets from DNS client into these chains, and it could be done with a tunnel looped back, with corresponding connection-marks, some extra NAT and routing (original cDNS implementation courtesy of @Sob, based on similar config by @sindy):
# Make a (bridge) interface for loopback tunnels, and set an local address to it.
/interface bridge add name=bridge-loopback protocol-mode=none
/ip address add address=127.0.0.2 interface=bridge-loopback network=127.0.0.2
# Make two IPIP tunnels pointing at each other. Addresses on them are not required.
# Since some 6.4x version it's required to have allow-fast-path=no on at least one of these tunnels, or the packets won't pass through
/interface ipip add local-address=127.0.0.2 name=ip2t-loopback-in remote-address=127.0.0.1
/interface ipip add local-address=127.0.0.1 name=ip2t-loopback-out remote-address=127.0.0.2 allow-fast-path=no

# Step 0: DNS client sends query to a wrong server.

# Step 1: Outbound queries from DNS client to wrong server are routed to "out" tunnel with routing mark. In cDNS scenario level7 condition goes here.
/ip firewall mangle add chain=output action=mark-routing protocol=udp dst-port=53 dst-address=<wrong address> new-routing-mark=rm-loopback
/ip route add distance=1 gateway=ip2t-loopback-out routing-mark=rm-loopback

# Step 2: Queries src-NATted as they go out to the "out" tunnel to some address not used elsewhere, to recognize replies when they'll come back. Here we may use more addresses with corresponding conditions (useful in cDNS scenario if you have more than one conditional server). Routing to this subnet is added to get replies back to "in" tunnel. 
/ip firewall nat add chain=srcnat action=src-nat protocol=udp dst-port=53 out-interface=ip2t-loopback-out to-addresses=10.53.0.1
/ip route add distance=1 dst-address=10.53.0.0/16 gateway=ip2t-loopback-in

# Step 3: Queries coming in from "in" tunnel are dst-NATted as required (all the BS is for this line!). In cDNS scenario with more than one conditional server we'll add src-address condition with address used in #2 and corresponding to-addresses.
/ip firewall nat add chain=dstnat action=dst-nat protocol=udp dst-port=53 in-interface=ip2t-loopback-in to-addresses=<right address>

# Step 4: Source address in queries changed once again to proper one for the outbound interface as they are sent out.
/ip firewall nat add chain=srcnat action=masquerade protocol=udp dst-port=53 out-interface=<proper outbound interface> src-address=10.53.0.0/16

# Step 5: Replies coming in and their dst address is getting NATted (back to 10.53.0.1) per #4.
# Step 6: Replies (now to 10.53.0.1) are routed to "in" tunnel per routing in #2.
# Step 7: Src address in replies NAtted (back to <wrong address>) as they go out to the "in" tunnel per #3.
# Step 8: Dst address in replies NAtted (back to ROS address) as they come in from "out" tunnel per #1.

# Step 9: DNS client receive replies that appear to be from <wrong address>, but actually they're from <right address>.
Thanks for sharing this awesome documented "awful hack".

Currently, I am debugging another way to resolve the issue:
Reject all outgoing DNS packets by default, except those on a white access-list.
If you'll use both kludges, your VPN clients will not leak DNS queries as they will be always forwarded to VPN provider's DNS, and your ROS DNS client will work normally, never resolving anything through VPN provider's DNS (even though it will have these servers in its list).
Yes, actually this should be the case expected. Thanks for sharing your thoughts!
 
611
newbie
Posts: 27
Joined: Wed Oct 17, 2018 10:12 am

Re: NordVPN IKEv2 EAP VPN tunnel: DNS leak

Mon Jan 13, 2020 8:52 am

The point is that the Mikrotik tutorial and the NordVPN tutorial are both missing this information: That's why my expectation is that the VPN tunnel configuration does not add any dynamic DNS servers to the DNS configuration without permission to pull and add this information dynamically.
There's a lot of quite unexpected/undocumented things in current IPsec implementation. And they may SUDDENLY change in any given future release, breaking your config.

For example, in one of the recent releases MT have changed the way the policies are dynamically modified (and matched?). I have a host behind CGNAT (my external IP is static and exclusive to me, but I only have an internal IP on my router, with 1:1 port mapping from/to external IP done by ISP) and IPsec to it worked without NAT (and without any problems) with a manually crafted policy (internal IP in SA) prior to 6.45.1, but this config ceased to work since 6.45.1 as SA addresses in my policy is getting overwritten when connection is established.

There should be a way to control if dynamic mode-configuration from the VPN provider is allowed to be imported into the running ROS-configuration; like that's the case for all other dynamic outbound connection types on MT-equipment.
The queue of the things MT should have done (and shouln't have done too) is so looong :)
Still you might want to bump them regarding this issue.

To make things even worse it seems that ROS is picking the decision which DNS server to pull by random. Or is there another algorithm running in the background?
I bet ROS just passes DNS server list to underlying Linux stuff, so MT won't be able to say how it works exactly.
I've observed the same thing with RP Filter - MT was able to reproduce the bug, but just shrugged as they don't know what's under the hood - "we'll look for Linux patches".

/ip firewall nat add chain=dstnat action=dst-nat protocol=udp dst-port=53 <your "VPN clients" selectors> to-addresses=<right address>
If possible, I don't like to redirect any outbound DNS information to one specific DNS server. It creates a single point of failure and does not respect individual DNS configuration preferences.
Your selector may also include destination addresses. You may hand some bogus DNS addresses to your "VPN clients" group with a separate DHCP network (sic!), then catch and NAT these addresses to the right servers in the aforementioned rule:
/ip dhcp-server network add address=<your "VPN clients" as a "subnet"> dns-server=<speciffic DNS for them> gateway=<or even specific GW for them> netmask=<netmask of your LAN>
To be true, I've never tried this for subnet address=, but it works OK if address= specifies a host - host on the same actual LAN as "normal clients" receives its special GW and DNS (so at least address matching in DHCP server networks is working as expected).

And if you have a MT (or other router) to spare, you may hand a different default gateway to your "VPN clients" group and completely separate the groups as they'll be using different routers to access internet. This way you may truly enjoy automatic DNS server pull (and DNS cache, and completely separate config):)

Currently, I am debugging another way to resolve the issue:
Reject all outgoing DNS packets by default, except those on a white access-list.
That will cause a delay, unless you're actually rejecting (not dropping) the queries and DNS client understands rejects (and tries the next sever immediately).
Haven't tried this as I'm not sure of the latter. Please share your results.

Thanks for sharing your thoughts!
You're welcome!

Who is online

Users browsing this forum: Bing [Bot], Buster2, jmdg11 and 89 guests