本文にスキップ

WireGuard

Overview

WireGuard is a modern, lightweight VPN protocol implemented as a kernel module. Unlike traditional VPNs, WireGuard has minimal logging by default. KYRA MDR collects handshake events from kernel logs, peer connection state via polling, and transfer statistics to monitor VPN access patterns and detect unauthorized tunnel activity.

Prerequisites

  • KYRA MDR account (MDR tier or above)
  • KYRA Collector installed and reachable from the WireGuard host (TCP 514)
  • Root or sudo access on the WireGuard server
  • WireGuard kernel module loaded (wg and wg-quick tools installed)

Configuration

Step 1: Enable WireGuard Kernel Logging

Terminal window
# Enable WireGuard dynamic debug messages
echo 'module wireguard +p' | sudo tee /sys/kernel/debug/dynamic_debug/control
# Verify debug messages
sudo dmesg | grep wireguard
# View WireGuard kernel messages via journalctl
sudo journalctl -k --grep="wireguard" --since "1 hour ago"

For persistent debug logging across reboots:

/etc/modprobe.d/wireguard.conf
options wireguard dyndbg=+p

Step 2: Monitor Interface Status

Terminal window
# Show all WireGuard interfaces and peers
sudo wg show
# Machine-readable output (tab-separated)
sudo wg show wg0 dump
# Output columns: public-key, preshared-key, endpoint, allowed-ips,
# latest-handshake, transfer-rx, transfer-tx, persistent-keepalive

Step 3: Create Peer Monitoring Script

Since WireGuard does not emit connect/disconnect events natively, poll for state changes:

#!/bin/bash
# /opt/kyra/wireguard-monitor.sh - run via cron every minute
INTERFACE="wg0"
STATE_FILE="/var/lib/kyra/wg-peers-state"
COLLECTOR="<COLLECTOR_IP>"
mkdir -p /var/lib/kyra
sudo wg show "$INTERFACE" dump | tail -n +2 | \
while IFS=$'\t' read -r pubkey psk endpoint allowed rx tx handshake keepalive; do
PEER_ID=$(echo "$pubkey" | head -c 12)
NOW=$(date +%s)
# Active if handshake within last 180 seconds
if [ "$handshake" -gt 0 ] && [ $((NOW - handshake)) -lt 180 ]; then
STATUS="active"
else
STATUS="inactive"
fi
PREV=$(grep "^${PEER_ID}:" "$STATE_FILE" 2>/dev/null | cut -d: -f2)
if [ "$STATUS" != "$PREV" ]; then
logger -t wireguard-audit -n "$COLLECTOR" -P 514 --tcp \
"PEER_${STATUS^^} peer=$PEER_ID endpoint=$endpoint allowed_ips=$allowed rx=$rx tx=$tx"
fi
# Update state file
grep -v "^${PEER_ID}:" "$STATE_FILE" 2>/dev/null > "${STATE_FILE}.tmp"
echo "${PEER_ID}:${STATUS}" >> "${STATE_FILE}.tmp"
mv "${STATE_FILE}.tmp" "$STATE_FILE"
done
Terminal window
sudo chmod +x /opt/kyra/wireguard-monitor.sh
echo "* * * * * root /opt/kyra/wireguard-monitor.sh" | sudo tee /etc/cron.d/kyra-wireguard

Step 4: Forward Kernel Logs via rsyslog

/etc/rsyslog.d/30-wireguard.conf
:msg, contains, "wireguard" @@<COLLECTOR_IP>:514
:programname, isequal, "wireguard-audit" @@<COLLECTOR_IP>:514
Terminal window
sudo systemctl restart rsyslog

Step 5: Monitor with journalctl

Terminal window
# WireGuard service logs
sudo journalctl -u wg-quick@wg0 --since "1 hour ago"
# Follow kernel messages in real time
sudo journalctl -k --grep="wireguard" -f

Step 6: Verify on KYRA Collector

Terminal window
kyra-collector status
kyra-collector logs --source wireguard --tail 10

Collected Log Types

Log TypeDescriptionSecurity Use
Handshake EventsPeer handshake initiation/completion from kernelConnection monitoring
Peer StatusActive/inactive state changes via pollingAccess tracking
Transfer StatsBytes rx/tx per peer per intervalData exfiltration detection
Endpoint ChangesPeer source IP:port changes between handshakesRoaming or hijack detection
Interface Eventswg-quick up/down, interface create/destroyService availability
Kernel WarningsInvalid handshake, flood detection, key rotationAttack detection

Key WireGuard Log Patterns

SourcePatternMeaning
dmesgReceiving handshake initiation from peer NPeer connecting
dmesgKeypair N created for peer NSession keys established
dmesgInvalid handshake initiationPotential scan or attack
journalctlwg-quick[]: [#] ip link add wg0 type wireguardInterface created
wg showlatest handshake: (none)Peer never connected

Security Checks

CheckMethodAlert Condition
Unknown endpoint IPCompare wg show endpoints against whitelistEndpoint not in allowed list
Excessive transferTrack rx/tx delta per intervalTransfer exceeds 10x baseline
Handshake floodCount Invalid handshake kernel messagesMore than 100 per minute
Config changeHash /etc/wireguard/wg0.confFile hash changed unexpectedly

Troubleshooting

  • No kernel messages: Dynamic debug may not be supported on all kernels. Check ls /sys/kernel/debug/dynamic_debug/control. Use the polling script as an alternative.
  • wg show permission denied: Requires root. Run monitoring script as root or via sudo.
  • Handshake shows (none): Peer never completed a handshake. Check peer config (public key, endpoint, allowed IPs) and firewall rules on UDP 51820.
  • Missing peer: Peer must be configured in /etc/wireguard/wg0.conf. WireGuard does not dynamically discover peers.
  • High CPU from polling: Reduce cron frequency to every 5 minutes for servers with 100+ peers.

Contact kyra@seekerslab.com for integration support.