Setting up a VPN with Wireguard
vpn services are hot-selling services. marketers love them because of the high affiliate commission they can get selling them.
and the pitch they use to sell vpns to unsuspecting buyers is this:
You can use vpn for these reasons:
- “protect yourself from public wifi which can sniff your bank details!”
- “protect your identity! don’t let your ISP and advertisers sniff your browsing activity!”
- “access netflix from other countries so that you can see shows blocked in your country!”
But the buyers just pretend to be unsuspecting, just as the marketers pretend to care about these usecases.
The real reasons people buy vpn for, are:
- so they can torrent movies and shows
- so they can price shop items where the seller has enabled price parity on certain countries
- so they can watch porn, as most countries ban most of some of those sites
so… I don’t know why I’m telling you all this, but I got it into my head recently the idea of setting up a vpn myself since I have 2 servers.
That’s when I came to know about wireguard.
And I set it up.
“Okay, but why?”
without this setup, running curl ifconfig.me from my laptop would say, let’s say:
122.178.3.4
and running it from one of my vps servers would say, let’s say:
132.145.1.2
now… with the wireguard vpn set up on both the systems, and telling my laptop wireguard to tunnel traffic through the server wireguard…
running curl ifconfig.me from my laptop would now say:
132.145.1.2
wow worthy isn’t it? (you may not appreciate it. but for some people, it is.)
Let’s see how to do it.
Wireguard VPN setup steps
install wireguard on all systems
wireguard comes with a wg command-line utility. use it to generate a private and public key, like so on each of the involved systems:
umask 077 # this ensures the 2 key files created in the next cmd has 600 permissions
wg genkey | tee private.key | wg pubkey > public.key
remember: the private key generated in each system stays in that system. never leaves. only the public key will be copied and used in other systems where the communication needs to happen.
now, in each system, we’ll create a wireguard config file to represent the “network interface” we’re going to add. This interface is the one through which the traffic will flow.
a wireguard network interface is a systemd service, defined by a ‘/etc/wireguard/ folder, where the file’s name would be the interface’s name that you can see when you run ip addr command. the typical name looks like wg0, wg1, wg2 etc.
once the conf file is created properly, the systemd service can be started and shut down with:
sudo systemctl start wg-quick@wg0
sudo systemctl stop wg-quick@wg0
Once started, you can see wg0 as an additional interface in ip addr, like so:
22: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 10.10.0.1/24 scope global wg0
valid_lft forever preferred_lft forever
so, what’s in the config file?
before that, we’re going to have to define the kind of ’network’ we want with our setup.
with wireguard, you can design a vpn with a bunch of nodes that all talk to each other directly.
or you can design a vpn where all the nodes talk to each other indirectly through a central hub node. The nodes connect only to the hub node.
or, you can design it to suit your specific arrangement. anything is possible with wg!
in my case here, i want to use my vps servers as a tunnel for the traffic coming from my local laptop. i don’t need the 2 vps’ talking to each other.
so…
why does this matter? as mentioned above, this determines what goes in the config file.
in all cases, the [Interface] and [Peer] blocks are needed.
only for the nodes that we want to use as a tunnel, we’ll have a ‘PostUp’ and ‘PostDown’ section in the Interface block. These define iptables commands that says to just
accept the traffic from the wireguard interface and forward it to the system’s WAN interface by masquerading it as the server’s ip. (<— this masquerading as server ip thing… this is what we’re here for.)
the nodes that send traffic to the tunneling nodes.. their config won’t be needing the iptables part.
in my case, the vps servers are the tunneling nodes. my local laptop is the traffic sending node.
so… here’s how the conf will look for a tunneling node (wg0.conf):
[Interface]
Address = 10.0.0.2/24
ListenPort = 51820
PrivateKey = <tunneling node's private key>
# Enable IP forwarding (routing all traffic)
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE
[Peer]
# Local machine
PublicKey = <the local machine's public key>
AllowedIPs = 10.0.0.1/32
And here’s how the conf for the local system (wg0.conf):
[Interface]
Address = 10.10.0.1/24
PrivateKey = <private key of local system>
DNS = 1.1.1.1
[Peer]
PublicKey = <public key of the specific vps>
Endpoint = 124.44.555.128:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Since my local system has to connect to 2 vps’.. so that i can use either as a vpn… i would need one more conf - wg1.conf - to connect to the other vps. it’d be the same except for the endpoint ip address.
One more thing. Since the vps servers are forwarding traffic, we’ll have to enable that ability in them. Do it with:
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf
(note: i’m not entirely sure how this does what it does. need to look it up. TODO.)
Oh.. one more one more thing. You’ll also have to ensure the wireguard port 51820 is not blocked at any level. I had this problem with the vps servers. Previously I had setup a firewall at vultr’s web ui level that blocked all outgoing traffic from all ports except 22, 80 and 443. I had to open the udp traffic on the wg port there to get this whole vpn thing working. The ufw command to open it at the system level:
sudo ufw allow 51820/udp
sudo ufw reload
# if you use iptables directly
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
starting the vpn service
Once the conf files are set up properly.. now would be a good time to start the systemd services, using the commands mentioned already above.
Note: While the vps servers have one wg conf each, the local system has 2. Don’t start both. Only start the one through which you want the traffic to be tunneled.
Once started, confirm if the service is up and running fine with:
systemctl status wg-quick@wg0
Now if you go to https://whatismyipaddress.com/ and check your local ip, it would be that of the specific vps server through which you tunneled its trafic. wow it is.