Keep your WireGuard VPN connection alive in a jail
Sometimes the VPN service provider might face an issue on their end.
Sometimes your connection goes down for whatever reason.
Sometimes it's been a while since the last successful handshake.
This script, combined with a cron job that runs every 10 minutes in your jail, will automatically reactivate your WireGuard connection if something goes wrong in your absence. It should work with any WireGuard VPN provider that can be natively used in FreeBSD or Linux, such as Mullvad, Proton, Azire, Air, etc.
Prequisites:
- You have a working WireGuard VPN with valid config files
- You are only using a single active wireguard connection (this does not work with multiple simultaneous wireguard connections
- You have configured and enabled the wireguard service and desired interface in
/etc/rc.conf
- You create a cron job under the root user (see example in the comments)
Contents of
/root/.bin/wg-keepalive.sh
Code:
#!/bin/sh # WireGuard Keepalive, FreeBSD Jail Edition # wg-keepalive.sh # Version: 1.0.0 # Checks if the interface is inactive or hasn't had a successful handshake since 10 minutes # Restarts the wireguard service if either of the above are true # DISCLAIMER: This assumes only a *single* active wireguard connection # It does not work for *multiple* active connections # Events are logged under /var/log/wg-keepalive-events.log # This script should be placed under /root/.bin/wg-keepalive.sh # You *must* have your WireGuard VPN configured # You *must* have the wireguard service and desired tunnel enabled in /etc/rc.conf # A complimentary cron job must exist for the root user # Example cron job entry that checks every 10 minutes: # */10 * * * * /root/.bin/wg-keepalive.sh WGINTERFACE=$(wg) # Check if wireguard interface is active if [ -z "$WGINTERFACE" ] then # Activate wireguard interface and log it service wireguard restart echo -e "`date +%Y-%m-%d-%H-%M`: Restarting wireguard service. Interface was not active.\n" >> /var/log/wg-keepalive-events.log exit 1 fi # Compare the current time (in seconds) to the latest handshake LATESTHANDSHAKE=$(echo "`date +%s` - `wg show all latest-handshakes | cut -f3`" | bc) # Check if latest handshake is longer than 10 minutes (600 seconds) if [ "$LATESTHANDSHAKE" -gt 600 ] then # If longer than 10 minutes, restart the wireguard service and log it echo -e "`date +%Y-%m-%d-%H-%M`: Restarting wireguard service. No handshake since $LATESTHANDSHAKE seconds ago.\n" >> /var/log/wg-keepalive-events.log service wireguard restart exit 1 else # If shorter than 10 minutes, do nothing and exit exit 0 fi
This is a sample of what the logfile looks like after logging some events:
Code:
2023-11-08-04-00: Restarting wireguard service. No handshake since 766 seconds ago. 2023-11-08-05-00: Restarting wireguard service. Interface was not active. 2023-11-08-06-00: Restarting wireguard service. Interface was not active.
Currently tested and used on TrueNAS Core 13.0-U5.3 in a FreeBSD 13.2-RELEASE-p5 jail, as of November 19, 2023.