WireGuard

From Gentoo Wiki
Jump to:navigation Jump to:search
This page contains changes which are not marked for translation.


WireGuard is a modern, simple, and secure VPN that utilizes state-of-the-art cryptography. Considered an alternative to OpenVPN, it can be used to create secure connections. Its goals are to be fast, simple, lean, and easy to configure. Wireguard consists of two components: userspace tools and a kernel module.

Wireguard is written and maintained by Jason A. Donenfeld (zx2c4) , a Gentoo developer.

Official and potentially more up-to-date installation instructions can be found upstream.

Installation

Kernel

Starting with Linux kernel 5.6, Wireguard is included in the upstream kernel sources. It is enabled via the following menuconfig option:

KERNEL Enable CONFIG_WIREGUARD
Device Drivers  --->
    [*] Network device support  --->
        [*] Network core driver support
        <*>   WireGuard secure network tunnel

USE flags

USE flags for net-vpn/wireguard-tools Required tools for WireGuard, such as wg(8) and wg-quick(8)

+wg-quick Install the wg-quick(8) helper tool. Most users want to use this.
selinux !!internal use only!! Security Enhanced Linux support, this must be set by the selinux profile or breakage will occur

Emerge

Install the wireguard-tools package to generate encryption keys and manage Wireguard interfaces:

root #emerge --ask net-vpn/wireguard-tools

Configuration

Kernel module loading

Note
If wireguard support is added to the kernel as a module, configuring a wireguard interface should load the wireguard kernel module automatically, so there may be no need to set it to load in /etc/modules-load.d/.

If WireGuard support has been added as a module, it may be necessary to instruct the selected init system to load the WireGuard kernel modules when the system boots.

Create a new file in the /etc/modules-load.d/ directory in order to instruct the module loading service to get the module loaded on boot:

FILE /etc/modules-load.d/wireguard.conf
wireguard

Or if VPN access is not needed very often, load kernel module manually:

root #modprobe wireguard

Loaded modules can be reviewed with lsmod.

Files

wg.conf

A WireGuard configuration file (the first of which is normally named wg0.conf) can be written as outlined in the man page. Review the CONFIGURATION FILE FORMAT and CONFIGURATION FILE FORMAT EXAMPLE sections in man 8 wg:

user $man 8 wg

As mentioned in the man page, WireGuard configuration files are defined in the INI format. A typical configuration file looks something like the following:

FILE wg0.confWireguard configuration file example
[Interface]
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
Endpoint = 192.95.5.67:1234
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24

[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
Endpoint = [2607:5300:60:6b0::c05f:543]:2468
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16

[Peer]
PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
Endpoint = test.wireguard.com:18981
AllowedIPs = 10.10.10.230/32

Usage

Generate a keypair

Before using WireGuard a keypair has to be generated. This can be accomplished using wg(8):

user $$(umask 077; wg genkey | tee privatekey | wg pubkey > publickey)

Network management methods

Various network management methods are available to supervise Wireguard tunnels.

wg-quick

Configuration can be automated using the wg-quick utility, which will create tunnels using configuration files in the /etc/wireguard file:

root #wg-quick up wg0

For more information on wg-quick consult man 8 wg-quick.

The net-misc/netifrc scripts (typically used with OpenRC) can be used to quickly bring Wireguard interfaces. Presuming a correctly defined /etc/wireguard/wg0.conf file has been created:

root #ln -s /etc/init.d/wg-quick /etc/init.d/wg-quick.wg0
root #rc-update add wg-quick.wg0 default

To bring up the interface now:

root #/etc/init.d/wg-quick.wg0 start


Warning
Deleting
root #ip link del wg0

or bringing down

root #ip link set wg0 down
the WireGuard interface will *NOT* stop packets routed to the WireGuard interface; packets will instead be routed normally through other interfaces!

netifrc

This implementation of WireGuard uses the same logic as wg-quick, but putting the logic directly in /etc/conf.d/net for netifrc.


Using the wg-quick USE flag will add virtual/resolvconf as a dependency. This might be a deal-breaker for systems that want to keep the resolv.conf file from being modified by external utilities. Luckily, this implementation does not use such dependencies; it's okay to add the -wg-quick USE flag to net-vpn/wireguard-tools.

FILE /etc/portage/package.use/wireguard
net-vpn/wireguard-tools -wg-quick


Copy the following netifrc configuration file to /etc/conf.d/net and edit the interfaces as needed to work with the machine:

root #cat /etc/conf.d/net

Remove any wg-quick extensions in /etc/wireguard/wg0.conf as they will not be recognized by wg (the tool that netifrc uses). Read the man page for wg to know what is syntactically correct. In short, remove the following lines in the configuration file if they exist:

CODE Lines to remove
Address = ...
MTU = ...
DNS = ...
Table = ...
PreUp = ...
PreDown = ...
PostUp = ...
PostDown = ...
SaveConfig = ...

The contents of Address = should go into config_wg0=. The contents of DNS = should go into dns_servers_wg0=.


Important
In order for this implementation to work, a firewall mark *MUST* be set in the WireGuard configuration file!
CODE
FwMark = 334455
If a firewall mark is not set, packets will not be routed to the WireGuard interface!


Once the WireGuard and netifrc configuration files are done, we are ready to use them. To bring up the WireGuard interface, make the symlink for wg0 and start it just like any other physical interface:

root #ln -s /etc/init.d/net.lo /etc/init.d/net.wg0
root #rc-service net.wg0 start

To have WireGuard start at system boot:

root #rc-update add net.wg0 default


Warning
Deleting
root #ip link del wg0

or bringing down

root #ip link set wg0 down
the WireGuard interface will *NOT* stop packets routed to the WireGuard interface; packets will instead be routed normally through other interfaces!

Network Namespaces

This implementation of WireGuard uses network namespaces, which are isolated networks that can be assigned interfaces. The benefit of doing this instead of changing firewall rules is that it's more clear that all or specified packets will go through a WireGuard interface even if the WireGuard interface goes down or gets deleted.

TL;DR:

To bring up a WireGuard interface (simplified):

  • Make a new network namespace, "physical"
  • Make a new WireGuard interface, "wg0", in network namespace "physical"
  • Move "wg0" from network namespace "physical" to "init"/"1"
  • Move all interfaces that can connect to the internet in network namespace "init"/"1" to "physical"


To bring down a WireGuard interface (simplified):

  • Move all interfaces that can connect to the internet in network namespace "physical" to "init"/"1"
  • Delete "wg0"
  • Delete "physical"


To bring up a WireGuard interface, we make a new network namespace with some name like, "physical"; then, we make a new WireGuard interface with the name "wg0" in the "physical" namespace then move it to the "init"/"1" namespace (the namespace that all interfaces start in). Then, move all interfaces that can connect to the internet to the "physical" interface. To bring down a WireGuard interface, we move all the interfaces that we previously moved to "physical" back to "init"/"1". Then, we delete the "wg0" WireGuard interface and the "physical" network namespace since we're not using them anymore. This is a simplified explanation, there are other steps that happen in between, such as routing packets to the WireGuard interface, but this is the biggest difference compared to other implementations.

This implementation also has the benefit of giving the user the ability to allow specified applications to temporarily bypass the WireGuard interface. For example, let's say we're using public WiFi at a hotel, shop, airport, etc. and we want to route all our packets through WireGuard to our home network. Everything works fine except when the hotel requires users to authenticate themselves through a web portal before they actually give us a connection to the internet.

Before, we would have to bring down the WireGuard interface, authenticate ourselves through the portal via our browser of choice (such as LibreWolf), then bring up the WireGuard interface again. In the time when the WireGuard interface was down, other running applications with network capabilities might connect to the internet. This can be a serious security, privacy, and anonymity concern if we really don't want anyone else to know what our machine is trying to connect to.

With network namespaces, we can handle the situation without ever bringing down the WireGuard interface. When WireGuard is set up using network namespaces, the only interface running applications can see/use is the WireGuard interface. All the interfaces that actually connect to the internet are in a different namespace and cannot be directly seen/used unless we give an application the ability to do so. We can do this by prefixing the command to run the application with another that temporarily bypasses the WireGuard interface until we close the application.

Setup

Normally we move interfaces with the ip command provided by sys-apps/iproute2, but for wireless ones, we need to use the iw command provided by net-wireless/iw. If our machine has wireless interfaces, such as a laptop, we need to install iw.

root #emerge --ask net-wireless/iw

Using the wg-quick USE flag will add virtual/resolvconf as a dependency. This might be a deal-breaker for systems that want to keep the resolv.conf file from being modified by external utilities. Luckily, this implementation does not use such dependencies; it's okay to add the -wg-quick USE flag to net-vpn/wireguard-tools.

FILE /etc/portage/package.use/wireguard
net-vpn/wireguard-tools -wg-quick


Now, this implementation involves copy-pasting a WireGuard configuration file, some scripts, and optionally setting up a cron job for automated starting of the WireGuard interface.

Note
At the time of making this namespace solution, OpenRC seems to have several bugs related to namespaces, even though OpenRC supports network namespaces via netns in /etc/conf.d/net. Testing has shown that
  • interfaces are not reliably placed when they are given a specified network namespace (netns_eth0="physical") even when the namespace exists.
  • services that depend on said interface ( depend() { need net; } ) start in the specified namespace when they shouldn't.


This is why we use a cron job to automate the starting of WireGuard instead of using an OpenRC Service Script.

Make the directory for WireGuard configuration files:

root #mkdir -p /etc/wireguard

Set the correct permissions because this directory can contain keys:

root #chmod 700 /etc/wireguard

Copy the following WireGuard configuration file to /etc/wireguard/wg0.conf:

root #cat /etc/wireguard/wg0.conf

(Optional) Set the correct permissions for the file; this is not required because we already set the permissions for the directory this file sits in:

root #chmod 600 /etc/wireguard/wg0.conf

Copy the following scripts into /usr/local/bin so that they can be found by the PATH environment variable:

root #cat /usr/local/bin/wg-netns
root #cat /usr/local/bin/wg-bypass

Set the correct permissions so that we can execute the files:

root #chmod 755 /usr/local/bin/{wg-netns,wg-bypass}
Configuration

Now that we have all the files we need, we can begin using our custom values. We are mainly going to be modifying the wg0.conf file, but the wg-netns file can be edited too if needed. Regardless, each file contains comments that should explain why it does the things it does.


In the wg0.conf file, the only variables that need to be modified are:

  • PrivateKey
  • Address
  • PublicKey
  • PresharedKey (if used)
  • AllowedIPs (if we don't want to route all packets)
  • Endpoint

Everything else is either optional or already has a default value.

Note

  • Some variables in wg0.conf can be modified in wg-netns to act as global defaults, but take note of which ones append data and which ones override data.
  • To avoid confusion with variables that don't need commas and ones that do, we use commas for all variables.
FILE wg0.confExample configuration
[Interface]
PrivateKey = ecoetnhuastn0620757ostnhoausho
Address = 123.123.123.123/32, a::cee:25/128, 222::666/128
MTU = 1420
DNS =
Namespace = physical
PhysicalInterface = eth0, wlan0, wlan1
ExtraServiceYes = uwsgi.searxng, nginx.myotherwebsite
ExtraServiceNo = nginx.mycoolwebsite

[Peer]
PublicKey = 0624204euoeu24424042thaoestuhuoeauh
PresharedKey = oesutuh75757557tnuhoeasuthoeuseohu
AllowedIPs = 10.0.20.0/24, 5555::/64
Endpoint = my.dynamicdns.org:55333
PersistentKeepAlive = 25

[Peer]
PublicKey = hhhhhhuhetuheteu062000206020620
PresharedKey = 75357375thhthuteohuonuheoutoehuo
AllowedIPs = 11.55.222.0/24, 1234::/64
Endpoint = 173.10.3.5:61199

The wg0.conf file is basically a normal WireGuard configuration file with extra features.


Users that have PAM enabled on their system might need to modify their PAM configuration file for OpenRC. By default, PAM will require authentication for each OpenRC command (even if the user is root). The wg-netns has multiple rc- commands in it; if PAM fails, the script will fail. To fix this, edit the /etc/pam.d/run_init file and add the line:

CODE
auth sufficient pam_rootok.so

There should already be a message in this file with this exact line commented-out; simply uncomment the line, save, and exit. This change will make it so that we don't need to authenticate ourselves to PAM when we run an OpenRC command as root (being root is already enough).


Once we are done editing our wg0.conf file, we can bring up the WireGuard interface by running:

root #wg-netns up wg0

And bring it down by running:

root #wg-netns down wg0

We can check the status of the "init"/"1" namespace by running:

user $ip address

And the status of a specific namespace with:

root #ip -n physical address

To have an application bypass the WireGuard interface (such as LibreWolf):

user $wg-bypass librewolf

In this case, LibreWolf will not use the WireGuard interface until it closes and starts without wg-bypass.

(Optional) Cron job

To automatically start the WireGuard interface at system boot, we can set up a cron job to execute wg-netns. We will be using Fcron (sys-process/fcron) as our cron daemon.

Important
If using a different cron daemon, ensure that the command only runs once!

Open the system crontab using fcrontab:

root #fcrontab -u systab -e

Add the following line:

CODE
@runatreboot(true),runonce(true) 1 /usr/local/bin/wg-netns up wg0

Once we save and exit, the output should look similar to the following:

root #fcrontab -u systab -e
0000-00-00 00:00:00 INFO fcrontab: editing systab's fcrontab
Modifications will be taken into account right now.
Important
If using SELinux, the contexts of some fcron files might need to be fixed; run the following command to fix them:
root #restorecon -r /var/spool/fcron

NetworkManager

Wireguard is officially supported by NetworkManager as of version 1.16[1]. Managing WireGuard is possible through the nmcli and nmtui commands. Review the latest documentation upstream for the extensive list of key-value properties.

Important

  • NetworkManager requires runtime dependencies (command-line interface tools) from the net-vpn/wireguard-tools package in order to manage connection profiles. Be sure this package has been installed before attempting to use nmcli command.
  • In order for non-root users to edit network connections, each user must be added to the plugdev group.

After creating a WireGuard configuration file (such as wg0.conf), the file can be imported into NetworkManager as a connection profile:

user $nmcli connection import type wireguard file /path/to/wg0.conf

After the configuration has been imported, the connection can be activated via:

user $nmcli connection up wg0

After adding a new connection, restart the interface by bringing it down, then back up up in a single command. Using the single command avoids disruption when working over the VPN connection itself:

user $nmcli connection down wg0 && nmcli connection up wg0

See the NetworkManager article for more details on managing connection profiles.

Removal

Unmerge

To find Wireguard-related packages:

root #emerge --ask --search wireguard

To remove the userspace tools:

root #emerge --ask --depclean --verbose net-vpn/wireguard-tools

Troubleshooting

Rebuilding modules on kernel upgrades for kernels less than 5.6

When upgrading to a newer kernel that is less than version 5.6 (version 4.9.x LTS is a fitting example), it is important to re-emerge the Wireguard kernel modules. This is handled by default when using genkernel, but can be quickly performed using the following auto-generated Portage set:

root #emerge --ask @module-rebuild

See also

  • OpenVPN — software that enables the creation of secure point-to-point or site-to-site connections.
  • vpnc — IPsec (Cisco/Juniper) VPN concentrator client

External resources

References