Before going further let's have a look at when OpenBSD's Wireguard implementation hit base by default.
On May 12 2020, Matt Dunwoodie shared his work on OpenBSD's Wireguard implementation on openbsd-tech mailing list:
Jason A. Donenfeld who is known to be Wireguard's author took part in the discussion, you can see the whole mailing list thread here:
On May 26 2020, Matt Dunwoodie and Jason A. Donenfeld shared a second revision of their work:
On June 19 2020, a third revision was submitted:
Then Jason A. Donenfeld submitted three patch:
Richard N Procter shared feedback about checksum counter not being correctly updated:
Klemens Nanni rework wg(4) peer counter:
Back to relevant things, Matt Dunwoodie and Jason A. Donenfeld OpenBSD's Wireguard implementation wg(4) first hit CVS tree on Jun 21 2020:
Let's take a look to wg(4) examples manpage:
Create two wg interfaces in separate rdomain(4)s, which is of no practical use but demonstrates two interfaces on the same machine:
#!/bin/sh
# create interfaces; set random private keys
ifconfig wg1 create wgport 7111 wgkey `openssl rand -base64 32` rdomain 1
ifconfig wg2 create wgport 7222 wgkey `openssl rand -base64 32` rdomain 2
# retrieve the public keys associated with the private keys
PUB1="`ifconfig wg1 | grep 'wgpubkey' | cut -d ' ' -f 2`"
PUB2="`ifconfig wg2 | grep 'wgpubkey' | cut -d ' ' -f 2`"
ifconfig wg1 wgpeer $PUB2 wgendpoint 127.0.0.1 7222 wgaip 192.168.5.2/32
ifconfig wg2 wgpeer $PUB1 wgendpoint 127.0.0.1 7111 wgaip 192.168.5.1/32
ifconfig wg1 192.168.5.1/24
ifconfig wg2 192.168.5.2/24
After this, ping one interface from the other:
$ route -T1 exec ping 192.168.5.2
The two interfaces are able to communicate through the UDP tunnel which resides in the default rdomain(4).
Show the listening sockets:
$ netstat -ln
Does it work? I will take a look with netstat(1) and ifconfig(8) command:
unhu# netstat -ln
Active Internet connections
Proto Recv-Q Send-Q Local Address Foreign Address (state)
ip 0 0 *.* *.* 17
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp 0 0 127.0.0.1.25 *.* LISTEN
tcp 0 0 *.22 *.* LISTEN
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
udp 0 0 *.7222 *.*
udp 0 0 *.7111 *.*
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp6 0 0 fe80::1%lo0.25 *.* LISTEN
tcp6 0 0 *.22 *.* LISTEN
tcp6 0 0 ::1.25 *.* LISTEN
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
udp6 0 0 *.7222 *.*
udp6 0 0 *.7111 *.*
We can see two UDP sockets which are respectively binded to 7111 and 7222 port.
You can ask yourself why is it binded to *
the answer is here:
Set the UDP port that the tunnel operates on. The interface will bind to INADDR_ANY and IN6ADDR_ANY_INIT. If no port is configured, one will be chosen automatically.
A quick look at inet(4) says:
Sockets may be created with the local address INADDR_ANY to effect “wildcard” matching on incoming messages.
INADDR_ANY stands for IPv4 and IN6ADDR_ANY_INIT for IPv6.
What ifconfig(8) command says about our Wireguard interface:
unhu# ifconfig | grep -A1 wg
wg1: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> rdomain 1 mtu 1420
index 5 priority 0 llprio 3
wgport 7111
wgpubkey P8Ij+K/McBqRKe29qRtriBjP/Zo0jKjSsN3bIOeDkw8=
wgpeer wm00xLZKnE37LJnenDz+A8AKFVvIhvkp9QG7SgnZsiM=
wgendpoint 127.0.0.1 7222
tx: 436, rx: 380
wgaip 192.168.5.2/32
groups: wg
inet 192.168.5.1 netmask 0xffffff00 broadcast 192.168.5.255
wg2: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> rdomain 2 mtu 1420
index 7 priority 0 llprio 3
wgport 7222
wgpubkey wm00xLZKnE37LJnenDz+A8AKFVvIhvkp9QG7SgnZsiM=
wgpeer P8Ij+K/McBqRKe29qRtriBjP/Zo0jKjSsN3bIOeDkw8=
wgendpoint 127.0.0.1 7111
tx: 380, rx: 436
wgaip 192.168.5.1/32
groups: wg
inet 192.168.5.2 netmask 0xffffff00 broadcast 192.168.5.255
Everything looks good but can we tell a little bit more about rdomain 1 and rdomain 2, let's read the well documented man page:
The traditional kernel routing system had a single table for routes and allowed only non-conflicting IP address assignments.
The rtable feature allows multiple lookup tables for routes.
The rdomain feature provides a way to logically segment a router between network paths.
Basically say, it's a way to segment an OpenBSD box into specific L3 routing domain.
By default each rdomain can't communicate with each other.
As stated on the man page, by default an OpenBSD box have only one rdomain known as rdomain 0
This article isn't about rdomain(4) and will be discussed on a dedicated blog entry.
What we can say about the configured example setup is that they both share the same network subnet prefix:
ifconfig wg1 192.168.5.1/24
ifconfig wg2 192.168.5.2/24
Which isn't allowed as stated in rdomain(4) man page:
The traditional kernel routing system had a single table for routes and allowed only non-conflicting IP address assignments.
That's where rdomain(4) come to the play:
# create interfaces; set random private keys
ifconfig wg1 create wgport 7111 wgkey `openssl rand -base64 32` rdomain 1
ifconfig wg2 create wgport 7222 wgkey `openssl rand -base64 32` rdomain 2
Each wg(4) interfaces are created in specific rdomain which override rdomain 0 limitation.
We can check it with the following commands:
unhu# route -T1 show
Routing tables
Internet:
Destination Gateway Flags Refs Use Mtu Prio Iface
192.168.5/24 192.168.5.1 UCn 1 0 - 4 wg1
192.168.5.1 wg1 UHLl 0 2 - 1 wg1
192.168.5.2 link#0 UHc 0 1 - 3 wg1
192.168.5.255 192.168.5.1 UHb 0 0 - 1 wg1
unhu# route -T2 show
Routing tables
Internet:
Destination Gateway Flags Refs Use Mtu Prio Iface
192.168.5/24 192.168.5.2 UCn 1 0 - 4 wg2
192.168.5.1 link#0 UHc 0 2 - 3 wg2
192.168.5.2 wg2 UHLl 0 4 - 1 wg2
192.168.5.255 192.168.5.2 UHb 0 0 - 1 wg2
Then we just have to check that both tunnel endpoints can be reached:
unhu# route -T1 exec ping -c 1 192.168.5.2
PING 192.168.5.2 (192.168.5.2): 56 data bytes
64 bytes from 192.168.5.2: icmp_seq=0 ttl=255 time=0.304 ms
--- 192.168.5.2 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.304/0.304/0.304/0.000 ms
unhu# route -T2 exec ping -c 1 192.168.5.1
PING 192.168.5.1 (192.168.5.1): 56 data bytes
64 bytes from 192.168.5.1: icmp_seq=0 ttl=255 time=0.290 ms
--- 192.168.5.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.290/0.290/0.290/0.000 ms
See you space cowboy...