VPN over Wireguard
WireGuard is a communication protocol and free and open-source software that implements encrypted virtual private networks (VPNs). It aims to be lighter and better performing than IPsec and OpenVPN, two common tunneling protocols. The WireGuard protocol passes traffic over UDP.
Configuring a VPN on FreeBSD
Start kernel WireGuard driver
To begin, if not enabled in your kernel, you must load the kernel wg(4) WireGuard driver. As root, run the following command on each host:
wg_peerX# kldload if_wg
To enable it across reboots add this line to your /boot/loader.conf file
wg_peerX# echo 'if_wg_load="YES"' >> /boot/loader.conf
Create the wg(4) pseudo-devices
The next requirement is to create two wg(4) pseudo-devices which will be used to tunnel packets and allow both networks to communicate properly.
On wg_peer1:
wg_peer1# sysrc cloned_interfaces="wg0"
wg_peer1# sysrc ifconfig_wg0="inet 10.0.0.40/24 mtu 1420 up"
On wg_peer2:
wg_peer2# sysrc cloned_interfaces="wg0"
wg_peer2# sysrc ifconfig_wg0="inet 10.0.0.50/24 mtu 1420 up
Create the Wireguard configuration
On heach host create the /etc/wireguard/wg0.conf file
wg_peerX# mkdir /etc/wireguard/
wg_peerX# echo "[Interface]
PrivateKey = $(wg genkey)
ListenPort = 51820" > /etc/wireguard/wg0.conf
wg_peerX# echo "/usr/bin/wg syncconf wg0 /etc/wireguard/wg0.conf" > /etc/start_if.wg0
Start Wireguard
On wg_peer1:
wg_peer1# service netif start wg0
wg_peer1# wg show
interface: wg0
public key: DeadBeefDeadBeefDeadBeefDeadBeefDeadBeef=
private key: (hidden)
listening port: 51820
On wg_peer2:
wg_peer2# service netif start wg0
wg_peer2# wg show
interface: wg0
public key: BeefDeadBeefDeadBeefDeadBeefDeadBeefDead=
private key: (hidden)
listening port: 51820
Configure the peers
On wg_peer1:
wg_peer1# echo "[Peer]
PublicKey = BeefDeadBeefDeadBeefDeadBeefDeadBeefDead=
Endpoint = 192.168.1.50:51820
AllowedIPs = 10.0.0.0/24" >> /etc/wireguard/wg0.conf
On wg_peer2:
wg_peer2# echo "[Peer]
PublicKey = BeefDeadBeefDeadBeefDeadBeefDeadBeefDead=
Endpoint = 192.168.1.40:51820
AllowedIPs = 10.0.0.0/24" >> /etc/wireguard/wg0.conf
Restart Wireguard
On wg_peer1:
wg_peer1# service netif restart wg0
wg_peer1# wg show
interface: wg0
public key: DeadBeefDeadBeefDeadBeefDeadBeefDeadBeef=
private key: (hidden)
listening port: 51820
peer: BeefDeadBeefDeadBeefDeadBeefDeadBeefDead=
endpoint: 192.168.1.50:51820
allowed ips: 10.0.0.0/24
On wg_peer2:
wg_peer2# service netif restart wg0
wg_peer2# wg show
interface: wg0
public key: BeefDeadBeefDeadBeefDeadBeefDeadBeefDead=
private key: (hidden)
listening port: 51820
peer: DeadBeefDeadBeefDeadBeefDeadBeefDeadBeef=
endpoint: 192.168.1.40:51820
allowed ips: 10.0.0.0/24
Test the VPN
On wg_peer1:
wg_peer1# ping 10.0.0.50
PING 10.0.0.50 (10.0.0.50): 56 data bytes
64 bytes from 10.0.0.50: icmp_seq=0 ttl=64 time=0.650 ms
64 bytes from 10.0.0.50: icmp_seq=1 ttl=64 time=0.497 ms
On wg_peer2:
wg_peer2# ping 10.0.0.40
PING 10.0.0.40 (10.0.0.40): 56 data bytes
64 bytes from 10.0.0.40: icmp_seq=0 ttl=64 time=0.710 ms
64 bytes from 10.0.0.40: icmp_seq=1 ttl=64 time=0.481 ms
Use cases
Bridging two network interfaces through Wireguard
Because Wireguard is a (IP/L3 interface) you can't attach it directly to a bridge. The alternative is to create a vxlan tunnel inside the wireguard tunnel.
Wireguard manages the security and authentication
Vxlan the transport of the Ethernet frames.
Configuring the VPN
After setting up the Wireguard tunnel as described bellow, we must set up the vxlan interfaces.
On wg-peer1
wg_peer1# sysrc cloned_interfaces="wg0 bridge0 vxlan0"
wg_peer1# sysrc create_args_vxlan0="vxlanid 48 vxlanlocal 10.0.0.1 vxlanremote 10.0.0.2"
wg_peer1# sysrc ifconfig_em0="up"
wg_peer1# sysrc ifconfig_bridge0="addm em0 addm vxlan0 up"
On wg-peer2
wg_peer1# sysrc cloned_interfaces="wg0 bridge0 vxlan0"
wg_peer1# sysrc create_args_vxlan0="vxlanid 48 vxlanlocal 10.0.0.2 vxlanremote 10.0.0.1"
wg_peer1# sysrc ifconfig_em0="up"
wg_peer1# sysrc ifconfig_bridge0="addm em0 addm vxlan0 up"