Ubuntu: WireGuard VPN for Ubuntu server, with an iPhone client

WireGuard aims to be the successor to IPsec and more performant than OpenVPN.  It is a general purpose VPN that is secure enough for servers, yet light enough to run on embedded devices.

In a previous article I described the installation of a WireGuard server with a Windows VPN client.  I will extend those instructions here to create a VPN client tunnel from an iPhone.

Below is a diagram that shows the logical deployment.

Prerequisites

You must first install the WireGuard server and validate using a Windows VPN client connection as described in my previous article.

This will get the WireGuard server in the proper form as well as proving out that client connections are possible.  Once we involve mobile devices, there are many environmental issues (enterprise lockdown, IPv6, mobile carrier port blocks, etc) that may affect the solution.

So we want proof that a basic client works properly before moving forward.

Key exchange using QR code

In the previous article for the Windows client, we generated the client’s public/private keypair on the client host.  We then moved the client’s public key to the WireGuard server side so we could add it as a valid client peer.  This is a robust security stance because the server and client never see each other’s private key.   They exchange is only of public keys.

However, if you allow the client’s public+private keypair to be generated on the WireGuard server (or another server), then you have the ability to send this keypair to the client via a secure third-channel (secure mail or some other means) while in parallel having the WireGuard server add the public side of the keypair to its authorized peer list.

In exploration of this solution, we will have the WireGuard server itself create the client’s public+private keypair, and this will be used to:

  • Authorize the client to connect to the server, by adding the public side of the key to the WireGuard server peer connections
  • Generate a QR code for the iPhone client that will populate its tunnel connection

Generate client’s public/private keypair

As we discussed, we are creating the client’s keypair from the WireGuard server.

sudo mkdir -p /etc/wireguard/clients
sudo chmod 755 /etc/wireguard/clients
cd /etc/wireguard/clients
wg genkey | sudo tee mobile.key | wg pubkey | sudo tee mobile.pub

Add client authorization as peer

Using the client’s public key, we can now add it to the server’s authorized peer list.

# authorize mobile client as peer with WireGuard server
sudo wg set wg0 peer '$(cat mobile.pub)' allowed-ips 10.0.14.8/32

# server will now show this peer
sudo wg show

Create client configuration file

Then create the client configuration file with placedholders we will replace momentarily.

$ sudo vi wg0-client.conf
[Interface]
PrivateKey = <clientPrivateKey>
Address = 10.0.14.8/24
ListenPort = 51820

[Peer]
PublicKey = <serverPublicKey>
Endpoint = <serverPublicEndpoint>:51820
AllowedIPs = 172.16.0.0/16
PersistentKeepalive = 15

Now define the values and do a replacement.

# client keypair just generated
clientPrivateKey=$(cat mobile.key)
clientPublicKey=$(cat mobile.pub)

# the location of the WireGuard server public key
# from the previous article
serverPublicKey=$(cat ~/publickey)
echo "serverPublicKey: $serverPublicKey"

# the public IP address or fronting router address of WG server
serverPublicEndpoint=199.99.99.99

# do replacements in file
sudo sed -i "s|<clientPrivateKey>|$clientPrivateKey|" wg0-client.conf
sudo sed -i "s|<serverPublicKey>|$serverPublicKey|" wg0-client.conf
sudo sed -i "s|<serverPublicEndpoint>|$serverPublicEndpoint|" wg0-client.conf

# show WireGuard client configuration
cat wg0-client.conf

We now need a way to pass this configuration to the iPhone client.  You could send the information via secure email, but another way is to generate a QR code that can be scanned by the phone.

# required package
sudo apt-get install qrencode -y

# generate QR code using ANSI
qrencode -t ansiutf8 -r wg0-client.conf

This utility is capable of generating HTML and other image formats, but for our purposes ASCII encoding is sufficient.

iPhone WireGuard app installation

We are now ready to configure the iPhone.  Go to the App Store and search for “WireGuard”.  You should see an app that looks like below from the “WireGuard Development Team”.

“Get” and then “Open” the application.  Click the plus icon at the top right to get a choice of how to create the new tunnel configuration (file,QR, or scratch).   Choose “Create from QR code” and then point your phone at the QR code generated earlier on the server.

Save this configuration as “iphone1”.  Then select the new tunnel configuration  which will pull up the settings like below.

If you need to adjust any values (for example the public Endpoint of the WireGuard server changes because of DHCP), you can press “Edit” at the top left to make any adjustments.

Slide the status to “Active” where it will now show as green.  Then open Safari and manually type in the address “http://172.16.1.10”, and you should get the same message that the Windows VPN client did from the previous article as shown below.

Other public internet sites are still available because it is only IPs in the client ‘AllowedIPs’ CIDR block that are directed toward the VPN tunnel (172.16.0.0/16).

 

REFERENCES

fabianlee github, diagram source

fabianlee.org, WireGuard server and Windows VPN client

stanislas, Wireguard and IPv6, qrcode

serverssideup.net, QR codes for WireGuard

stanislas.blog, Wireguard and IPv6

artixlinux.org, wireguard preshared secrets psk

gitlab.com, wireshark capture of wireguard traffic

NOTES

generated psk (preshared secret on server)

wg genpsk > presharedkey

from server, adding client peer that has psk

wg set wg0 peer <publicClientKey> preshared-key client-psk.psk allowed-ips 10.0.14.8/32