Wireguard Self-Hosted Virtual Private Network Tunnel
Wireguard is a self-hosted network tunnel program, used to securely connect hosts and peers in a fashion much similar to SSH. It boasts simplicity without sacrificing security, resulting in a robust network tunnel with minimal impact on host server performance.
The heart of wireguard lies in using UDP protocol, as opposed to TCP, which minimizes interaction on the host's part, and has the added benefit of preventing connection information from being read (like with SSH, tcp protocol tells the client that the connected port is for SSH, which hackers can use to brute force into).
The main mechanism behind wireguard is almost identical to SSH, where the host and client have public and private keys to validate each other with. During each connection attempt, both host and client verify the public key provided and validate to that of the locally stored private key. Only after validation does the host allow the connection, and this allows for access to network hardware and clients.
The applications of such a network tunnel are plentiful. Network tunnels allow concealment of local network traffic when in sketchy public wireless networks. Local area restrictions can be circumvented by establishing a tunnel to a network without such network restrictions.
My applications will initially be to sync my phone's photos to my home server from anywhere in the world. Later, I will implement pi-hole on my home network to remove all advertisements for anything on my network, and using wireguard will allow me to gain all the benefits of pi-hole wherever I am on my phone.
I'm sure there's more that can be done, but the beauty of this program is in it's simplicity of performance and setup. Given it is UDP protocol too, it is highly resistant to DDOS attacks, which jam up networks operating TCP protocol and constantly sending back network responses.
Below is a minimal setup for wireguard that can be upscaled to allow for many peers or devices to connect.
Wireguard installation & setup
Installation
To begin setting up wireguard, install wireguard through
sudo apt install wireguard
Key Pair Generation
Next, we need to securely generate public and private key pairs on our systems. I tend to store all wireguard files under /etc/wireguard which is unreadable by any system users.
We can accomplish this as a one-liner through
wg genkey | tee wg_client | wg pubkey > wg_client.pub,
which generates the private key string, pipes it to tee to write the key to wg_client, which then pipes to wg pubkey to derive the public key from the private key file.
To secure these keys, we shift ownership to root and move into /etc/wireguard/keys:
sudo chown root:root wg_client* sudo chmod 600 wg_client sudo chmod 644 wg_client.pub sudo mv wg_client* /etc/wireguard/keys/
The process will be identical on the server:
wg genkey | tee wg_host | wg pubkey > wg_host.pub sudo chown root:root wg_host* sudo chmod 600 wg_host sudo chmod 644 wg_host.pub sudo mv wg_host* /etc/wireguard/keys/
wireguard host configuration
Wireguard configuration files are actually quite similar between hosts and clients. For the host config, the setup generally follows the structure
[Interface] Address = 10.0.0.1/24 PrivateKey = [Peer] PublicKey = AllowedIPs = 0.0.0.0/0
and it is immediately apparent the mechanism of the public/private key handshake. Each configuration will validate the privided public key to the listed private key.
There is a few intricacies between client and host configs, though, here we show them side by side
===== SERVER CONFIG ===== | ===== CLIENT CONFIG ===== [Interface] | [Interface] Address = 10.0.0.1/24 | Address = 10.0.0.2/24 ListenPort = 51820 | PrivateKey = CLIENT_PRIVATE_KEY PrivateKey = SERVER_PRIVATE_KEY | DNS = 1.1.1.1 | [Peer] | [Peer] PublicKey = CLIENT_PUBLIC_KEY | PublicKey = SERVER_PUBLIC_KEY AllowedIPs = 10.0.0.2/32 | Endpoint = SERVER_PUBLIC_IP:51820 | AllowedIPs = 0.0.0.0/0
Obviously you need to fill in the various public and private keys, but a few variable stand out. It is seen that each interface has a unique address which is akin to assigning static ip addresses on your home network. Each config also has an AllowedIPs variable to whitelist the ips that can connect as peers. Also if you want to use DNS, you need to specify which in the client config file, where above we use cloudflare dns.
However, we specify an endpoint for the peer under the client config, linking to the server ip under our established private network at the default port 51820. This means that whatever port you assign here will need to be accessible through various network and local (i.e. ufw) firewalls. So ensure your network port 51820 is open to UDP connections and set ufw to allow this port through
sudo ufw allow 51820/udp comment wireguard
For now though, we save the configs and setup the interface using these configs through:
sudo wg-quick up wg0
on both host and client. you can then verify the connections through
sudo wg ping 10.0.0.1 ping 10.0.0.2
These should indicate the valid connection. if it isn't pinging, the likely issue is the network or local firewalls aren't configured to allow traffic to the server.
finally, we can automatically boot up wireguard on system startup through
sudo systemctl enable wg-quick@wg0
on both host and client.
optional upgrades
The above will function to connect to your server, but you may want to use it as a vpn and masqeurade your ip with that of your server's. However, the wireguard network interface is not the primary internet interface, as seen when running `ip addr` on either client or server. Therefore, we need a way to route network traffic from the server's wireguard interface to the server's primary network interface.
To set this up, we set up two sets of commands to be run when starting up wireguard (PostUp) and shutting down wireguard (PostDown)
# network routing from wg0 PostUp = sysctl -w net.ipv4.ip_forward=1 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT PostUp = iptables -t nat -A POSTROUTING -o NETWORK_INTERFACE -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT PostDown = iptables -t nat -D POSTROUTING -o NETWORK_INTERFACE -j MASQUERADE
Where NETWORK_INTERFACE is the interface listed by `ip addr` that your internet traffic goes through. Using these, the routing will automatically be set up and removed whenever wireguard is started up or shut down, leading to a secure way to set up a VPN to guard network traffic in public settings.