Your own private VPN
In the past, I often used to remotely connect to my desktop computer at home to perform intensive tasks such as compiling programs or doing ML workloads. To achieve this, I simply opened the router port and had a free reverse DNS service that would automatically bind my home’s current IP to a domain name. It was a simple solution and it worked quite well.
Today, while working on my master thesis, I find myself in a slightly more complex scenario: I have my computer at home, as well as a workstation behind a university firewall, and I want to be able to work from my laptop when necessary or connect either workstation with one another. I thought of leveraging my VPS by hosting a VPN server there.
I decided to give Wireguard a try, since it is a recent, lightweight and performant VPN implementation that works on multiple platforms and it is included by default in recent Linux kernel versions. Moreover, the set-up was straight forward and the config files turned out to be very short.
I’ll share my setup since I think that it might be useful for other people. But please bear in mind that I am not a network engineer so I don’t really know if this is the best way of doing things.
The first step would be to install
wireguard-tools on your server and clients.
For MacOS, I’d recommend installing wireguard to brew, since the AppStore client
app gave me some problems when I tried to SSH into the other computers.
I don’t want to pass all my network traffic through the VPN, but rather just to create a subnet so that I can connect all my computers and devices together. This way, each device will have its own gateway to the internet untouched.
You will have to generate a pair of private and public keys for the server and all the clients that will be connected to the VPN. To generate a pair, you can run:
wg genkey | tee privatekey | wg pubkey > publickey
On your server, open the file
/etc/wireguard/wg0.conf and write:
[Interface] Address = 10.0.0.1/24 ListenPort = 41194 PrivateKey = <your_server_privatekey> # You will need to add this for every device you would like to add # to your network [Peer] Publickey = <your_client_publickey> # This is the IP that will be assigned to this client AllowedIPs = 10.0.0.2/32
I chose to create a local net with the prefix
10.0.x.x so that it does not
collide with each computer’s home subnet
192.168.x.x. You can in fact check
that this is what happens when I define the adresses and masks.
On every client, install wireguard and write the following in
[Interface] PrivateKey = <your_client_privatekey> # The IP you assigned to your client AllowedIPs = 10.0.0.2/24 [Peer] PublicKey = <your_server_publickey> # We want this client to be able to access every other device in the subnet AllowedIPs = 10.0.0.0/24 Endpoint = <your_domain_or_server_ip>:41194 # Keeps the connection alive PersistentKeepalive = 15
Then, on the server and every client, enable and activate Wireguard:
sudo systemctl start wg-quick@wg0 sudo systemctl enable wg-quick@wg0
And that’s all! If you followed this configuration you now should be able to connect between your computers too.
Note: I had some problems with SSH that I solved
by putting the following under the
[Interface] section of my server config:
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE