You like to replace the OpenVPN server from my example (1) with Wireguard as shown on the schema in the question. You also want to have a bridged virtual private network to have both remote private subnets in one broadcast domain like as they were just on one local place, e.g. your home network.
First a summary what's possible or not:
- Wireguard does not support bridged mode on OSI layer 2 like OpenVPN with tap interfaces. The first sentence in the whitepaper begins: "WireGuard is a secure network tunnel, operating at layer 3 ...". So we have to live with routing.
- Wireguard uses its own network protocol so it cannot mixed up with openVPN. You have to setup both, the server and the client with Wireguard.
- A Virtual Private Network is made to connect two (ore more) secured subnets. That's by definition. So peer-to-peer security is not an issue here. If you want that, for example ssh (secure shell) connections then you don't need a VPN.
- Wireguard is full supported by systemd-networkd since systemd 237 (4) line 2289. Raspbian Buster comes with systemd 241 (Stretch has 231) so we can only use Raspbian Buster. Please use a fresh flashed image for reference. I use Raspbian Buster Lite.
- A mobile client is not a problem because Wireguard has Built-in-Roaming.
Asking google you will find that everything is already said about setup Wireguard, but not yet from everyone. So I will only focus on a concrete setup with two Raspberry Pis as Client and Server, using systemd-networkd as asked.
♦ Proof of concept
First I do a setup on the local network. In practical it doesn't make much sense but we can verify how it works with reduced sources of error. That's also the reason why I use here the wired connection (eth0) on client and server. If it works then we make the remote setup with wireless.
General Setup
We need the Raspberry Pi OS Buster with at least systemd 241 but if I search in its repository I do not find Wireguard. But it is available in the upcoming Debian testing version "Bullseye" (6) and it is downstream compatible.
Just follow the Wireguard installation and then come back here.
Setup Server
First [Use systemd-networkd for general networking](https://raspberrypi.stackexchange.com/a/108593/79866).
For better understanding I will use only static ip addresses. Later with a mobile client it may be necessary to use DHCP and DNS name resolution. Create these three files:
server ~$ sudo -Es # if not already done
server ~# cat > /etc/systemd/network/12-wg0.network <<EOF
[Match]
Name=wg0
[Network]
Address=10.10.10.2/24
EOF
server ~# cat > /etc/systemd/network/04-eth.network <<EOF
[Match]
Name=eth0
[Network]
# example, use a free ip address from your local network
Address=192.168.50.2/24
# example, use the ip address from your internet router
Gateway=192.168.50.1
DNS=84.200.69.80 1.1.1.1
IPForward=yes
EOF
server ~# echo "PrivateKey=$(wg genkey)" > /etc/systemd/network/02-wg0.netdev
server ~# edit /etc/systemd/network/02-wg0.netdev
Complete the file so that it looks like this (example: don't touch your PrivateKey):
[NetDev]
Name=wg0
Kind=wireguard
Description=Wireguard Server
[WireGuard]
PrivateKey=uAD5I1QRRo48H5PTSrjW2YrhpxUUO8f6v9HvzAaAGmA=
ListenPort=51820
[WireGuardPeer]
# Public key from Client
PublicKey= # will be completed later
AllowedIPs=10.10.10.3/32
Set file permissons, protect private key:
server ~# cd /etc/systemd/network/
server ~# chgrp systemd-network . * # dot asterisk
server ~# chmod 640 02-wg0.netdev
server ~# systemctl reboot
After reboot and login then Check Installation as shown in the section below. Note that we need the public key for the client configuration that we get with sudo wg show wg0
.
Setup Client
First [Use systemd-networkd for general networking](https://raspberrypi.stackexchange.com/a/108593/79866).
Then create these three files:
client ~$ sudo -Es # if not already done
client ~# cat > /etc/systemd/network/12-wg0.network <<EOF
[Match]
Name=wg0
[Network]
Address=10.10.10.3/24
EOF
client ~# cat > /etc/systemd/network/04-eth.network <<EOF
[Match]
Name=eth0
[Network]
# example, use a free ip address from your local network
Address=192.168.50.3/24
# example, use the ip address from your internet router
Gateway=192.168.50.1
DNS=84.200.69.80 1.1.1.1
IPForward=yes
EOF
client ~# echo "PrivateKey=$(wg genkey)" > /etc/systemd/network/02-wg0.netdev
client ~# edit /etc/systemd/network/02-wg0.netdev
Complete the file so that it looks like this (example: don't touch your PrivateKey). Insert the public key from the server:
[NetDev]
Name=wg0
Kind=wireguard
Description=Wireguard Client
[WireGuard]
PrivateKey=UNj3PB1NRC/VzYhozfyJDA//lUNF0FuVtghNRkZ4vH4=
ListenPort=51820
[WireGuardPeer]
# Public key from Server
PublicKey=i3WbIc27CDAK2zs8jQ2g9Irk7InC434kbiX6jb241Fg=
Endpoint=192.168.50.2:51820
AllowedIPs=0.0.0.0/0
Set file permissons, protect private key:
client ~# cd /etc/systemd/network/
client ~# chgrp systemd-network . * # dot asterisk
client ~# chmod 640 02-wg0.netdev
client ~# systemctl reboot
After reboot and login then Check Installation as shown in the section below. Note that we need the public key for the server configuration that we get with sudo wg show wg0
.
Go to the server configuraion and insert the public key from the client in the servers file /etc/systemd/network/02-wg0.netdev
. Then on the server do:
server ~$ sudo systemctl daemon-reload
server ~$ sudo systemctl restart systemd-networkd.service
Now you can check the connection. You should be able to ping each side from the other through the tunnel:
client ~$ ping -c3 -I 10.10.10.3 10.10.10.2
server ~$ ping -c3 -I 10.10.10.2 10.10.10.3
Use nc
(netcat) to check data transfer through the tunnel. On one side, no matter if client or server, start nc
to listen on a port for data. I will use port 12345 here.
server ~$ nc -vvlnp 12345
On the other side send a "hello world"
client ~$ echo "hello world" | nc -v 10.10.10.2 12345
The server side should greating the world.
Check Installation (example from server)
# Check if module is loaded and running
rpi ~$ lsmod | grep wireguard
wireguard 143360 0
ip6_udp_tunnel 16384 1 wireguard
udp_tunnel 16384 1 wireguard
ipv6 450560 43 wireguard
# Check if interface is up
rpi ~$ ip addr show dev wg0
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 10.10.10.2/24 brd 10.10.10.255 scope global wg0
valid_lft forever preferred_lft forever
rpi ~$ networkctl status wg0
● 3: wg0
Link File: n/a
Network File: /etc/systemd/network/12-wg0.network
Type: wireguard
State: routable (configured)
Address: 10.10.10.2
rpi ~$ sudo wg show wg0
interface: wg0
public key: i3WbIc27CDAK2zs8jQ2g9Irk7InC434kbiX6jb241Fg=
private key: (hidden)
listening port: 51820
Note the public key
. We need the server public key for the client configuration and vice versa.
♦ Remote Setup
Work in progress, will be continued soon.
(1) - How to bridge an access point with a remote network by openvpn?
(2) - OSI model
(3) - Wireguard Whitepaper
(4) - systemd NEWS, line 2289
(5) - Built-in-Roaming
(6) - Debian package wireguard
(7) - Wireguard Installation for Debian
(8) - Install and configure WireGuard on Raspberry Pi