Recently, I read a comment on Hacker News about someone who had created their own private mesh network between their Virtual private servers (VPS).
I decided to try and replicate this myself across three of my VPS instances.
Installing WireGuard
All three of my instances are running Ubuntu 18.04, see the WireGuard instructions for other setups: instructions
sudo add-apt-repository ppa:wireguard/wireguard sudo apt-get update sudo apt-get install wireguard-dkms wireguard-tools
After installing WireGuard on all three machines, I was able to proceed to configuring WireGuard.
Configure WireGuard
Generate Keys
On each machine, I created a private/public key pair:
(umask 077 && printf "[Interface]\nPrivateKey = " | sudo tee /etc/wireguard/wg0.conf > /dev/null) wg genkey | sudo tee -a /etc/wireguard/wg0.conf | wg pubkey | sudo tee /etc/wireguard/publickey
Note: umask in the first line will create a new file with limited permissions.
We have also saved the public key to /etc/wireguard/publickey for use later.
Configuring the Interface
Edit each machines WireGuard config to add ListenPort and SaveConfig.
/etc/wireguard/wg0.conf:
ListenPort = 51820 SaveConfig = true
ListenPort: | This can be any open port, make sure to poke a hole in your firewall |
---|---|
SaveConfig: | Automatically save configuration |
Next, I added a unique IP address to each config, this address will serve as a private IP for each server.
Server 1 - /etc/wireguard/wg0.conf:
Address = 10.0.0.1/24
Server 2 - /etc/wireguard/wg0.conf:
Address = 10.0.0.2/24
Server 3 - /etc/wireguard/wg0.conf:
Address = 10.0.0.3/24
The addresses are provided in CIDR notation. You can pick any subnet you'd like for your own network, I used 10.0.0.0/24.
After adding IP addresses we are read to configure peers.
Server 2 - /etc/wireguard/wg0.conf:
[Interface] ... [Peer] PublicKey = public_key_of_first_server AllowedIPs = 10.0.0.1/32 Endpoint = public_IP_of_first_server:51820 [Peer] PublicKey = public_key_of_third_server AllowedIPs = 10.0.0.3/32 Endpoint = public_IP_of_third_server:51820
Server 3 - /etc/wireguard/wg0.conf:
[Interface] ... [Peer] PublicKey = public_key_of_first_server AllowedIPs = 10.0.0.1/32 Endpoint = public_IP_of_first_server:51820 [Peer] PublicKey = public_key_of_second_server AllowedIPs = 10.0.0.2/32 Endpoint = public_IP_of_second_server:51820
Starting WireGuard
Open firewall
I am using ufw as my firewall and I poked holes on each machine:
sudo ufw allow 51820
Start it up
Now, I started WireGuard for the first time on each machine:
sudo systemctl start wg-quick@wg0
Next, we can check the VPN network interface wg0:
ip addr show wg0
Finally, check the state of WireGuard its self:
sudo wg
Note: the first server should only show an interface config, while the other two will also show configured peers.
Add missing peer configuration
On the first server add configuration for the other two:
sudo wg set wg0 peer public_key_of_second_server endpoint public_IP_of_second_server:51820 allowed-ips 10.0.0.2/32 sudo wg set wg0 peer public_key_of_third_server endpoint public_IP_of_third_server:51820 allowed-ips 10.0.0.3/32
Now check the connection from the first computer to either the second or third computer:
ping -c 3 10.0.0.3
Save the configuration by restarting WireGuard on the first server:
sudo systemctl restart wg-quick@wg0
Checking the VPN connection
Check the connection from each machine:
$ ping -c 3 10.0.0.1 $ ping -c 3 10.0.0.2 $ ping -c 3 10.0.0.3
Sample output:
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data. 64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=45.1 ms 64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=22.0 ms 64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=22.0 ms --- 10.0.0.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 22.034/29.734/45.134/10.889 ms
Configure WireGuard to start on boot
sudo systemctl enable wg-quick@wg0
Conclusion
Setting up a Virtual Private Cloud with my own private mesh was super easy using WireGuard. I was able to follow along instructions from a couple posts to get it working. In retrospect the documentation on the WireGuard site looks quite handy as well.