DNS: Starlink + Mullvad filtering = Problems

I'm trying to set up a BPI-R3 to use Mullvad VPN over WireGuard. I have previously done this on a couple of GL.iNet travel routers and it worked like a charm.

I followed the Mullvad guide to set it up, and also compared against the config in one of my travel routers, but when I was done, I couldn't get name resolution for a computer connected to the router. I could get name resolution from the router itself (i.e. "ping mullvad.net" would resolve and work).

The main difference I can see between the devices is that my travel router is configured with a static IP because I have only been using it as a VPN behind a primary router, while the BPI-R3 is connected directly to Starlink's "ethernet adapter", so I get a DHCP-provided IPv4 address from their CG-NAT, which has a gateway address of 100.64.0.1. And of course, Mullvad VPN's content-blocking DNS servers are all 100.64.0.*.

Mullvad's e-mail support thinks this conflict of addresses is probably the issue. I was only getting DNS from the router itself via Starlink's default DNS entries and the Mullvad DNS was simply not working at all.

Prior to e-mailing Mullvad, I had already tried undoing the DNS sections of their guide (which says to enter the DNS server address in both "Use custom DNS servers" and "DHCP-Options" on the LAN interface) and instead putting it in "Use custom DNS servers" on the WireGuard interface, because I don't know enough to know why this might be stupid (I assume it is).

But that actually worked, in terms of giving me DNS from both the router and the connected laptop, and passing Mullvad's DNS leak test, but it didn't appear to be blocking any ads from sites confirmed to be in their blocklists. Mullvad's support says this probably means that the filtering DNS address (100.64.0.7 for ads/track/mal) wasn't being received or recognized by Mullvad's WireGuard gateway and it was just falling back on the default (10.64.0.1) which doesn't do any filtering.

So my questions:

  1. Why does my "sort-of working" approach with the custom DNS in the WireGuard interface successfully give me tunnelled DNS (the leak test passes) but fail to give me content-blocking (i.e. Mullvad seems to be falling back on their default instead of using the specified filtering address)?

  2. Does that conflict of addresses (Starlink gateway vs. Mullvad DNS) make sense as the root of the initial problem (no DNS to clients when custom DNS specified on the LAN interface per the guide)?

  3. If yes, is there any simple way of fixing it while still using the Mullvad filtering DNS? I don't understand how all of the various places to specify custom DNS servers interact with each other.

  4. If yes to #2 and no to #3, what's the next best alternative to get comparably filtered+private DNS via the router? AdGuard Home seems pretty complicated for my level (dealing with alternate storage, etc). Maybe DNS over TLS using NextDNS?

Use policy routing to make sure the lan always forwards into the vpn. This should make that connection unaffected by conflicting addresses on wan. Use DHCP option 6 to advertise the Mullvad server to LAN devices (instead of the router, since it still has the quagmire of conflicting IPs for its internal DNS).

Note that endpoint clients are not obligated to use the advertised DNS, and many don't, so this sort of simple DNS based blocking does not always work.

By following the Mullvad guide, I end up with the "lan" zone forwarding only to the VPN zone (Network>Firewall in LuCI). And the guide also uses DHCP option 6 on the LAN interface to advertise the Mullvad DNS.

That's the configuration that was not working to start with. No name resolution on LAN clients, even though "resolvectl" on a connected laptop was showing the Mullvad DNS server. It seems like somehow the conflict was still occurring (or else there's a completely different and coincidental problem).

I'm not too worried about the DNS filtering being bulletproof (if I get it working at all), but what are the options for improving it?

By default, there is only one routing table, and there is a routing conflict within that table when trying to reach an end destination at Mullvad (through the VPN) which overlaps your outgoing "public" IP on Starlink (through the WAN).

One solution would be to add an extra table and attach it to the LAN, so any Internet request from the LAN will always go out by VPN regardless of the destination IP. That table would not contain Starlink routes.

Could the following work?

The route to the WAN subnet is usually a /24 route so maybe we could get away with adding:
100.x.x.x is the DNS server
ip route add 100.x.x.x/32 dev <wg_interface>

As /32 takes precedence over /24

1 Like

Yes that should work as long as the IP doesn't exactly match one needed for Starlink.

1 Like

I will try @egc's suggestion. My actual Starlink IPv4 address seems to typically end up being something like 100.67.x.x despite the 100.64.0.1 gateway, so it seems like a reasonably safe bet that the exact address won't collide.

I'm still considering just abandoning Mullvad's filtering and using either Adblock or Adblock-Fast. Any comments comparing the two (differences, pros and cons) would be very welcome.

OK, @egc's approach works.

I made it persistent from LuCI -> Network -> Routing -> Static IPv4 Routes -> Add :

Interface: <wg_interface>
Route type: unicast
Target: 100.64.0.7/32 (the DNS address)

And left everything else alone. Do I have to worry about any of the other default values?

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.