summaryrefslogtreecommitdiff
path: root/docs/sysadmin/networking/wireguard.md
blob: 7301d87bf5c089be338d8f14dd3f38a63323c5b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# WireGuard

WireGuard is a L3 connection-less tunnel protocol, based on UDP.

* After a 1-RTT handshale, packets will be encrypted and transmitted in
WireGuard Transport Data messages. No additional messages needed.
* The transport data message takes 16Bytes, the UDP header takes 8, and the
IP header takes 20 (or 40 for IPv6), leaving MTU = 1440 or 1420 (IPv6).
* No server / client distinction. Peers are identified via public keys.
* Peers may roam to whatever IP they want as long as they handshake with the
same public key.
* Only one side of the tunnel needs a public IP address.
* Multiple peers per interface possible, with crypto-based internal routing and
allowed IPs filter.

For the Linux implementation:

* WireGuard interfaces are just represented as Linux virtual interfaces, and
they can be managed using iproute2 and wg(1).
* Has very well support for network namespaces.
* Do not work well with vrf.
* Could be hard to debug.

## Basic Operation

Setup the interface and address with ordinary Linux network management tools,
e.g. iproute2:

```shell
$ ip l add dev wg0 type wireguard
$ ip l set dev wg0 up
$ ip a add dev wg0 ...
```

Set WireGuard-specific options using `wg(1)`:

```
$ wg
$ wg set nic listen-port uint16_t
$ wg set nic private-key /path/to/private-key
$ wg set peer public-key preshared-key /path/to/preshared-key
$ wg set peer public-key endpoint ip:port
$ wg set peer public-key persistent-keepalive intervals
$ wg set peer public-key allowed-ips ip/cidr
$ wg set peer public-key remove
```

## Crypto Routing and Allowed IPs

Give a WireGuard NIC a block of IP address, and specify allowed ranges of each
peer. Packets will be routed to peers based on allowed IPs. This does not go
through system routing table.

TODO

## Network Namespace

WireGuard will continue to listen on the originating network namespace after it
is moved to new namespaces. That is, for example, you want WireGuard to bind to
an Ethernet interface, but you want to route packets in a netns from / to the
WireGuard interface, but that Ethernet interface is not in the netns. You can
just create the WireGuard interface in the netns that has the Ethernet NIC, and
use `ip l set dev NIC netns NETNS` to move that into the specific netns.

See [wireguard.com/netns](https://www.wireguard.com/netns/).

## fwmark

TODO

## wg-quick(1)

A bash script that takes the input configuration file and automatically invokes
ip-link(1), ip-addr(1), wg(1), ip-route(1), and resolvconf(1). It is a oneshot
script: it will exit after applying the configuration.

It doesn't support network namespaces. You can do ip-link(1) yourself and patch
wg-quick(1) to ignore creating the WireGuard interface.

Sample configuration:

```
# /path/to/wg0.conf
[Interface]
Address =
PrivateKey = private-key
ListenPort = port
# Table = off
# DNS =

[Peer]
PublicKey = public-key
AllowedIPs = cidr, cidr, cidr
PersistentKeepalive =
Endpoint = ip:port
```

Note that when using its systemd service, the file has to exist when stopping
the service, otherwise the stop command will fail and you have to clear the
failed unit yourself.

## Debugging

Could be hard though. Good luck with tcpdump(1).

For kernel module debug logs:

```shell
$ modprobe wireguard 
$ echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
```