-
Notifications
You must be signed in to change notification settings - Fork 3
Linux: WireGuard VPN
WireGuard is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache.
These are my setup notes.
WireGuard was included in the kernel source in some 4.x release. At the time of writing, the vps hosting the WireGuard server is running a 4.19 kernel. The kernel headers will be needed, and IP forwarding needs to be enabled.
$ sudo apt install linux-headers-$(uname -r)
$ echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.d/99-sysctl.conf
$ sudo sysctl net.ipv4.ip_forward=1
The install can be completed with apt
on a Debian-based distro. After installation, load the kernel module.
$ sudo add-apt-repository ppa:wireguard/wireguard
$ sudo apt update
$ sudo apt install wireguard
$ sudo modprobe wireguard
Time to generate some keys.
$ (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
The final config looks like this.
# /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <base64 encoded private key string>
ListenPort = 5555
SaveConfig = false
Address = 10.0.0.1/24
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -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
Both Android and iOS can install WireGuard clients from their respective Play/App Store. In the mobile app, set up a new connection and name it accordingly. Click Generate to create a new client key pair. Copy the mobile client public key up to the server (ashamedly, I did mine through pastebin). Apply the following settings:
This is the internal private IP that the VPN interface will be assigned on the client.
- Addresses: 10.0.0.2/32
We run our own DNS server to prevent leaking DNS queries, and so that we can null-route undesirable domains.
- DNS Servers: 10.0.0.1
Copy the server's public key from /etc/wireguard/pubkey
.
- Peer Public Key:
Allow the client to communicate out the internet.
- Allowed IPs: 0.0.0.0/0
Specify the VPN server's IP address so the client knows where to connect. The port should correspond with ListenPort
in the WireGuard configuration.
- Endpoint: 1.2.3.4:5555
Add the public keys from any clients into /etc/wireguard/wg0.conf
. This is what my final config looks like.
# /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <base64 encoded private key string>
ListenPort = 5555
SaveConfig = false
Address = 10.0.0.1/24
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -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
[Peer]
PublicKey = <base64 encoded public key string of mobile client>
AllowedIPs = 10.0.0.2/32
[Peer]
PublicKey = <base64 encoded public key string of mobile client>
AllowedIPs = 10.0.0.4/32
Earlier there was mention of hosing our own DNS so that we could null-route undesirable domains. The DNS server in this case is unbound, and it needs to be seeded.
$ sudo apt install unbound unbound-host
$ sudo wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache
Next the zones need to be set for the blacklisted domains. I'm using the aggregate from StevenBlack.
$ sudo mv /etc/unbound/unbound.conf.d/ads.conf /etc/unbound/unbound.conf.d/ads.conf.$(date +%s) 2>/dev/null
$ wget -q -O - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts | grep '^0.0.0.0 ' | while read entry; do
fqdn=$(echo "${entry}" | awk '{print $2}')
echo "local-zone: \"${fqdn}\" redirect" | sudo tee -a /etc/unbound/unbound.conf.d/ads.conf >/dev/null
echo "local-data: \"${fqdn} A 0.0.0.0\"" | sudo tee -a /etc/unbound/unbound.conf.d/ads.conf >/dev/null
done
Note: You need the ca-certificates
package, otherwise wget
will bail from failing the cert check. Also:
$ wget -qO- https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts | wc -l
40056
😭 😭 😭 😭 😭 😭 😭 😭 😭 😭 😭 😭 😭 😭 😭
A few last items to finalize the DNS setup.
$ sudo chown -R unbound:unbound /var/lib/unbound
$ sudo systemctl enable unbound
$ sudo unbound-host -C /etc/unbound/unbound.conf -v ietf.org
$ sudo systemctl restart unbound.service # don't recall why I did this but it's in my history ¯\_(ツ)_/¯
I think that does it. Give a shout if this doesn't work. Obviously technology moves quickly so adapt relevant changes as necessary.