Secondary Local DNS server for Wireguard

Hi everyone,

I have reached to a point when I can't even phrase my question properly. I have a WireGuard server running in a separate firewall zone, controlling accesses pretty well with the firewall and "Allowed IPs" attribute of the Peer.

Now my next plan is to hook up a few linux machines (for ex. Raspberries) across the family, and connect all to my VPN server. This way I could easily SSH to them, and maintain some applications.

Instead of remembering IP addresses, it would be so awesome to have one more local domain , let's say /wg/ and access all of them combined with the Peer's name. For example ssh pi@parents-pi.wg.

So far I tried to configure an entry in the Hostnames, but after saving, something goes wrong, and the peer is not even reaching the /lan/ devices. I couldn't see anything from the logs.

Does someone know any good idea to achieve this?

Since I'm using AdGuardHome on a different device, one workaround is to create a custom filtering rule, hardcoding the IP address and the desired name.
Still, I'm very interested how this could be done properly, having every local domain related service within the router/OpenWrt

You don't need another local domain for this, you can use the same lan domain and have them resolve to hosts on another network. To illustrate how this can work, I will contrive some example networks as follows:

  • Network berry.lan with prefix fd82:272a:3c46:0100::/56
    • Router router.berry.lan with address fd82:272a:3c46:0100::1
    • Server rasp.berry.lan with address fd82:272a:3c46:0100::2
  • Network nut.lan with prefix fd82:272a:3c46:0200::/56
    • Router router.nut.lan with address fd82:272a:3c46:0200::1
    • Desktop wal.nut.lan with address fd82:272a:3c46:0200::3

The two routers have a site-to-site Wireguard tunnel correctly configured. The allowed IPs for each peer would be the network prefix for that peer. The routers also advertise their respective prefixes on their networks so the hosts within those networks get the same prefix. For example, configure router.berry.lan with /etc/config/network:

config globals 'globals'
    option ula_prefix 'fd82:272a:3c46:0100::/56'

config wireguard_vpn
    option description 'nut.lan'
    list allowed_ips 'fd82:272a:3c46:0200::/56'
    option route_allowed_ips '1'
    ...

router.nut.lan should be set up the same way.

At this point, wal.nut.lan can reach rasp.berry.lan by IP address. This will involve tunneling between the two routers. wal.nut.lan will choose the correct source address such that replies from rasp.berry.lan will reach wal.nut.lan back through the same Wireguard tunnel.

Of course, typing IPv6 addresses is a chore, so we set up DNS so we can reach these hosts by name. Fortunately, OpenWrt runs dnsmasq out-of-the-box, and it can be configured to use DNS forwarding. This allows you to resolve names in other networks through the Wireguard tunnel, not just the local network.

For example, configure router.nut.lan with /etc/config/dhcp:

config dnsmasq
    ...
    option local '/nut.lan/'
    option domain 'nut.lan'
    option localservice '0'
    list rebind_domain 'lan'
    list server '/berry.lan/fd82:272a:3c46:0100::1'

router.berry.lan should be set up the same way.

Let's see what happens when you ssh pi@rasp.berry.lan from your desktop wal.nut.lan:

  1. Desktop attempts to resolve rasp.berry.lan. Because OpenWrt advertises itself as the DNS server, wal.nut.lan sends the DNS query for rasp.berry.lan to router.nut.lan.
  2. Dnsmasq on router.nut.lan will forward the query to fd82:272a:3c46:0100::1. This will be tunneled to router.berry.lan.
  3. Dnsmasq on router.berry.lan responds to the query, which will be tunneled back to router.nut.lan.
  4. Dnsmasq on router.nut.lan replies to wal.nut.lan with the response from router.berry.lan.
  5. wal.nut.lan connects to rasp.berry.lan using the provided IP address, which will also be tunneled.

How dnsmasq responds to the rasp.berry.lan is also configurable. You can directly set the AAAA record in dnsmasq or use static DHCP leases.

4 Likes

Nice write up :+1:

I set this up a long time ago on another firmware with IPv4 but basically you tell DNSMasq to resolve queries for a certain domain (the other side) using a certain server (the other side DNS server).

One question does DNSMasq always listen on all interfaces?

I can remember that I had to specifically tell DNSMasq to listen on the vpn (tun) interface.

By default, dnsmasq binds to the wildcard address unless you specify bind-interfaces (according to the dnsmasq man page). So yes, it effectively listens on all interfaces. Perhaps the behavior was different in previous dnsmasq versions.

I do remember that I needed to add these lines

option localservice '0'
list rebind_domain 'lan'

so the remote dnsmasq replies (which have private IP addresses) don't get rejected by the local dnsmasq instance.

1 Like

Very nice explanation. Thank you for that. It makes me get one more OpenWrt router for this just to try it out.

What would happen if you don't have access to the router on the other side, and you have to solve every DNS related thing on the main router?

If I understand your question correctly, you're asking if you can still use this kind of solution if the other-side router isn't running OpenWrt?

