Wireguard - Android Road Warrior

Motivation

There are a lot of blog posts and wiki pages about how to set up Wireguard, but I still had to do a bunch of trial and error to come up with a configuration that worked for me. I have two goals:

  1. Secure all traffic from my Android phone for privacy / when on unsecured WiFi.
  2. Full access to my home network resources when away from home.

Caveats:

  • This does client key generation on the server, which is fine for this simple use case, but not a cryptographic best practice.
  • This sets up only a single client. If you need multiple clients, you'll have to get fancier.
  • As part of meeting my goals, ALL phone traffic goes through the VPN. That may not be your desired configuration.

Preparation

You will need:

  1. The public IP address of your router (or a DNS record that points to it)
  2. An open port on your router forwarded to wherever you run Wireguard
  3. The IP address of the DNS server your phone should use when connected to your home network (maybe your router, maybe not)
  4. Two addresses in a private subnet not used elsewhere on your home network

Implementation

I hosted all of this in a VM running Ubuntu 18.04.1.
At the end of this process, a QR Code is displayed to be scanned by the Wireguard Android app.
This script is run as root sudo bash -x simple-wireguard.sh:

#!/bin/bash -x

################ CHANGE THESE ##################
# Your Home IP or DNS record
WG_ADDRESS=wireguard.your.domain
# UDP port forwarded to this machine
WG_PORT=12345
# DNS entries for the client to use when on VPN
WG_DNS=192.168.1.1,8.8.8.8
# Unused private IPs for this connection
WG_SERVER_INT=172.16.17.1
WG_CLIENT_INT=172.16.17.2
################################################

add-apt-repository -y ppa:wireguard/wireguard
apt-get -y update
apt-get -y install wireguard qrencode

# Enable Packet Forwarding
echo net.ipv4.ip_forward=1 > /etc/sysctl.d/wireguard.conf
sysctl -p /etc/sysctl.d/wireguard.conf

# Generate Keys and Configurations
cd /etc/wireguard
wg genkey | tee server.private | wg pubkey > server.public
wg genkey | tee client.private | wg pubkey > client.public

# Server Configuration sets up NAT
cat >wg0.conf <<EOF
[Interface]
Address = ${WG_SERVER_INT}
SaveConfig = false
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o net0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o net0 -j MASQUERADE
ListenPort = ${WG_PORT}
PrivateKey = $(cat server.private)

[Peer]
PublicKey = $(cat client.public)
AllowedIPs = ${WG_CLIENT_INT}
EOF

cat >client.conf <<EOF
[Interface]
Address = ${WG_CLIENT_INT}
PrivateKey = $(cat client.private)
DNS = ${WG_DNS}

[Peer]
PublicKey = $(cat server.public)
Endpoint = ${WG_ADDRESS}:${WG_PORT}
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 10
EOF

# Turn on and enable for boot
systemctl start wg-quick@wg0
systemctl enable wg-quick@wg0

# Show the QR Code
qrencode -t ansiutf8 < client.conf

Better Tools

I wanted something simple and comprehensible that I built myself, but there are tools out there that build fancier configurations that are recommended by smart people in this space:

Another option that is built atop wireguard-go is Tailscale. Their service is proprietary, though many of their client implementations are open-source.

References

Below are a couple of gists I worked on when helping someone else trying to use the code above: