path: root/src/wg.4
blob: 6750d934b3f7f5de083f4a68492da6537ad8ecc3 (plain) (tree)


















.\" Copyright?
.Dd $Mdocdate: April 22 2019 $
.Dt WG 4
.Nm wg
.Nd WireGuard pseudo-device
.Cd "pseudo-device wg"
.Nm wg
driver provides simple Virtual Private Network (VPN) interfaces for
securely communicating with other WireGuard endpoints.
.Nm wg
interfaces implement the WireGuard protocol, heavily relying on the
Noise protocol framework.
Each interface is able to connect to a number of endpoints, relying on
an internal routing table to direct outgoing IP traffic to the correct
endpoint.  Incoming traffic is also matched against this routing table
and dropped if endpoint does not match the corresponding output route.
The interfaces can be created at runtime using the
.Ic ifconfig wg Ns Ar N Ic create
command or by setting up a
.Xr hostname.if 5
configuration file for
.Xr netstart 8 .
The interface itself can be configured with
.Xr ifconfig 8 ;
see its manual page for more information.
Support is also available in the
.Nm wireguard-tools
package by using the
.Xr wg 8
.Xr wg-quick 8
.Nm wg
interfaces support the following
.Xr ioctl 2 Ns s :
.Bl -tag -width indent -offset 3n
.It Dv SIOCGWGSERV Fa "struct wg_get_serv *"
Get the currently configured device parameters. This includes the
configured key, port and the number of peers and peer public keys.
.It Dv SIOCGWGPEER Fa "struct wg_get_peer *"
Get a specific peer's status. The pubkey is required to be set and if it
doesn't exist, the call will return ENOENT.
.It Dv SIOCSWGSERVPORT Fa "struct wg_set_serv *"
Set device listen port.
.It Dv SIOCSWGSERVKEY Fa "struct wg_set_serv *"
Set device private key.
.It Dv SIOCCWGPEERS Fa "struct wg_set_serv *"
Clear all peers from device.
.It Dv SIOCSWGPEERIP Fa "struct wg_set_peer *"
Set peer IP endpoint.
.It Dv SIOCSWGPEERAIP Fa "struct wg_set_peer *"
Add allowed IP to peer.
.It Dv SIOCSWGPEERPSK Fa "struct wg_set_peer *"
Set peer preshared key.
.It Dv SIOCSWGPEERPKA Fa "struct wg_set_peer *"
Set peer persistent keepalive timeout.
.It Dv SIOCDWGPEER Fa "struct wg_set_peer *"
Delete peer.
.It Dv SIOCDWGPEERAIP Fa "struct wg_set_peer *"
Delete allowed IP from peer.
.It Dv SIOCCWGPEERAIP Fa "struct wg_set_peer *"
Clear all allowed IPs from peer.
WireGuard is designed as a small, easy to use VPN. Some features may be
foreign to new users, however the concepts are not difficult.

The following items highlight the purpose of WireGuard specific features:
.Bl -tag -width indent -offset 3n
.It Peer
A peer is a host that the interface creates a connection with. It is
identified by a 32 byte public key. There is no concept of client/server
as both ends of the connection are equal. An interface may have multiple
.It Allowed-IPs
Allowed-IPs dictate which IP addresses each peer is responsible for.
Thus, they form a routing table for outgoing packets and are necessary
to have multple peers per interface. Incoming packets are also matched
against this routing table, to verify they originate from the correct
.It Handshake
In order to establish a set of shared secret keys, two peers perform a
handshake. This occurs every 2 minutes while traffic is being sent. If
no traffic is being sent, then no handshake occurs. When traffic
resumes, a new handshake is performed. Each handshake generates a new
set of ephemeral keys to provide forward secrecy.
.It Connection
Due to the handshake behavior, there is no connected/disconnected state.
Thus WireGuard is considered "connection-less".
.It Key
Each interface has a static private key. This key is used to perform
Curve25519 operations which is an asymmetric crypto algorithm.
The corresponding public key is used
to identify the local interface to other peers. The key is used in the
.It Preshared-Key
In addition to the Curve25519 interface keys, each peer can have a
unique static preshared key. The preshared key is also used in the
handshake in order to mitigate the post-quantum weakness of Curve25519.
The forward secrecy property of the handshake is defeated in a
post-quantum world without a preshared key.
A peer with no set preshared key will just use an empty, all 0's key.
Keys for WireGuard can be generated from any sufficient secure random
source. The Curve25519 keys and preshared keys are both 32 bytes long
and are commonly encoded in base64 for ease of use.
Keys can be generated with
.Xr openssl 1
as such:
.Dl $ openssl rand -base64 32
It should be noted that not all 32 byte strings are valid Curve25519
keys. The key must be an element of a finite set, which is achieved by
setting specific bits in the string. The interface will perform this for
you, so you may just pass a 32 byte random string. This does not apply
to the preshared key.
It goes without saying that these keys must be kept private. Also, the
root user is able to retrieve these keys from a running interface.
When an interface has a private key set with
.Nm wgkey ,
the corresponding
public key is shown in the status output of the interface, like so:
.Bd -literal -offset indent
wgkey (pub) NW5l2q2MArV5ZXpVXSZwBOyqhohOf8ImDgUB+jPtJps=
.Xr ifconfig 8
supports a number of directives, (*) indicates wgpeer must be set:
.Bl -tag -width indent -offset 3n
.It Dv wgkey - set interface private key
.It Dv wgport - set interface listen port
.It Dv wgpeer - select peer
.It Dv *wgpsk - set peer preshared key
.It Dv *wgaip - set peer allowed ip
.It Dv *wgpip - set peer endpoint ip
.It Dv *wgpka - set peer persistent keepalive

The following script will create two
.Nm wg
interfaces in separate
.Xr rdomain 4
.Bd -literal -offset indent

KEY1="`openssl rand -base64 32`"
KEY2="`openssl rand -base64 32`"

ifconfig wg1 create
ifconfig wg1 wgport 11111 wgkey $KEY1 rdomain 1

ifconfig wg2 create
ifconfig wg2 wgport 22222 wgkey $KEY2 rdomain 2

PUB1="`ifconfig wg1 | grep 'wgkey (pub)' | cut -d ' ' -f 3`"
PUB2="`ifconfig wg2 | grep 'wgkey (pub)' | cut -d ' ' -f 3`"

ifconfig wg1 wgpeer $PUB2 wgpip 22222 wgaip
ifconfig wg2 wgpeer $PUB1 wgpip 11111 wgaip
ifconfig wg1
ifconfig wg2
The two interfaces are able to communicate over the UDP tunnel which
resides in
.Xr rdomain 4
by default. This example carries no practical use apart from
demonstrating two interfaces on the same machine.
The most common use-case is to connect two separate hosts over a
network. Keys must be generated and distributed manually over a secure
channel such as
.Xr ssh 1
or out-of-band. A regular
.Xr hostname.if 5
file can be used to configure the interface. The following values are an
example. It goes without saying that you should generate your own unique
.Bd -literal -offset indent
wgport 3689
wgkey KmDUgApHqim36Iqwyph6SE90GIZx0Hq38mz1m8kpWfg=

wgpeer xY28FIHnumyD5ZNksGscYOD23PX27e9niZsP4gh6kBc= wgpsk
wgpeer xY28FIHnumyD5ZNksGscYOD23PX27e9niZsP4gh6kBc= wgaip
wgpeer xY28FIHnumyD5ZNksGscYOD23PX27e9niZsP4gh6kBc= wgaip fc01::/16
wgpeer xY28FIHnumyD5ZNksGscYOD23PX27e9niZsP4gh6kBc= wgpip peer 9863

inet6 fc01::1/16

.Xr inet 4 ,
.Xr ip 4 ,
.Xr netintro 4 ,
.Xr hostname.if 5 ,
.Xr pf.conf 5 ,
.Xr ifconfig 8 ,
.Xr netstart 8 ,
.Xr wg 8 ,
.Xr wg-quick 8
.%T WireGuard whitepaper
.An Matt Dunwoodie <> .
Due to queuing in the kernel, in order to reduce packet loss, the
following command may be necessary to achieve good performance.
.Dl # sysctl