Configuring and Managing Routes Between Multiple Networks with Wireguard

Joseph D. Marhee
Oct 3, 2019 · 4 min read

I recently updated the VPN solution in my infrastructure lab using Wireguard; my architecture is fairly basic, in that each site (in this case, a handful of colocated environments, and multiple cloud providers) runs a Wireguard endpoint, which then are peered with one-another to connect my service network (rather than that of the hosts themselves) across these sites and providers.

I made the switch after using Wireguard in the context of direct connecting cloud provider networks in my work, and decided to do the same for my lab, which spans a much smaller scale, but a much more diverse set of machines and networks, which made managing a large OpenVPN configuration somewhat cumbersome, and found Wireguard straight-forward, if a little light on diverse documentation, but reasonably well-suited to automation.

There are many excellent guides online for configuring Wireguard between multiple peer nodes, and for my use-case, I found that I need additional route changes to allow each peer to access the LANs the accompanying peered nodes were a part of.

For example, assuming a network, 192.168.2.0/24 for the Wireguard interfaces themselves, my first server in one location, 192.168.2.1 was part of a network in that location for machines not, themselves, setup with Wireguard, 192.168.122.0/24 , and another endpoint accessible on Wireguard as 192.168.2.2, 192.168.1.0/24 , and I wanted this latter set of machines to be able to access the machines in the LAN for the former, but not the other way around.

The standard Wireguard config supports PostUp and Down arguments to add additional routing changes, and support for things like configuring NAT with iptables . In this respect, this is the only non-standard use of Wireguard in-use in my project.

On my server, my configuration looked like this:

[Interface]                                                                                                             Address = 192.168.2.1                                                                                                   PrivateKey = (Hidden)                                                               ListenPort = (Whatever)                                                                                                     PostUp   = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o virbr0 -j MASQUERADE                                                                                                     PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o virbr0 -j MASQUERADE                                                                                                                                                                                                                             

with [Peer] blocks for two other endpoints that can access the networks attached to 192.168.2.1 ‘s virbr0 interface:

[Peer]                                                                                                                  PublicKey = TH+DHbSc7ALMapPCsUlCVzWJdQKtFPNfW8Hkel8m2Uw=                                                                Endpoint = (Host):(Port)                                                                                         PersistentKeepalive = 25                                                                                                AllowedIPs = 192.168.2.3/32  
[Peer] PublicKey = 6w/+laHf7m0T13tgogRbwKp5na20yygLObLL9AgSHH8= AllowedIPs = 192.168.2.2/32 Endpoint = (Host):(Port)

Pretty straightforward, but to drill down on the behavior I’m hoping to achieve here, only this server 192.168.2.1 will have PostUp and Down rules:

iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o virbr0 -j MASQUERADE

in this case, to forward traffic over the wg0 interface (in my case, but in the above, the %i will automatically substitute the interface you’re bringing online when you do things like wq-quick up {interface name} ) to the target network you’d like to expose to the peers (and then enable in the client config, which I’ll cover in a moment), which in this case is the network attached to the bridged interface, virbr0 .

Because I wanted my peer sites to be able to run workloads in and out of this LAN attached to 192.168.2.1 endpoint, my client config does not require PostUp or PostDown -managed route changes, but does need to be aware of the networks it will be exposed to (via those firewall changes on that endpoint — changes we will not be making on these client peer endpoints):

[Interface]                                                                                                             PrivateKey = (Hidden)                                                               ListenPort = (Port)                                                                                                     Address = 192.168.2.2/24                                                                                                DNS = 1.1.1.1
[Peer] PublicKey = mXvCVKYmYuYL0AO2AvDPsLmOdUGwXDi5d2DekKCt9RY= AllowedIPs = 192.168.2.0/24, 192.168.122.0/24 Endpoint = (Host):(Port) PersistentKeepalive = 25

So, in this configuration, we’re exposing a new endpoint at 192.168.2.2 to peer with 192.168.2.1 , and in AllowedIPs , we not only want to be aware of the Wireguard network we’re declaring 192.168.2.0/24 , but the network attached to the first host’s virbr0 interface, in this case, 192.168.122.0/24 .

Behind this new endpoint is a network, 192.168.0.0/24 that the first host cannot be routed back to without adding a similar rule on this new endpoint’s Interface configuration, but if we were to add similar rules to the iptables rules we added above, and then in the config for the first server’s Peer block:

[Peer]                                                                                                                  PublicKey = 6w/+laHf7m0T13tgogRbwKp5na20yygLObLL9AgSHH8=                                                                AllowedIPs = 192.168.2.2/32, 192.168.0.0/24                                                                                             Endpoint = (Host):(Port)

like so, this remote peer’s network could similarly forward traffic, and route it appropriately.

Basically, at the end of this, you can use Wireguard as a site-to-site VPN, and much like you would with any VPN solution, more flexibly operate access to the networks attached to each endpoint, and similar to the push "${some route}" behavior in OpenVPN, for example, using the lean interface of the Wireguard configuration format to accomplish this.

Additional Resources

Configuring Wireguard

Kilo — Wireguard-based multi-cloud overlay

More From Medium

More from Joseph D. Marhee

More from Joseph D. Marhee

Using for_each in Terraform in modules

169

More from Joseph D. Marhee

More from Joseph D. Marhee

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade