Wireguard on OpenBSD for use as a mobile VPN

Last modification on

Wireguard is a fast, modern and secure VPN tunnel.

Below is a guide to setup Wireguard on the OpenBSD operating system intended for use with a mobile VPN.

It describes using the OpenBSD Wireguard wg(4) kernel driver (not the userland application) and will focus on setting up a IPv4 tunnel.

It is recommended to install wireguard-tools. Although not required for using the OpenBSD wg(4) kernel driver they contain useful tools to generate a private and public key.

To install the wireguard-tools package on OpenBSD:

# pkg_add wireguard-tools

Enable IPv4 traffic forwarding

To enable traffic forwarding for IPv4 run:

# sysctl net.inet.ip.forwarding=1

To make it persistent add the above lines to the file /etc/sysctl.conf. These sysctl lines are loaded on boot time.

Server: /etc/hostname.wg0

wgport 51820 wgkey 'private_key_here'
inet 10.1.2.1/24
up

# peer: phone
wgpeer 'pubkey' wgaip 10.1.2.2/32 wgdescr 'phone' wgpsk 'psk_here'

Generating a private key

Using wireguard-tools wg command:

$ wg genkey

Replace private_key_here with the generated text.

To generate both a private and public key to the files private.key and public.key:

$ wg genkey | tee private.key | wg pubkey > public.key

Keep the private key secure. Do not share it with anyone!

Generate a separate preshared key (PSK).

Using a preshared key (PSK) is optional, but recommended. This is used in the handshake to guard against future compromise of the peers' encrypted tunnel if a quantum-computational attack on their Diffie-Hellman exchange becomes feasible.

Using wireguard-tools wg command:

$ wg genpsk

The PSK can be shared with a known client when configuring the clients. Make sure to share it via a safe channel.

To configure or restart the wg0 interface using the configuration in /etc/hostname.wg0:

# sh /etc/netstart wg0

To show general info of the interface run the command (requires root permissions to view all information):

# ifconfig wg0

In the ifconfig wg0 output it should list the server public key as:

wgpubkey server_pubkey_here

Full example of a client config: wg-client.conf

[Interface]
Address = 10.1.2.2/32
DNS = 10.1.2.1
PrivateKey = CHBzstIHCi7+YOOa2MN0RXhkPAmJwIXQW0e6/n6+Pno=

[Peer]
AllowedIPs = 0.0.0.0/0
Endpoint = example.org:51820
PreSharedKey = 8ao/EMExyPAHrT3ShX+lnA0u7jUmo7MhrT0GjDcrIJA=
PublicKey = Rny+AW4EPqPPxfO+8O+QdlkIrWbZRGQ6u6Fje5pUOFM=

Of course do not copy-paste this private key and PSK. Generate your own ;)

pf(4) firewall rules

Below is a fragment of the firewall rules required for Wireguard. These rules assume a simple VPS with a vio network interface connected to the interwebs (no double NAT or other weird complex things ;)).

pf.conf:

# wireguard
pass out quick on egress inet from (wg0:network) nat-to (vio0:0)
pass in quick on wg0 from any to any
pass in quick on wg0 proto udp from any to any port 51820
# allow all on wireguard
pass quick on wg0

Mobile VPN application

For Android download the APK from https://www.wireguard.com/install/. There are also other versions available on the page.

Android Wireguard settings

Adding a tunnel

In the Wireguard application press the plus (+) button in the bottom left of the screen to add a tunnel.

Option: "Scan from QR code"

Generate a QR code image from a client config

Install the libqrencode package for qrencode:

# pkg_add libqrencode

Generate a QR code PNG image from a client config:

$ qrencode -o qr.png < wg-client.conf

This QR code simply contains the full text from the wg-client.conf. It can be scanned from the Android Wireguard application. If it contains sensitive information such as the private key make sure to share the image in a safe way and/or destroy it immediately.

QR code image

If the QR code contains a private key, make sure to destroy it "Inspector Gadget"-style.

inspector Gadget reading self-destruct message

Inspector Gadget, self-destruct video clip

Now scan the generated image to import the config.

Option: "Import from file or archive"

Import a text .conf file or archive (ZIP) file containing one or more configs.

Example conf file: client-example.conf.
Example ZIP file: client-example.zip.

Option: "Create from scratch"

Generating the private key on the device itself and sharing the public key and PSK is probably the safest option. Although sharing the public key text from a mobile device can be a bit annoying.

Android settings

Only allow connections and DNS using VPN:

  • Settings -> VPN -> Network & Internet: Make sure Wireguard is set and enabled under VPN.

VPN settings, open Wireguard cogwheel:

  • Enable: Always on VPN option, with the description: "stay connected to VPN at all times".
  • Enable: Block connections without VPN.

Other recommendations:

  • Under Wi-Fi -> Privacy.
    • Use randomized MAC.
    • Disable "Send device name".
  • Set a secure and privacy-respecting DNS server.

Debugging tips

For the Wireguard Android application you can find a textual log:

  • Open the Wireguard application.
  • At the top right select the 3 dots settings thingy.
  • Select the menu labeled "View application log".

On the OpenBSD server you can run enable run-time debugging on the wg0 interface:

# ifconfig wg0 debug

Bonus: example using wg-quick from wg-tools

Using the wg-quick program from wg-tools you can also quickly setup a client. This will setup the DNS, routing and interface. It can setup and restore the DNS and routing settings easily.

As root, to setup the interface:

# wg-quick up absolute/path/to/config/wg-client.conf

As root, to restore the interface:

# wg-quick down absolute/path/to/config/wg-client.conf

Bonus: generating a private key using only OpenSSL commands

Generate a private key:

$ openssl genpkey -algorithm X25519 -outform DER -out private.der

Now extracts the last 32 bytes which has the actual private key (the first ASN.1 DER encoded bytes contain metadata information). Convert the actual key (partly truncated) data to base64.

Run:

$ tail -c 32 private.der | openssl enc -a -A > private.key

Derive public key:

$ openssl pkey -inform DER -in private.der -pubout -outform DER -out public.der

Convert public key to Wireguard format:

$ tail -c 32 public.der | openssl enc -a -A > public.key

References