Creating a "local" VPN network
Now that I have a point-to-point Wireguard connection between my desktop and my VPS, I want to create a small network of devices that can communicate with each other over the VPN. This will look like a “local” network, but it is actually a virtual network overlaid on the internet and my home network.
With such a network I should be able to, for example, connect to my home desktop from my laptop when I am away from home (without needing to open ports on my home router).
I am aiming to create a spoke-and-hub network where the VPS is the hub and my home devices are the spokes. Something like this:
flowchart LR;
subgraph home
A[Desktop<br>10.20.10.2]
B[NAS<br>10.20.10.3]
end
subgraph roaming
C[Laptop<br>10.20.10.4]
end
V[Wireguard Server<br>10.20.10.1]
V <---> |tunneled| A
V <---> |tunneled| B
V <---> |tunneled| C
subgraph internet
I[...<br>0.0.0.0/32]
end
internet <---> |untunneled| V
Client & Server Configuration
Only a small modification of the setup used in this post is required.
To enable communication from one host to another in the network we need to make the AllowedIps less restrictive. Recall AllowedIps configures the routing table for the interface, determining which destination addresses can be routed into the VPN’s interface. In this case we can open it up to 10.20.10.0/24 to widen access to all hosts in our subnet.
Local DNS
I then used CoreDNS to provide local DNS resolution for the VPN network. This allows me to refer to devices by name rather than IP address. The following Corefile enables this for the network shown above:
. {
hosts {
10.20.10.1 vps
10.20.10.2 desktop
10.20.10.3 nas
10.20.10.4 laptop
fallthrough
}
}
Instructions and examples for setting up CoreDNS with systemd can be found at https://github.com/coredns/deployment/blob/master/systemd/README.md, and don’t forget to open up port 53/UDP in your firewall for DNS queries. Note, if you are using ufw, then you can restrict access to udp port 53 to just the VPN interface and subnet like so:
ufw allow in on wg0 from 10.20.10.0/24 to any port 53 proto udp
It is also recommended to use Coredns’s bind plugin to restrict which interfaces CoreDNS listens on. For example, to only listen on the VPN interface wg0:
. {
bind wg0
...
}
Do(HTTPS|TLS) for Remote Hosts
To enable DNS resolution for hosts outside of the VPN network so that VPN clients can route all their DNS queries through the VPN, we can use DNS over HTTPS or DNS over TLS. CoreDNS makes this simple with the forward plugin. For example,
. {
hosts {
10.20.10.1 vps
10.20.10.2 desktop
10.20.10.3 nas
10.20.10.4 laptop
fallthrough
}
forward . tls://1.1.1.1 {
tls_servername one.one.one.one
}
}