wireguard is a modern, secure and fast vpn tunnel that is extremely simple to setup and works already nearly everywhere.
Since I spent a little bet to play with it because this looked quite interesting, I thought of writing a small tutorial.
I normally use Gentoo (and macos) so this guide is about Gentoo.
General concepts
Wireguard sets up peers identified by an public key and manages a virtual network interface and the routing across them (optionally).
The server is just a peer that knows about loots of peers while a client knows how to directly reach the server and that’s it.
Setting up in Gentoo
Wireguard on Linux is implemented as a kernel module.
So in general you have to build the module and the userspace tools (wg
).
If you want to have some advanced feature make sure that your kernel has the following settings:
IP_ADVANCED_ROUTER
IP_MULTIPLE_TABLES
NETFILTER_XT_MARK
After that using emerge
will get you all you need:
$ emerge wireguard
Tools
The default distribution of tools come with the wg
command and an helper script called wg-quick
that makes easier to bring up and down the virtual network interface.
wg help Usage: wg <cmd> [<args>] Available subcommands: show: Shows the current configuration and device information showconf: Shows the current configuration of a given WireGuard interface, for use with `setconf' set: Change the current configuration, add peers, remove peers, or change peers setconf: Applies a configuration file to a WireGuard interface addconf: Appends a configuration file to a WireGuard interface genkey: Generates a new private key and writes it to stdout genpsk: Generates a new preshared key and writes it to stdout pubkey: Reads a private key from stdin and writes a public key to stdout You may pass `--help' to any of these subcommands to view usage.
Usage: wg-quick [ up | down | save | strip ] [ CONFIG_FILE | INTERFACE ] CONFIG_FILE is a configuration file, whose filename is the interface name followed by `.conf'. Otherwise, INTERFACE is an interface name, with configuration found at /etc/wireguard/INTERFACE.conf. It is to be readable by wg(8)'s `setconf' sub-command, with the exception of the following additions to the [Interface] section, which are handled by wg-quick: - Address: may be specified one or more times and contains one or more IP addresses (with an optional CIDR mask) to be set for the interface. - DNS: an optional DNS server to use while the device is up. - MTU: an optional MTU for the interface; if unspecified, auto-calculated. - Table: an optional routing table to which routes will be added; if unspecified or `auto', the default table is used. If `off', no routes are added. - PreUp, PostUp, PreDown, PostDown: script snippets which will be executed by bash(1) at the corresponding phases of the link, most commonly used to configure DNS. The string `%i' is expanded to INTERFACE. - SaveConfig: if set to `true', the configuration is saved from the current state of the interface upon shutdown. See wg-quick(8) for more info and examples.
Creating a configuration
Wireguard is quite straightforward, you can either prepare a configuration with your favourite text editor or generate one by setting by hand the virtual network device and then saving the result wg showconf
presents.
A configuration file then can be augmented with wg-quick
-specific options (such as Address
) or just passed to wg setconf
while the other networking details are managed by your usual tools (e.g. ip).
Create your keys
The first step is to create the public-private key pair that identifies your peer.
wg genkey
generates a private key for you.- You feed it to
wg pubkey
to have your public key.
In a single line:
$ wg genkey | tee privkey | wg pubkey > pubkey
Prepare a configuration file
Both wg-quick
and wg setconf
use an ini-like configuration file.
If you put it in /etc/wireguard/${ifname}.conf
then wg-quick
would just need the interface name and would look it up for you.
The minimum configuration needs an [Interface]
and a [Peer]
set.
You may add additional peers later.
A server would specify its ListenPort
and identify the peers by their PublicKey
.
[Interface] Address = 192.168.2.1/24 ListenPort = 51820 PrivateKey = <key> [Peer] PublicKey = <key> AllowedIPs = 192.168.2.2/32
A client would have a peer with an EndPoint
defined and optionally not specify the ListenPort
in its interface description.
[Interface] PrivateKey = <key> Address = 192.168.2.2/24 [Peer] PublicKey = <key> AllowedIPs = 192.168.2.0/24 Endpoint = <ip>:<port>
The AllowedIPs
mask let you specify how much you want to route over the vpn.
By setting 0.0.0.0/0
you tell you want to route ALL the traffic through it.
NOTE:
Address
is awg-quick
-specific option.
Using a configuration
wg-quick
is really simple to use, assuming you have created /etc/wireguard/wg0.conf
:
$ wg-quick up wg0
$ wg-quick down wg0
If you are using netifrc from version 0.6.1
wireguard is supported and you can have a configuration such as:
config_wg0="192.168.2.4/24" wireguard_wg0="/etc/wireguard/wg0.conf"
With the wg0.conf
file like the above but stripped of the wg-quick
-specific options.
Summing up
Wireguard is a breeze to set up compared to nearly all the other vpn solutions.
Non-linux systems can currently use a go implementation and in the future a rust implementation (help welcome).
Android and macos have already some pretty front-ends that make the setup easy even on those platforms.
I hope you enjoyed it 🙂