Projet

Général

Profil

Openbsd wireguard rdomain » Historique » Version 1

sacha, 11/11/2020 21:48

1 1 sacha
---
2
Title: Setting up a WireGuard® client with routing domains on OpenBSD
3
langs: en
4
Breaks: False
5
---
6
# Setting up a WireGuard® client with routing domains on OpenBSD
7
8
_Matthieu Herrb - last edited october 24, 2020._
9
10
OpenBSD-current recently got native support for the [Wireguard®](https://wireguard.com/) VPN, thanks to the work of Matt Dunwoodie and Jason A. Donefeld. Their code was merged by David Gwynne.
11
This is great, especially since I've been using WireGuard for various purposes already.
12
A local assocative ISP here in Toulouse is offering WireGuard based VPNs for 5€/month.
13
In this note, I'm going to show how to setup a machine running OpenBSD to connect to this kind of VPN, using routing domains to make the VPN the default interface.
14
15
This configuration can be used to get a fixed public IPv4 and IPv6 address for a self-hosted server to run any kind of internet services.
16
17
## General principle
18
19
The client machine is going to connect to the internet via any kind of LAN that provides IPv4 DHCP auto-configuration.
20
It can be an ADSL or fiber modem at home or some enterprise network.
21
The only serious requirement is that UDP traffic on the WireGuard (51820) port goes out.
22
This connexion is only going to be used to connect to the VPN, and will be setup in routing domain 1.
23
The Wireguard connexion is going to be the _egress_ connexion in the default routing domain (0).
24
25
In this setup there is no need to provide complicated routing or packet filter configuration.
26
All traffic will go through the VPN "naturally" as the default routing domain only knows about the VPN interface.
27
28
### Routing Domains and routing tables
29
30
For those not familiar with routing domains and tables on OpenBSD, it is recommended to read the [rdomain(4)](https://man.openbsd.org/rdomain.4) manual page.
31
Routing domains are separated network address spaces in the OpenBSD kernel.
32
Each routing domain has at least one routing table, separated from the routing tables of other domains.
33
Network interfaces belong to one domain and are not usable by the others.
34
Also, processes are running inside a routing domain, using by default the default routing table of their domain.
35
So their network traffic can only use the interfaces in this domain.
36
37
So routing domains and tables are a great way to isolate network trafic between processes.
38
39
### WireGuard® at Tetaneutral.net
40
41
The [Tetaneutral.net](https://www.tetaneutral.net/) non-profit ISP provides WireGuard based VPN connections with one fixed IPv4 address and a /56 IPv6 prefix.
42
When you subscribe to the service, you provide the public key for your end point, and Tetaneutral gives you back the assigned IP adresses and the IP address, port number and public key of the VPN endpoint.
43
44
It is likely that many other ISP providing WireGuard based VPNs will work approxymately the same as Tetaneutral, and thus this can be expaned easily.
45
You can even setup your own WireGuard VPN service using OpenBSD, but this is out of the scope of this note.
46
47
## Let's go !
48
49
### OpenBSD installation
50
51
OpenBSD is installed as usual on the machine, setting up the network connection for the network on which it is going to have its internet access.
52
In this example the __re0__ interface is going to be used for this. So with DHCP `/etc/hostname.re0` looks like:
53
54
    dhcp
55
56
### Obtaining VPN parameters
57
58
Install the `wireguard-tools` package, to have access to the [wg(8)](https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8) command:
59
60
    $ pkg_add wireguard-tools
61
62
Now the parameters for the VPN are needed. For this a private key will be generated using the following commands:
63
64
    $ umask 077
65
    $ wg genkey > /etc/wg0.key
66
67
The corresponding public key is displayed by the following command:
68
69
    $ wg pubkey < /etc/wg0.key
70
71
_Note:_ if you don't want to install the `wireguard-tool` package, the [wg(4)](https://man.openbsd.org/wg.4) manual page describes an alternate way to generate the private key and display the public key using tools in the base system.
72
73
To obtain the remaining of the parameters, contact the VPN provider and send them the public key shown above.
74
They should reply providing:
75
76
(the values below are fake examples)
77
78
- the IP and port number of their endpoint: `198.51.100.116 51820`
79
- the public key of their endpoint: `Qay+wLckmRMr08t/9psjhrltJ0T4xb0m8++gQj0FpEA=`
80
- the IPv4 and IPv6 prefix assigned to your endpoint: `203.0.113.3/32` and `2001:db8:8087:300::/56` respectively.
81
- the addresses of the DNS servers that can be used inside the VPN: `198.31.100.10` and `198.51.100.11`
82
83
Keep those informations somewhere, to use them later.
84
85
### Moving the default interface to rdomain 1
86
87
Now edit `/etc/hostname.re0` to add a `rdomain` directive to move this interface to rdomain 1:
88
89
    rdomain 1
90
    dhcp
91
92
That's it. If the machine is rebooted at this point, most processes won't have network access since only routing domain 1 has network access. So do not reboot for now.
93
94
### Creating the VPN interface
95
96
A __wg0__ interface for the VPN is going to be setup. For this create the `/etc/hostname.wg0` file, containing (using the fake information form the provider shown above):
97
98
    up
99
    wgkey <your wg private key>
100
    wgpeer Qay+wLckmRMr08t/9psjhrltJ0T4xb0m8++gQj0FpEA= wgrtable 1 wgendpoint 198.51.100.116 51820 wgaip 0.0.0.0/0 wgaip ::/0
101
    inet 203.0.113.3 255.255.255.255
102
    inet6  2001:db8:8087:300::1 56
103
    ! route add default -link -iface wg0
104
    ! route add -inet6 default -link -iface wg0
105
106
The last two lines set up the default route for rdomain 0 via the `wg0` interface.
107
108
Once `/etc/hostname.wg0` is created, the `/etc/wg0.key` file created previously can be removed.
109
It was only used to keep the private key while obtaining the remaining information needed to create `hostname.wg0`
110
111
### Setting up the DNS
112
113
There are different options to tell the VPN client which DNS resolvers to use.
114
The issue is that `/et/resolv.conf` still contains the adresses of the DNS servers on the LAN, provided by dhclient(8).
115
Generally when using a VPN you don't want to use those, because they will leak the domains that the users of the VPN are connecting to.
116
117
#### Simple forwarding
118
119
The simplest solution is to use the _supersede_ option of [`dhclient.conf(5)`](https://man.openbsd.org/dhclient.conf.5) to replace the DHCP provided servers by the ones provided by the VPN provider. This will be the contents of `/etc/dhclient.conf`:
120
121
    supersede domain-name-servers 198.51.100.10, 192.51.100.11;
122
123
#### Using unwind(8)
124
125
Another option is to set up [unwind(8)](https://man.openbsd.org/unwind.8), with an [`unwind.conf(5)`](https://man.openbsd.org/unwind.conf.5) configuration file specifying the VPN name servers as forwarders.
126
127
Add the DNS servers provided by the VPN provider in `/etc/unwind.conf` (see [`unwind.conf(5)`](https://man.openbsd.org/unwind.conf.5) for details):
128
129
    forwarder { 198.51.100.10 192.51.200.11 }
130
    
131
Activate unwind with
132
133
    rcctl enable unwind
134
    
135
And edit `/etc/dhclient.conf` to contain:
136
137
    prepend domain-name-servers 127.0.0.1 ;
138
    
139
This solution also allows processes in routing domain 1 to use the DNS servers provided by the DHCP server. 
140
141
### SSH access from the LAN
142
143
If you want to be able to continue accessing the machine from the lan it is connected to, `/etc/ssh/sshd_config` needs to be told to also listen to routing domain 1.
144
145
    ListenAddress 0.0.0.0 rdomain 0
146
    ListenAddress :: rdomain 0
147
148
    ListenAddress 0.0.0.0 rdomain 1
149
150
Otherwise, after reboot, the machine will only be accessible from the console and with SSH though the VPN.
151
152
### Rebooting
153
154
And that's it. The machine can now be rebooted.
155
All processes in the default routing domain (0) will only see the `lo0` and `wg0` interfaces, while the dhclient process needed to bring up `re0` will be in routing domain 1.
156
The `wgrtable` keyword in the wg0 interface configuration tells it ue use the routing table of routing domain 1 to reach the remote VPN endpoint.
157
158
## Checking that it works
159
160
After rebooting, let's review the setup by cheching the `wg0` interface:
161
162
    # ifconfig wg0
163
    wg0: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> mtu 1420
164
        index 6 priority 0 llprio 3
165
        wgport 47326
166
        wgrtable 1
167
        wgpubkey <public key>
168
        wgpeer Qay+wLckmRMr08t/9psjhrltJ0T4xb0m8++gQj0FpEA=
169
                wgendpoint 198.51.100.116 51820
170
                tx: 45564, rx: 71200
171
                last handshake: 107 seconds ago
172
                wgaip ::/0
173
                wgaip 0.0.0.0/0
174
        groups: wg egress
175
        inet  203.0.113.3 netmask 0xffffffff
176
        inet6 2001:db8:8087:300::1 prefixlen 56
177
178
And the default routes:
179
180
    # route -n show  | grep default
181
    default            link#6             ULS        5      229     -     8 wg0  
182
    default                            link#6                         ULS        0        4     -     8 wg0
183
184
You can test that all traffic will go through the VPN using [traceroute(8)](https://man.openbsd.org/traceroute.8).
185
The machine is reachable from the internet using both its public IPv4 and IPv6 addresses.
186
187
Finally, the `ps` command with option `-o rtable` will show routing table information in the last column: 
188
189
    # ps xau -o rtable
190
    USER       PID %CPU %MEM   VSZ   RSS TT  STAT   STARTED       TIME COMMAND          RTABLE
191
    root         1  0.0  0.0   468   408 ??  I       4:43PM    0:01.02 /sbin/init            0
192
    root     95458  0.0  0.0   788   620 ??  Ip      4:43PM    0:00.24 /sbin/slaacd          0
193
    _slaacd  30350  0.0  0.0   792   676 ??  Ip      4:43PM    0:00.08 slaacd: engine (      0
194
    _slaacd  69167  0.0  0.0   800   720 ??  Ip      4:43PM    0:00.08 slaacd: frontend      0
195
    root     59774  0.0  0.0   704   528 ??  IU      4:43PM    0:00.02 dhclient: re0 [p      1
196
    _dhcp    30649  0.0  0.0   828   656 ??  Ip      4:43PM    0:02.77 dhclient: re0 (d      1
197
    root     35197  0.0  0.1   548  2252 ??  IpU     4:44PM    0:00.02 syslogd: [priv]       0
198
    _syslogd  1991  0.0  0.1  1120  1384 ??  Ip      4:44PM    0:00.14 /usr/sbin/syslog      0
199
    root     76166  0.0  0.0   836   584 ??  IU      4:44PM    0:00.01 pflogd: [priv] (      0
200
    _pflogd   9499  0.0  0.0   884   564 ??  Sp      4:44PM    0:01.26 pflogd: [running      0
201
    _ntp     45580  0.0  0.1  1044  2872 ??  I<p     4:44PM    0:00.72 ntpd: ntp engine      0
202
    _ntp     59996  0.0  0.1   888  2560 ??  Ip      4:44PM    0:00.09 ntpd: dns engine      0
203
    root     30954  0.0  0.1   848  1616 ??  I<pU    4:44PM    0:00.06 /usr/sbin/ntpd        0
204
    root     75315  0.0  0.1  1328  1496 ??  I       4:44PM    0:00.16 sshd: /usr/sbin/      0
205
    root     60900  0.0  0.1  1716  2028 ??  Ip      4:44PM    0:00.07 /usr/sbin/smtpd       0
206
    _smtpd   65700  0.0  0.2  1448  3832 ??  Ip      4:44PM    0:00.08 smtpd: klondike       0
207
    _smtpd   90699  0.0  0.2  1656  4044 ??  Ip      4:44PM    0:00.07 smtpd: control (      0
208
    _smtpd   31369  0.0  0.2  1536  3936 ??  Ip      4:44PM    0:00.07 smtpd: lookup (s      0
209
    _smtpd   45982  0.0  0.2  1596  4064 ??  Ip      4:44PM    0:00.06 smtpd: pony expr      0
210
    _smtpq   17106  0.0  0.2  1664  4048 ??  Ip      4:44PM    0:00.08 smtpd: queue (sm      0
211
    _smtpd   94920  0.0  0.2  1444  3872 ??  Ip      4:44PM    0:00.05 smtpd: scheduler      0
212
    _sndiop  35803  0.0  0.0   524   936 ??  IpU     4:44PM    0:00.00 sndiod: helper (      0
213
    _sndio   61376  0.0  0.0   536   808 ??  I<p     4:44PM    0:00.00 /usr/bin/sndiod       0
214
    root     97224  0.0  0.0   204   836 ??  I       4:44PM    0:00.01 /usr/sbin/apmd -      0
215
    root     98386  0.0  0.1   668  1312 ??  Sp      4:44PM    0:00.08 /usr/sbin/cron        0
216
    root     27323  0.0  0.0   940   932 p0  Ip      5:13PM    0:00.36 -ksh (ksh)            0
217
    root     49147  0.0  0.0   484   432 p0  R+pU/3  6:30PM    0:00.00 ps -xau -o rtabl      0
218
    root     42404  0.0  0.1   316  1312 C1  I+pU    4:44PM    0:00.03 /usr/libexec/get      0
219
    root     52228  0.0  0.1   320  1308 C2  I+pU    4:44PM    0:00.02 /usr/libexec/get      0
220
    root     71695  0.0  0.1   316  1308 C3  I+pU    4:44PM    0:00.03 /usr/libexec/get      0
221
    root     90445  0.0  0.1   320  1320 C5  I+pU    4:44PM    0:00.03 /usr/libexec/get      0
222
223
Only the dhclient(8) processes are in the non-default routing domain 1.
224
225
## What's next ?
226
227
As already said above, the machine is now reachable from the internet.
228
So perhaps [pf(4)](https://man.openbsd.org/pf.4) needs to be configured to be more restrictive. 
229
[sshd(8)](https://man.openbsd.org/sshd.8) can be configured to refuse password based authentication, in order to avoid brute force attacks.
230
231
You can then point a domain (leased from a registrar) to the IP addresses of the machine and [httpd(8)](https://man.openbsd.org/httpd.8) can be set-up to provide web based services on this domain.
232
233
Or another interface can be added to that host to convert it into a router to connect to another network.
234
This can be either another physical interface or a vlan interface over the existing re0 interface.