How to install a Wireguard VPN client in a FreeBSD jail - nixCraft

How to install a Wireguard VPN client in a FreeBSD jail

See all FreeBSD related FAQ
I installed/set up a Wireguard VPN server on Debian 10 Linux box. How do I install, configure and set up a Wireguard client in a FreeBSD jail?

WireGuard is an open-source software application and communication protocol that implements VPN to create secure point-to-point connections in routed or bridged mode. It was initially developed for Linux but now ported to FreeBSD and other operating systems. This page explains how to install and set up WireGuard clients on the FreeBSD system, including jail.
Tutorial requirements
RequirementsFreeBSD host, FreeBSD jail or FreeNAS
Root privileges Yes
Difficulty level Intermediate
Category WireGuard VPN
OS compatibility FreeBSD FreeNAS Jails Unix
Est. reading time 4 minutes

How to install a Wireguard VPN client in a FreeBSD

This guide assumes that the WireGuard server is up and running either Linux or FreeBSD server. See how to install WireGuard:

I tested this guide running on FreeBSD 11.x, but instructions remain same for FreeBSD 12.x.

A note about FreeBSD jail

Make sure you unhide tun* and bpf* devices for your jail. For example, here is my config file displayed using the cat command:
# cat /etc/devfs.rules

[devfsrules_jail_nixcraft-jail=5]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add path 'tun*' unhide
add path 'bpf*' unhide
add path zfs unhide

See my guide “How to configure a FreeBSD Jail with vnet and ZFS” for more information. If you are using FreeNAS based jail make sure you turn on VNET/BPF support as follows in UI:
FreeNAS jail VNET support for WireGuard VPN

Step 1 – Update FreeBSD

Run the following pkg command:
# pkg update
# pkg upgrade

Search for WireGuard package, run:
# pkg search wireguard
Outputs:

wireguard-2,1                  Meta-port for Wireguard
wireguard-go-0.0.20220316_5,1  WireGuard implementation in Go
wireguard-kmod-0.0.20220615    WireGuard implementation for the FreeBSD kernel
wireguard-tools-1.0.20210914_1 Fast, modern and secure VPN Tunnel
wireguard-tools-lite-1.0.20210914_1 Fast, modern and secure VPN Tunnel (lite flavor)

You need to install the wireguard meta port.

Step 2 – Installing a Wireguard VPN client in a FreeBSD jail

Execute the following command to install a Wireguard VPN client in a FreeBSD jail or FreeBSD host:
# pkg install wireguard
How to install a Wireguard VPN client in a FreeBSD jail

Step 3 – Generating private and public keys for WireGuard VPN client

We need to use the wg command command. It is the configuration utility for getting and setting the configuration of WireGuard tunnel interfaces:
# cd /usr/local/etc/wireguard/
# umask 077; wg genkey | tee privatekey-remote-ln-sg-vpn | wg pubkey > publickey-remote-ln-sg-vpn
# ls -l
# cat privatekey-remote-ln-sg-vpn publickey-remote-ln-sg-vpn

FreeBSD WirdGuard VPN Client Config

Step 4 – Creating wg0.conf file

Use a text editor such as vim to edit/update wg0.conf file:
# vim /usr/local/etc/wireguard/wg0.conf
Sample config file:

# WireGuard config client for Linode VPN server running on Debian 10 #
[Interface]
## FreeBSD client's private key here ##
PrivateKey = {FreeBSD_Jail_PRIVATE_KEY_HERE}
 
## Client ip address as per your set up ##
Address = 172.16.0.3/24
## Set DNS as per your VPN set up ##
DNS = 10.8.0.1
 
[Peer]
## Debian 10 WireGuard server's public key goes here ##
PublicKey = {SERVER_PUBLIC_KEY_HERE}
 
## set ACL ##
AllowedIPs = 0.0.0.0/0
 
## Your Debian 10 WireGuard server's public IPv4/IPv6 address and port goes here ##
Endpoint = {WG_PUBLIC_IP}:{WG_PORT}
 
## Keep connection alive ##
PersistentKeepalive = 15

Step 4 – Turn on WireGuard VPN client service

