I have always wanted to setup my own VPN for privacy reasons. It’s a long overdue personal project.

Staying in a hotel, their wifi is way too slow. So I have been relying on my phone tether for internet access. It’s interesting that phone hotspot blocked connection to Steam so I couldn’t update some of my games. Hence, VPN seems like a good choice.

Wireguard

I came across wireguard while researching OpenVPN. It’s an up-and-coming VPN, which advertised to be more performant and simpler than OpenVPN.

Server

I utilise my ovh vps to run VPN. I did run into a problem where I couldn’t redirect ipv6 traffic through my server. It turned out that ovh hadn’t setup IPv6 by default.

For Ubuntu 18.04, netplan was used by default so I needed to modify /etc/netplan/50-cloud-init.yaml

network:
    version: 2
    ethernets:
        ens3:
            dhcp4: true
            match:
                macaddress: {{ server_mac }}
            set-name: ens3
            addresses:
                    - {{ server_ipv6 }}/64
            gateway6: {{ server_gateway }}

Install Wireguard

The package isn’t in Ubuntu repo so I need to add its ppa.

sudo add-apt-repository ppa:wireguard/wireguard
sudo apt-get update
sudo apt-get install wireguard

Allow Forwarding Traffic

In /etc/sysctl.conf, uncomment net.ipv4.ip_forward=1 and net.ipv6.conf.all.forwarding=1. Then run the command sudo sysctl -p.

Open Port

# a random closed port
sudo ufw allow 12345

Generate Keys

Creating 2 public and private key files only readable by root:

umask 077
wg genkey | tee privatekey | wg pubkey > publickey

Config

#/etc/wireguard/wg0.conf
[Interface]
# ip used to identify between different peers
Address = 192.168.2.1/32, fd86:ea04:1115::1/128
# iptable config to redirect all traffic
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -$
# delete iptable config when wireguard stops
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING$
# port wireguard running on
ListenPort = 12345
PrivateKey = <server privatekey>
SaveConfig = true

Client

Install wireguard and generate keys following the exact same steps as server. Below is my config for wireguard in client:

#/etc/wireguard/wg0-client.conf
[Interface]
Address = 192.168.2.2/32, fd86:ea04:1115::2/128
PrivateKey = <client privatekey>
 
[Peer]
PublicKey = <server publickey>
# allow all ip
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <server ip>:12345
PersistentKeepalive = 25

Now, append to server’s /etc/wireguard/wg0.conf

[Peer]
PublicKey = <client publickey>
AllowedIPs = 192.168.2.2/32, fd86:ea04:1115::2/128

Start VPN

# server
sudo wg-quick up wg0
# client
sudo wg-quick up wg0-client

If everything is working fine, sudo wg will show handshake.

To auto start wireguard on boot, do systemctl enable wg-quick@wg0 on server.

Phone

qrencode -t ansiutf8 < wg0-client.conf creates a qr image to import the config to phone app. I also installed an app to share vpn with other devices.

Testing

I tested the connection with https://test-ipv6.com/, everything work fine with laptop client. But on phone, real IPv6 showed up on the website. At the moment, I’m unsure how to fix it.

Since I used my phone for tether, I could block IPv6 on laptop and no website would be able to tell my real IP. So leaking IPv6 is not really a major concern for now.