March 19, 2019

Wireguard Port Forwarding

I’ve been trying to setup Wireguard. It’s one of those things where it looks like it should be quite easy, but if it doesn’t work you have no idea why.

I have a computer sitting in our office, and I want to be to access it outside of our office over the internet. Unfortunately, the office is behind a NAT and I can’t just go exposing ports.

SO, I used DigitalOcean to create an tiny Ubuntu server in the cloud. This server has a static IP address, and I have control over which ports are accessible.

My plan is to use Wireguard to create a VPN between the office computer and the cloud server. Then I can forward traffic from the server to the office, quickly and securely.

From now on, I will refer to the office computer as the “client” and the DigitalOcean server as the “server”.

You will need to be root for most of these commands, so I have dropped the sudo prefix.

Installing Wireguard

Ubuntu

add-apt-repository ppa:wireguard/wireguard
apt-get update
apt-get install wireguard-dkms wireguard-tools

Arch Linux

You can also use systemd-networkd to configure wireguard, but I think it just makes it even more complicated.

pacman -S wireguard-arch wireguard-tools

Generating private/public keys

You need to do this on both the client and the server.

umask 077
cd /etc/wireguard
wg genkey > privatekey
wg pubkey < privatekey > publickey

Configuration

Everything in <> is a variable and should be replaced.

Server

[Interface]
Address = <SERVER_ADDRESS>
PrivateKey = <SERVER_PRIVATE_KEY>
ListenPort = <SERVER_PORT>

[Peer]
PublicKey = <CLIENT_PUBLIC_KEY>
AllowedIPs = <CLIENT_ADDRESS>/32

Client

[Interface]
Address = <CLIENT_ADDRESS>
PrivateKey = <CLIENT_PRIVATE_KEY>

[Peer]
Endpoint = <SERVER_IP>:<SERVER_PORT>
PublicKey = <SERVER_PUBLIC_KEY>
AllowedIPs = <SERVER_ADDRESS>/32
PersistentKeepalive = 25

Variables

You need to create a new IP address for the client and server. I think this can be any address that isn’t used.

- <SERVER_ADDRESS>: 10.11.12.1
- <CLIENT_ADDRESS>: 10.11.12.2

These are the private and public keys from the different computers. The following are ones I have generated just for this article, and should not be copy/pasted:

- <CLIENT_PRIVATE_KEY>: OOsIW12TAKkv6yec5gp6nNC3TN53/PyajifXHHz1t08=
- <CLIENT_PUBLIC_KEY>: 8xMY/IkM2pEn4ADjEQM+rQLjSbscg4hrqERNqvXAbyg=
- <SERVER_PRIVATE_KEY>: YGSeVUzy6N0KqcvMeYmE2OJXntJCZOq682WYS6elcm4=
- <SERVER_PUBLIC_KEY>: rczpxKe5VPMrjTPZ13/jwCOYQkZEVzgkVFJPeyK2sn8=

Your server should have a static IP. You will also need to pick a port number, and make sure that it isn’t blocked by any firewall.

I like to use random.org to pick port numbers.

- <SERVER_IP>: 175.198.17.240
- <SERVER_PORT>: 45776

Example Server Config

[Interface]
Address = 10.11.12.1
PrivateKey = YGSeVUzy6N0KqcvMeYmE2OJXntJCZOq682WYS6elcm4=
ListenPort = 45776

[Peer]
PublicKey = 8xMY/IkM2pEn4ADjEQM+rQLjSbscg4hrqERNqvXAbyg=
AllowedIPs = 10.11.12.2/32

Example Client Config

[Interface]
Address = 10.11.12.2
PrivateKey = OOsIW12TAKkv6yec5gp6nNC3TN53/PyajifXHHz1t08=

[Peer]
Endpoint = 175.198.17.240:45776
PublicKey = rczpxKe5VPMrjTPZ13/jwCOYQkZEVzgkVFJPeyK2sn8=
AllowedIPs = 10.11.12.1/32
PersistentKeepalive = 25

Starting wireguard

# start wireguard using our config file
systemctl start [email protected]

# set wireguard to start automatically at boot
systemctl enable [email protected]

Checking status

wg show

You should see information about the peer.

interface: wg0
  public key: 8xMY/IkM2pEn4ADjEQM+rQLjSbscg4hrqERNqvXAbyg=
  private key: (hidden)
  listening port: 36494

peer: rczpxKe5VPMrjTPZ13/jwCOYQkZEVzgkVFJPeyK2sn8=
  endpoint: 175.198.17.240:45776
  allowed ips: 10.11.12.1/32
  latest handshake: 9 seconds ago
  transfer: 560.43 KiB received, 34.57 KiB sent
  persistent keepalive: every 25 seconds

Pinging

Run this on the client to ping the server.

ping 10.11.12.1

Run this on the server to ping the client.

ping 10.11.12.2

Port Forwarding

Now that we have a connection between the client and the server, we can setup port forwarding.

This will forward any incoming traffic to the server on $PORT to the client.

I don’t really understand how iptables works, I just copied this from: https://golb.hplar.ch/2019/01/expose-server-vpn.html

#!/usr/bin/env bash

PORT=6379
SERVER_ADDRESS=10.11.12.1
CLIENT_ADDRESS=10.11.12.2

iptables -P FORWARD DROP

iptables -A FORWARD -i eth0 -o wg0 -p tcp --syn --dport ${PORT} -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -i eth0 -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i wg0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport ${PORT} -j DNAT --to-destination ${CLIENT_ADDRESS}
iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport ${PORT} -d ${CLIENT_ADDRESS} -j SNAT --to-source ${SERVER_ADDRESS}

Saving IP Tables

This will persist your iptables rules in case the server restarts.

apt install iptables-persistent

© 2020 George Czabania