Type the following sysrc command:
# sysrc wireguard_interfaces="wg0"
# sysrc wireguard_enable="YES"

Step 5 – Running WireGuard VPN client on FreeBSD jail for the first time

The syntax is as follows for the service command:

Start the wireguard vpn client:

# service wireguard start

[#] wireguard-go wg0
INFO: (wg0) 2020/08/08 12:24:37 Starting wireguard-go version 0.0.20200320
[#] wg setconf wg0 /tmp/tmp.DjieZIFu/sh-np.EtDMVd
[#] ifconfig wg0 inet 172.16.0.3/24 172.16.0.3 alias
[#] ifconfig wg0 mtu 1420
[#] ifconfig wg0 up
[#] resolvconf -a wg0 -x
[#] route -q -n add -inet 0.0.0.0/1 -interface wg0
[#] route -q -n add -inet 128.0.0.0/1 -interface wg0
[#] route -q -n add -inet 13.xxx.yyy.zzz -gateway 192.168.2.254
[+] Backgrounding route monitor

Stop the wireguard vpn client

# service wireguard stop

Restart the wireguard vpn client

# service wireguard restart

Get the status of wireguard vpn client:

# wg
# ps aux | grep wireguard

Step 5 – Test WireGuard VPN connectivty

Let us verify VPN connectivty. Run the ping command to send ICMP ECHO_REQUEST packets to network to VPN server IP address 172.16.0.1:
# ping -c 4 ping 172.16.0.1

PING 172.16.0.1 (172.16.0.1): 56 data bytes
64 bytes from 172.16.0.1: icmp_seq=0 ttl=64 time=41.848 ms
64 bytes from 172.16.0.1: icmp_seq=1 ttl=64 time=41.683 ms
64 bytes from 172.16.0.1: icmp_seq=2 ttl=64 time=41.793 ms
64 bytes from 172.16.0.1: icmp_seq=3 ttl=64 time=42.089 ms

--- 172.16.0.1 ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 41.683/41.853/42.089/0.149 ms

Use the ifconfig command and netstat command to view routing information:
# ifconfig
# ifconfig wg0

wg0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1420
	options=80000<LINKSTATE>
	inet 172.16.0.3 --> 172.16.0.3 netmask 0xffffff00
	nd6 options=101<PERFORMNUD,NO_DAD>
	groups: tun
	Opened by PID 96281

See routing info on your FreeBSD:
# netstat -f inet -r -n
# netstat -f inet6 -r -n

Make sure you get public IPv4/IPv6 address of your VPN end point using the host command/dig command/drill command:
# drill TXT +short o-o.myaddr.l.google.com @ns1.google.com
# dig TXT +short o-o.myaddr.l.google.com @ns1.google.com

;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 1382
;; flags: qr aa rd ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; o-o.myaddr.l.google.com.	IN	TXT

;; ANSWER SECTION:
o-o.myaddr.l.google.com.	60	IN	TXT	"13.xxx.yyy.zzz"

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 42 msec
;; SERVER: 216.239.32.10
;; WHEN: Sat Aug  8 12:23:05 2020
;; MSG SIZE  rcvd: 68

Helper script for connection

I have not used the following script since FreeBSD 13. Whatever bug they had in an older version of FreeBSD is fixed. However, I am keeping the script below if you still use an older FreeBSD version.

I have FTTH and backup 4G LTE internet at home. Once in a week/month, my FTTH will be down. Sometimes remote Debian 10 Wireguard VPN server at the office will be restarted or down for maintenance too. So I wrote a quick notification and wg service restart script in /bin/sh. It is also possible that there might be a bug in WireGuard FreeBSD package as it failed to restart when the remote server was down. Either way, this tiny script saved time for me.

#!/bin/sh
# Name: monitor-wg0.sh
# Purpose: Check for wg0 status and if it is down due to an Internet problem or remote VPN problem, try to restart it. 
# Tested on: FreeBSD 11.x and 12.x only
# Author: Vivek Gite {https://www.cyberciti.biz/} under GPL v2.x+
# ---------------------------------------------------------------------------------------------------------------------
# Replace domain name and wg0 gateway IP as per your set up
DOMAIN="www.google.com"
VPNGWIP="172.16.0.1"
if ! ping -q -c 4 "$DOMAIN" >/dev/null 2>&1 || ! ping -q -c 4 "$VPNGWIP" >/dev/null 2>&1
then
	/usr/bin/logger -p local0.crit "*** Cannot connect to the Internet via a VPN. Restarting wg0 ..."
	/usr/sbin/service wireguard restart
	if ! ping -q -c 4 "$DOMAIN" >/dev/null 2>&1 || ! ping -q -c 4 "$VPNGWIP" >/dev/null 2>&1
	then
		/usr/bin/logger -p local0.crit "*** VPN wg0 or the Internet still down. Manual intervention is needed ..."
	else
		/usr/bin/logger -p local0.crit "*** SUCCESS: VPN wg0 back online."
	fi
fi

I am going to run crontab (cron jobs) every 10 minutes to check wg0 VPN status as follows:

# monitor wg0 link and notify on my FreeBSD home server/laptop:
*/5 * * * *     /root/bin/monitor-wg0.sh

See how to set up and configure cron jobs/crontab for more info.

Conclusion

This quick guide covered the WireGuard VPN client installation and configuration for FreeBSD jail. See WireGuard project documentation or read man pages by typing the following man command:
$ man 8 wg-quick
$ man 8 wg

🥺 Was this helpful? Please add a comment to show your appreciation or feedback.

nixCrat Tux Pixel Penguin
Hi! 🤠
I'm Vivek Gite, and I write about Linux, macOS, Unix, IT, programming, infosec, and open source. Subscribe to my RSS feed or email newsletter for updates.

7 comments… add one
  • Mannekino Jan 12, 2021 @ 17:59

    Thank you for this guide. Worked like a charm for me to get WireGuard going inside a Jail on my TrueNAS server. I skipped the configuration file and private/public key sections because I got a configuration from my VPN provider.

  • Mike Feb 7, 2021 @ 3:41

    Thank you this worked perfectly. However, I’m unable to access my jail when the VPN connection is active. Do you know how I can have internet traffic still go through the VPN while keeping access from my local LAN?

  • Gleb May 27, 2021 @ 11:54

    Are you accept donations? This guide is rock 🤘!

  • fred974 Jun 14, 2021 @ 16:16

    Thank you very much for this guide. I followed the steps you provided inside the TrueNAS jail and I get this error when trying to start the service

    root@Syncthing:~ # service wireguard start
    [#] ifconfig wg create name wg0
    [!] Missing WireGuard kernel support (ifconfig: SIOCIFCREATE2: Invalid argument). Falling back to slow userspace implementation.
    [#] wireguard-go wg0
    /usr/local/bin/wg-quick: line 33: wireguard-go: command not found
    [#] ifconfig wg0 destroy
    ifconfig: interface wg0 does not exist

    Any idea where I went wrong?

    Thank you

    • xerexos Sep 25, 2022 @ 17:57

      im having the same issue as you, no clue whats wrong
      [#] ifconfig wg create name wg0
      [!] Missing WireGuard kernel support (ifconfig: SIOCIFCREATE2: Invalid argument). Falling back to slow userspace implementation.
      [#] wireguard-go wg0
      /usr/local/bin/wg-quick: line 33: wireguard-go: command not found
      [#] ifconfig wg0 destroy
      ifconfig: interface wg0 does not exist

      • 🛡️ Vivek Gite (Author and Admin) Vivek Gite Sep 26, 2022 @ 5:25

        For FreeBSD < 12.1 only the userland implementation wireguard-go is available. For FreeBSD >= 12.1 we default to use the kernel module if_wg(4). If you experience problems with it you can switch back to wireguard-go by removing net/wireguard-kmod and making sure net/wireguard-go is installed. The userland tools wg-quick(8) and wg(8) try to use kernel support if the kernel module is available and otherwise fall back to wireguard-go automatically. Config files are fully compatible.

Leave a Reply

Your email address will not be published. Required fields are marked *

Use HTML <pre>...</pre> for code samples. Your comment will appear only after approval by the site admin.