Really quick and dirty guide to get wireguard up and running between two machines.

Wireguard (wireguard.io) is an amazing new VPN solution that is simple/secure/performant

Goal is to have a roadwarrior setup, were we can connect from a moving laptop to a central server. All the traffic from the laptop will be routed through the wireguard tunnel and NATed on the central server, this way the client will be able to access its infrastructure remotely and also the Internet.

Install wireguard according to the upstream documentation: https://www.wireguard.io/install/

On the server add a new wireguard device, add an IP address on it and bring it up

$ sudo ip link add dev wg0 type wireguard
$ sudo ip address add dev wg0
$ sudo ip link set wg0 up

on the server and the client generate your public and private keys

$ umask 077
$ wg genkey | tee privatekey | wg pubkey > publickey

On the server we will create the following file: /etc/wireguard/wg0.conf:

ListenPort = 51820
PrivateKey = private_key_previously_generated

PublicKey = public_key_of_the_client
AllowedIPs =

then we will load the configuration:

$ sudo wg setconf wg0  /etc/wireguard/wg0.conf

we should now be able to get the configuration:

$ sudo wg
interface: wg0
  public key: server_public_key
  private key: (hidden)
  listening port: 51820

peer: peer_public_key
  endpoint: public_ip:port
  allowed ips:
  latest handshake: 1 minute, 1 second ago
  transfer: 24.96 KiB received, 32.00 KiB sent

Last thing to do on the server is to configure iptables to NAT the outgoing traffic out of one of its interfaces (the one that is Internet facing in my case). And also activate routing.

$ sudo apt install iptables-persistent
$ sudo iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
$ sudo sysctl net.ipv4.ip_forward = 1
$ sudo echo "sysctl net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

On the client now we will set the configuration in /etc/wireguard/vpn0.conf

Address =
PrivateKey = client_private_key
PostUp = ip route replace default dev vpn0
PostUp = ip route add remote_server_ip via
PostDown = ip route replace default via
PostDown = ip route del remote_server_ip via # is my gateway

PublicKey = server_public_key
AllowedIPs =              # Allow all IPs to be routed through the tunnel
Endpoint = remote_server_ip:51820   
PersistentKeepalive = 25            # NAT and Firewall Traversal Persistence

Finally on the client we can enable the tunnel:

$ sudo wg-quick up vpn0

and all the traffic should now be routed through the tunnel and NATed on the server lets see what a traceroute towards looks like.

                                      My traceroute  [v0.87]
                                                         Packets               Pings
 Host                                                  Loss%   Snt   Last   Avg  Best  Wrst StDev
 1.                                       0.0%     7   12.0  11.0  10.2  12.0   0.6
 2. public_ip_of_my_server                              0.0%     6   12.2  11.1  10.5  12.2   0.4
 3. a_hop                                               0.0%     6   11.1  11.6  10.5  15.4   1.8
 4. another_hop                                         0.0%     6   22.3  16.0  10.8  25.9   6.4
 5. hop_hop                                             0.0%     6   11.5  12.6  11.1  18.1   2.7
 6. hip_hop                                             0.0%     6   12.5  24.9  11.5  89.3  31.6
 7. google-public-dns-a.google.com                      0.0%     6   11.6  12.0  11.2  13.7   0.6

I’ll polish a bit this blog-post over-time. It’s a bit rough for now… Comments are welcome by email