Wireguard

Wireguard is a fast, and very lightweight VPN solution, that has the benefit of being cross platform. One of it’s drawbacks, though, is you need to manage all ends of it: Key generation, key distribution, addressing, etc.

Which is fine for more technical people such as myself, but for less skiled individuals, a solution like Tailscale (Which is based on wireguard) is probably a better way to go.

However! If you are up for it, you can totally manage this all yourself.

Scenario

I needed to bridge two networks, without relying on indivual endpoints being bothered with having a client installed, etc. I also wanted to be able access resources on both sides of the network, using domain names. Only one side of the network has a public hittable IP. The network with the hittable IP will be knonw as “Network 1” and the other half “Network 2”

Addressing

While IPv6 is all the rage these days, I will admit my lack of solid understanding of it, to the point where I’d be able to do all the required routing magic, DHCP allocation, etc. Bear with me! It took me 10 years to get where I am dealing with IPv4 😅

One network was already addressed in the 192.168.0.0/24 network. Leaving that network alone, as it has the most unmanaged endpoints. I do NOT want to go through re-addressing that! The other network is new, so I settled on the magic network I usually pick: 192.168.42.0/24.

Now, there’s a third network to keep in mind, here: The VPN network. You may be asking “Why a VPN network?” Good answer for this is:

1 Isolation 2 Hides the routing away from clients 3 Allows more networks to join, without concerning about addressing

For the VPN network (Or, core network, if you will), I picked 10.8.0.0/24. I picked that because it is very obvious the addressing is “different” from the end point networks.

Network design

So the concept is like this:

    Network 1           Core Network           Network 2
   --------------           -----------          ---------------
  |192.168.0.0/24|   <-->  |10.8.0.0/24|  <-->  |192.168.42.0/24|  
   --------------           -----------          ---------------

Network 1

Network 1 has the benefit of full control of the firewall, but also has the drawback of not having very reliable power/ISP, and has limited compute space. That’s fine, though! All we really need is one stable machine to accept inbound VPN connections, to build the hub of connected networks.

I had a spare laptop sitting around, so and I’ve been meaning to cut my teeth on FreeBSD, I started with a fresh FreeBSD install, and then used pkg to install the wireguard software. After much finangling, I could not get the final routing bits in place, finally cut my losses, and went with Debian, which I am much more familiar with.

So, the configuation I used for the hub is here:

[Interface]
Address = 10.8.0.1/32
SaveConfig = true
ListenPort = 51820
PrivateKey = HUB PRIVATE KEY HERE

[Peer]
PublicKey = NETWORK2 PUBLIC KEY HERE 
AllowedIPs = 10.8.0.2/32, 192.168.42.0/24

You’ll note the peer’s AllowedIPs are for both the core router network, and the other network’s private IP space. This allows bi-directional routed traffic. Note, I am not masquerading any IPs here. This is all a raw IP packet routing 😀

Also, on the host, you will need to enable IP forwarding, and I personally also allow ICMP forwarding too, for troubleshooting:

sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf

The first line enables it right meow. The second line makes it persist across boots.

Afterwards, I had to modify the hardware router config, as it was responsible for handing out the DHCP leases. I have a TP Link router on both networks, and they allow for adding routing table entries.

I needed two additional ones there: Dest Network: 192.168.42.0/24 via 192.168.0.100 (IP address of the laptop dealing with wireguard routing) Dest Network: 10.8.0.0/24 via 192.168.0.100 (Same, but this allows the network to also know where the VPN routing network is)

Also, this side is the network that I have full management of the firewall inbound, public address, etc. So, I also needed to forward the UDP port to it, but elected instead to make it the DMZ host. I’ll leave this exercise to the reader, but you will either need to full expose the machine to the internet, or forward UDP 51820 to 192.168.0.100.

Network 2

This network hosts most of the services, and only one or two endpoints I full manage, and have full control over. This machine will call into the hub, and initiate the connections. The config is as follows:

[Interface]
Address = 10.8.0.2/32
SaveConfig = true
ListenPort = 51820
PrivateKey = THIS NETWORK'S PRIVATE KEY 

[Peer]
PublicKey = HUB'S PUBLIC KEY 
AllowedIPs = 10.8.0.0/24, 192.168.0.0/24, 192.168.42.1/32 # These are all of the networks allowed to route through here.  Note the 192.168.42.1/32, this is so the network can do its thing
Endpoint = PUBLIC IP OF HUB:51820
PersistentKeepalive = 30

If you end up needing three, or four or whatever other sites, you can basically just copy/paste this config into each, modifying the private key, modifying the local router, and adding the network to the hub as well.

You ALSO need to enable packet forwarding on this host. Use the same commands as above for the hub.

Also, in the hardware router, you will need to add routes back, for the 192.168.0.0/24 and 10.8.0.0/24 networks.

Summary

If you need another network, this isn’t an issue! Just make sure you add all of your networks in the wireguard confs, so it knows where they are, and that they are allowed. And each hardware router in each network will need backroutes to the other networks you need as well.

All in all, easy peasy. And, if you don’t want to use an old laptop, or don’t have one, a Raspberry Pi 3 or better should handle wireguard connections for about 5-10 networks, if I were to guess.

Some next up articles will be about spinning up some DNS servers for your newly created network, and Proxmox with clustering!