[SOLVED] Wireguard selective routing

Started by Nikotine, September 12, 2021, 05:00:12 PM

Previous topic - Next topic
September 12, 2021, 05:00:12 PM Last Edit: September 14, 2021, 01:33:35 PM by Nikotine
I'm following this guide (https://docs.opnsense.org/manual/how-tos/wireguard-selective-routing.html) to have only a few local hosts use a Mullvad remote Wireguard peer.
At the end of that guide, there are a few options to solve DNS leaks. I've chosen option 2, using a port forward  for DNS requests to the Mullvad DNS server.

The problem is that now Chrome is complaining about the connection not being private (NET::ERR_CERT_COMMON_NAME_INVALID) or Opnsense complaining about a DNS rebind attack...

EDIT: I'm sorry for the huge screenshots. They looked fine on my screen, but huge after upload to imgur and inserting them here...

Wireguard connection to server in Switzerland:


Wireguard gateway:


Firewall aliases (all_local_clients and local_hosts_remote_Mullvad).
I'm 10.25.9.10, the computer I'm typing this on.
Currently that alias is disabled, otherwise I can't reach this forum.


Firewall rules.
Second rule is to have all traffic from local_hosts_remote_Mullvad alias, not destined to local networks, to use the Mullvad gateway.


NAT outbound rule:


Then finally, to resolve the DNS leaks, NAT port forward of DNS request from hosts in local_hosts_remote_Mullvad alias to Mullvad's DNS server:


Things I've tried:
1. enabling Reflection for port forwards, Reflection for 1:1 and Automatic outbound NAT for Reflection. Didn't help.

2. enabling, disabling or using system default NAT reflection setting in the DNS port forward rule. No difference.






I'm just realizing that the error I get in Chrome is about the Let's Encrypt certificate I'm using locally, but it's only when I route the traffic over Wireguard...

What DNS servers do the relevant clients use otherwise?


So the port forward rule destination shouldn't be "this firewall", but instead the Cloudflare IPs or even "any"? That is, what you are trying to capture is the DNS request packets from the clients - if they are directly using Cloudflare rather than eg OPNsense (which is in turn forwarding to Cloudflare), then that is what the rule should be directed at.

Yes sorry, the clients use the firewall (unbound) as DNS server, who has DNS forwarding on, to Cloudflare.

But you're right, there's something wrong with this rule. Even if it would work, I wouldn't be able anymore to resolve local hostnames. I believe I should try to catch the DNS requests that are forwarded by unbound on the firewall to Cloudflare, to Mullvad instead, IF that request came from a client using Mullvad in the first place...
Not sure how to do that though. Packet tagging perhaps?

This was all very easy to do on Openwrt with the VPN policy routing plugin. It's a bit of a challenge in opnsense  ;)

Yeah, that sounds like some more work

So... it seems the problem has nothing to do with DNS, I have disable all DNS forwarding stuff for the moment.

The problem is a certificate error. Chrome tries to use my local Let's Encrypt certificate whenever I'm trying to access a website, mullvad.net in this case...



This blows my mind, any tips?

Ok, I disabled https for the GUI for a moment, to get that variable out of the loop.

Then I started googling and found that you, Greelan, are the author of the guide  :)
I then found your link to this Imgur post: https://imgur.com/gallery/JBf2RF6.
Going through the screenshots in there, I found a mistake in my setup: when setting up the gateway, I hadn't used the fictive gateway IP from the local peer setup in Wireguard, but the Wireguard local tunnel address, entirely my mistake.
After having changed that, the Gateway went offline though, so I changed the monitor IP to 1.1.1.1 instead of the endpoint address.
Not sure why the latter isn't working.



My selected hosts are now using the Wireguard connection!
I've also re-enabled https for GUI and that didn't break it  :)
Now let's see how to get any DNS leaks fixed.

September 13, 2021, 11:41:22 PM #9 Last Edit: September 13, 2021, 11:45:12 PM by Greelan
Good you found the problem.

For the monitor IP for Mullvad, do a traceroute while connected to the VPN. The first hop after OPNsense will be the tunnel IP at Mullvad's end, that you can use as the monitor IP


September 14, 2021, 12:34:39 PM #11 Last Edit: September 14, 2021, 12:37:15 PM by Nikotine
With selective VPN routing now working, Mullvad keeps complaining about DNS leaks:



I'm trying to implement option 2 of "dealing with DNS leaks" of the guide (https://docs.opnsense.org/manual/how-tos/wireguard-selective-routing.html#dealing-with-dns-leaks).
All traffic coming from the hosts I want to use the Mullvad peer, is tagged with the first firewall rule.
I had to disable quick (red circle), otherwise it wouldn't process further rules.
The original rule to route traffic to the Wireguard gateway has been adjusted to match that tag.



This works, traffic for my selected hosts is still tunnelled via the Wireguard peer.
DNS leak exists.
Then I have added a port forward, to redirect DNS request, with the same packet tag, to Mullvad's DNS.



But the DNS leak doesn't go away.

Unfortunately you can't setup a gateway in a port forward rule.
So am I correct that traffic will be tagged by my first firewall rule, then be port forwarded if the tagged traffic is DNS traffic, and then routed to the correct gateway by the second firewall rule?

September 14, 2021, 01:33:19 PM #12 Last Edit: September 14, 2021, 01:38:10 PM by Nikotine
I reverted back to the one firewall rule and removed the packet tagging.
Then I amended the port forward to forward ALL DNS traffic from the Mullvad clients to Mullvad's DNS server.
That works, I get all greens on Mullvad's check page, but local hostnames don't get resolved anymore obviously, which is only a small price to pay.

I suspect that when Unbound forwards a DNS request, the packet tag is removed.

September 14, 2021, 01:34:36 PM #13 Last Edit: September 14, 2021, 01:37:59 PM by Greelan
Not sure that first rule will do anything. Being non-quick, it will only apply if the next rule doesn't.

Also not sure if the port forward will achieve anything given the relevant clients are using the firewall as their DNS server, not Cloudflare.

What would work is simply a port forward that says any DNS requests coming into the firewall from the relevant clients is forwarded to Mullvad DNS.

However this will break local DNS resolution. 

The solution you are really after is to only change the destination on egress - so if a DNS request is resolved locally, there is nothing to do, and only if OPNsense forwards it to Cloudflare is the destination then changed. But at that point the request is coming from the firewall, not the clients, and so is not using the tunnel.

Edit: snap!

September 14, 2021, 01:36:04 PM #14 Last Edit: September 14, 2021, 01:43:36 PM by Nikotine
We were cross-posting  :)
My findings are the same... Thanks for the brainstorm anyway!

About this:
QuoteNot sure that first rule will do anything. Being non-quick, it will only apply if the next rule doesn't.
It was working, that rule added a local tag to packets, which was then picked up by the second rule to route that traffic to the gateway.
Just the NAT port forward didn't seem to pick up that tagged traffic, probably because the DNS traffic I tried to capture now came from the firewall and the tag had been removed by Unbound.