The dnsmasq instances described in my example do not need to run on the same physical machine as the router. You can deploy dnsmasq on a Raspberry Pi (that you're already using) and configure the router to use that for DNS. Even the most bare-bones crap stock router firmware usually have a way to configure DNS. After all, this is how Pi-hole works, and not all Pi-hole users are running OpenWrt.

Or you can forgo the extra machine and have that other router use the main router as the DNS for everything. Meaning that instead of this:

other router -> ISP (or some other) DNS server

You have this:

other router -> main router -> ISP (or some other) DNS server

The downside is increased DNS latency since it has to make that extra hop through the Wireguard tunnel for every request. But if your clients cache DNS responses it might be okay.

1 Like

If I understand your question correctly, you're asking if you can still use this kind of solution if the other-side router isn't running OpenWrt?

Yes, that's my question. The solution you proposed is great for households, but it isn't as generic as I imagined, because I already have a few other devices that are much limited than a Raspberry, and they would move between more locations.

What if you have no other access on an end device other than to start/stop a VPN connection, and you are also moving the device, not knowing the network it will be connected to. In these cases basically the WireGuard server's side is the only stable element. I hope I cleared up myself a bit more.

If I'm reading this correctly, you have end devices that use a point-to-site Wireguard tunnel. And you'd like those devices to be able to resolve the names of servers accessible through that tunnel.

In that case, you should be able to set the DNS for the Wireguard interface on those end devices. Set the DNS to the IP address of the main router. Obviously this IP address needs to be an allowed IP for the Wireguard peer.

Then the main router becomes the upstream DNS for that Wireguard client. Assuming that DNS is set up correctly there, then the main router can respond to queries for your Raspberry Pis. Of course, DNS can be on some other machine, just use the IP address for that instead.

All of this should work no matter what network the end device is connected to.

1 Like

you have end devices that use a point-to-site Wireguard tunnel

That's right. I have exactly the same setup as you described. My AdGuardHome running on the separate machine is already added as DNS in the peer's config. With Allowed IPs and firewall access, I can access my LAN network from the peer using the local domain.

The problem is the other way around, I cannot address the peer from the local network with a domain. One solution I have found so far, is to add some rules in the AdGuardHome, to "hard-code" names to specific IP addresses. It is doing the job, but I would solve it the proper way.

Well that is described above :slight_smile:

Basically you add an extra DNS server to DNSMasq (and Adguard probably will also support this).
But this DNS server is only used for a specific domain, in this case the domain of the otherside of the tunnel.
server=/otherside/ip-address-of-otherside-dns-server

So if you you want to resolve client1.otherside there will be a query to the DNS server of the other side of course that DNS server has know the ip address of client1 :slight_smile:

Queries for other domains will just use your regular DNS server

The description above describes a screnario, when it's possible to manage a DNS server on the "other" (or call it remote) location. This is not possible if you connect with your device to a public wi-fi for example.

I see however, that multiple dnsmasq instances can be run on OpenWrt. That would be perfect: the original would listen on lan, and covering all the existing local devices, and one more for wireguards devices. This way no configuration is needed on the "other" side, everything is handled by my main router. Is this really an option?

Just to ensure we're on the same page, here's the mental picture I have:

main-router <--[ Wireguard tunnel ]--> end-device

You are on the main-router's network and you want to connect to the end-device by name, no matter what network the end-device is. Meaning we cannot rely on end-device's network to provide proper name resolution on end-device's behalf.

Let's say that end-device has IP address fd82:272a:3c46:0400::4, which you specify in the end-device's IP Wireguard configuration. Further, main-router has correctly set up end-device as a peer, with allowed IP set to fd82:272a:3c46:0400::4/128.

Note that the IP you choose should be on a different network prefix than main-router's prefix. So let's say that main-router's prefix is fd82:272a:3c46:0300::/56. Because fd82:272a:3c46:0400::4 does not share the same 56-bit prefix, packets destined for end-device sent by hosts on main-router's network will be sent to main-router. Then, main-router tunnels those packets to end-device.

Assuming all that works, add the corresponding AAAA record in main-router's DNS:

uci add_list dhcp.@dnsmasq[0].address="/end-device.main.lan/fd82:272a:3c46:0400::4"
uci commit dhcp
service dnsmasq restart

Replace main.lan with whatever domain your main-router's network is using.

Now, main-router DNS is the one responsible for all queries to end-device. Hosts on main-router's network can now resolve end-device. Yes, you have to manually set this up, but since you already had to manually set up the Wireguard tunnel to end-device in the first place, this is not a concern.

Hosts on other networks would need to have their router's DNS forward queries to end-device to main-router's DNS as I've already described earlier in my first reply or my second reply to you, depending on how configurable those other routers are.

Hi Elbert,

Everything is exactly how you said. Well, I was working with IPv4, but same principles, WireGuard running on a different subnet, peers having 192.168.2.x/32 IP address.

This will be new to me, but I will try out adding the AAAA records to the DNS, and come back to you with my results.

Thank you very much your support, you are a really good explainer.

Is it possible to have multiple dnsmasq instances, and have completely different domain on the wg0 interface?

Yes, it's possible, although I've never tried that. You might be able use this example in the wiki to get started. But I would try getting this whole thing working on a single dnsmasq instance first.

Or even better, run another dnsmasq instance on one of your Raspberry Pis so you don't end up trashing your main router's dnsmasq configuration if it goes awry. Then set up a DNS forwarding on the main router.

For example, let's say you want end-device.wg.lan to resolve to your end-device at the other side of the Wireguard tunnel. Set up a Raspberry Pi with a static DHCP lease (so it always gets the same IP address) and set up dnsmasq on it with the proper A or AAAA record for end-device.wg.lan. Then on the main router, set dnsmasq to forward all queries for wg.lan to that Raspberry Pi.

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