In the never ending hunt for the ideal VPN software we recently got to play with WireGuard, which has become a quick favourite. This text will serve as a quick-start guide for setting up a OpenVPN-esque default gateway server and a roaming client.
WireGuard offers some extremely powerful features that set it apart from the competition:
After installing WireGuard, it is necessary to generate keys on both hosts.
$ umask 077 && mkdir -p /etc/wireguard && cd /etc/wireguard $ wg genkey | tee privatekey | wg pubkey > publickey
Next the server needs a configuration file, we will set the listening port to
51820 and allow the client to connect from any IP address. Replace SERVER_PRIVATE_KEY with the servers previously generated key and CLIENT_PUBLIC_KEY with the clients public key, both are base64 encoded strings.
[Interface] ListenPort = 51820 PrivateKey = SERVER_PRIVATE_KEY [Peer] PublicKey = CLIENT_PUBLIC_KEY AllowedIPs = 0.0.0.0/0
Now that we have a configuration we need to set up the interfaces and ensure the server can route the clients with an
iptables NAT rule. Do not forget to make this rule persistent across reboots. The internal network will be set to
10.13.0.0/24 and the server will have an internal IP of
10.13.0.1, and should be changed to suite the needs of the network.
# ip link add dev wg0 type wireguard # ip address add dev wg0 10.13.0.1/24 # ip link set wg0 up # wg setconf wg0 /etc/wireguard/wg0.conf # iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # sysctl net.ipv4.ip_forward = 1 # printf "sysctl net.ipv4.ip_forward = 1\n" >> /etc/sysctl.conf
The client is configured in a very similar manner as the server, but it needs to know the IP of the server. Setting the
PersistentKeepalive is optional, but WireGuard is purposefully as silent in its default configuration and if a client is idle on a NAT the connection may be interrupted. This option prevents that by sending a keep alive every declared seconds. Replace CLIENT_PRIVATE_KEY with the clients previously generated key and SERVER_PUBLIC_KEY with the servers public key.
[Interface] ListenPort = 51820 PrivateKey = CLIENT_PRIVATE_KEY [Peer] PublicKey = SERVER_PUBLIC_KEY AllowedIPs = 0.0.0.0/0 Endpoint = 198.51.100.67:51820 PersistentKeepalive = 25
Now we initialize the interfaces and set the configuration. The client in this example will have an internal IP of
10.13.0.100 on the same subnet as declared on the server.
# ip link add dev wg0 type wireguard # ip address add dev wg0 10.13.0.100/24 # ip link set wg0 up # wg setconf wg0 /etc/wireguard/wg0.conf
Finally, the client needs to set its default routes (or which ever routes that are necessary) to the server. This requires knowing the original gateway and the IP of the server, in this example the gateway is
192.168.1.1 and the server IP is
# ip route add 198.51.100.67 via 192.168.1.1 # ip route del default # ip route add default dev wg0
NOTE: It is important understand that this configuration does will leak DNS requests if the original DHCP acquired DNS server is still routable. To prevent this set a
/etc/resolv.conf to an internal VPN host or to a trusted DNS server elsewhere. There is also the problem of default routes being changed when reconnecting to a wireless network, so there is some manual configuration that may need to be done.
After the server and client are set up the configuration and status can be checked with the
wg(8) utility, if everything was configured properly an example of output on the server would look like the following.
# wg interface: wg0 public key: jHhuAqsPKZC25/zjQ9G+1JEGO2FglLxqq4t8gWWW73U= private key: (hidden) listening port: 51820 peer: f2LdqRAog0FfdCbdZLkGKdJfPBkwrSt8XKl1kG8N2Vg= endpoint: 203.0.113.161:4135 allowed ips: 0.0.0.0/0 latest handshake: 8 seconds ago transfer: 4.40 MiB received, 322.38 MiB sent
The final step is adding the configuration to the default network configuration so that it starts at reboot. This step may be different depending on what distribution of Linux being used, this example will be using
/etc/network/interfaces on the server.
auto wg0 iface wg0 inet static pre-up ip link add dev wg0 type wireguard post-up wg setconf wg0 /etc/wireguard/wg0.conf post-up ip link set dev wg0 up address 10.13.0.1 netmask 255.255.255.0
If everything is routing properly just check the external IP matches the server, if not
traceroute can help debug any potential issues.