Quote from: mtchetch on March 13, 2026, 01:20:05 PMBecause of the acute lack of solutions I decided to roll my own and share it.
An easy way of doing this with minimal modifications is to use userscripts.
The scipt has been tested on OPNsense 26.1.1-amd64
Steps to implement:
Log into the firewall shell with SSH and create the script file:Code Selectvi /usr/local/opnsense/service/conf/actions.d/actions_wireguardlogger.conf
Add the content (if not familiar with VI press i and then paste content and press esc and :wq and enter)Code Select[restart]
command: /bin/sh -c 'S=/var/db/wg-peer-cron.state; T=$(mktemp /tmp/wg-peer-cron.XXXXXX) || exit 1; M=$(mktemp /tmp/wg-peer-map.XXXXXX) || exit 1; N=$(date +%s); mkdir -p /var/db; python3 -c '\''import xml.etree.ElementTree as ET; root=ET.parse("/conf/config.xml").getroot(); [print(((c.findtext("pubkey") or "").strip())+"|"+((c.findtext("name") or "").strip())) for c in root.findall("./OPNsense/wireguard/client/clients/client")]'\'' > "$M"; /usr/bin/wg show all dump | awk -F "\t" -v now="$N" '\''NF==9{hs=$6+0; age=(hs>0?now-hs:999999999); st=(hs>0&&age<=300?"connected":"disconnected"); print $1 "|" $2 "|" st "|" hs "|" $4 "|" $5 "|" age}'\'' > "$T" && [ -s "$T" ] || { rm -f "$T" "$M"; exit 0; }; [ -f "$S" ] || : > "$S"; while IFS="|" read -r IF PK ST HS EP AL AGE; do O=$(awk -F "|" -v i="$IF" -v p="$PK" '\''$1==i && $2==p {print; exit}'\'' "$S"); OS=$(printf "%s" "$O" | awk -F "|" '\''{print $3}'\''); [ -n "$OS" ] || OS=unknown; PN=$(awk -F "|" -v p="$PK" '\''$1==p {print $2; exit}'\'' "$M"); [ -n "$PN" ] || PN=unknown; [ -n "$EP" ] && [ "$EP" != "(none)" ] || EP=unknown; [ "$ST" = connected ] && [ "$OS" != connected ] && logger -t wireguard -p auth.notice "wireguard peer connected: instance=$IF, peer_name=$PN, peer_pubkey=$PK, endpoint=$EP, allowed_ips=$AL, handshake_age=${AGE}s"; [ "$ST" = disconnected ] && [ "$OS" != disconnected ] && logger -t wireguard -p auth.notice "wireguard peer disconnected: instance=$IF, peer_name=$PN, peer_pubkey=$PK, endpoint=$EP, allowed_ips=$AL, handshake_age=${AGE}s"; done < "$T"; cut -d"|" -f1-6 "$T" > "$S"; rm -f "$T" "$M"'
parameters:
type: script
message: checking wireguard connections
description: Wireguard connection monitor and logger
Pay attention to the command parameter, the whole long command needs to be one line.
Restart the configd service to see the new script:Code Selectservice configd restart
Log into web management and go to system -> settings -> cron
Create a new job and set it to run every minute
If you did everything correctly the Wireguard log will start logging events every minute. These are accessible directly in the wireguard VPN log menu.Code Select2026-03-13T14:04:00 Notice wireguard wireguard peer connected: instance=wg0, peer_name=phone, peer_pubkey=bOa1clBIOgmJEw2To7+StkqPaA2UxKsjw=, endpoint=192.168.11.65:51888, allowed_ips=192.168.12.2/32, handshake_age=56s
2026-03-13T14:03:00 Notice wireguard wireguard peer disconnected: instance=wg0, peer_name=laptop, peer_pubkey=9V3VB9ALJtB0lgvhpCetVVEbZW6YH6Rnk=, endpoint=192.168.11.228:54553, allowed_ips=192.168.12.3/32, handshake_age=513s
2026-03-13T13:58:12 Notice wireguard wireguard peer disconnected: instance=wg0, peer_name=phone, peer_pubkey=bOa1clBIOgmJEw2To7+StkqPaA2UxKsjw=, endpoint=192.168.11.65:51888, allowed_ips=192.168.12.2/32, handshake_age=381s
2026-03-13T13:54:36 Notice wireguard wireguard peer connected: instance=wg0, peer_name=laptop, peer_pubkey=9V3VB9ALJtB0lgvhpCetVVEbZW6YH6Rnk=, endpoint=192.168.11.228:54553, allowed_ips=192.168.12.3/32, handshake_age=9s
2026-03-13T13:51:57 Notice wireguard wireguard peer connected: instance=wg0, peer_name=phone, peer_pubkey=bOa1clBIOgmJEw2To7+StkqPaA2UxKsjw=, endpoint=192.168.11.65:51888, allowed_ips=192.168.12.2/32, handshake_age=6s
Peers are marked disconnected when they have not handshaked in 300 seconds / 5 min.
For the life of me I do not understand why this simple logging is not part of the Wireguard implementation on every firewall, since it is essential to know who is accessing your firewall and from where.
That scripts runs perfectly fine, thank you so much!
At least a bit of information in the logs.
"