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 (
wgandwg-quicktools installed)
Configuration
Step 1: Enable WireGuard Kernel Logging
# Enable WireGuard dynamic debug messagesecho 'module wireguard +p' | sudo tee /sys/kernel/debug/dynamic_debug/control
# Verify debug messagessudo dmesg | grep wireguard
# View WireGuard kernel messages via journalctlsudo journalctl -k --grep="wireguard" --since "1 hour ago"For persistent debug logging across reboots:
options wireguard dyndbg=+pStep 2: Monitor Interface Status
# Show all WireGuard interfaces and peerssudo 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-keepaliveStep 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 minuteINTERFACE="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"donesudo chmod +x /opt/kyra/wireguard-monitor.shecho "* * * * * root /opt/kyra/wireguard-monitor.sh" | sudo tee /etc/cron.d/kyra-wireguardStep 4: Forward Kernel Logs via rsyslog
:msg, contains, "wireguard" @@<COLLECTOR_IP>:514:programname, isequal, "wireguard-audit" @@<COLLECTOR_IP>:514sudo systemctl restart rsyslogStep 5: Monitor with journalctl
# WireGuard service logssudo journalctl -u wg-quick@wg0 --since "1 hour ago"
# Follow kernel messages in real timesudo journalctl -k --grep="wireguard" -fStep 6: Verify on KYRA Collector
kyra-collector statuskyra-collector logs --source wireguard --tail 10Collected Log Types
| Log Type | Description | Security Use |
|---|---|---|
| Handshake Events | Peer handshake initiation/completion from kernel | Connection monitoring |
| Peer Status | Active/inactive state changes via polling | Access tracking |
| Transfer Stats | Bytes rx/tx per peer per interval | Data exfiltration detection |
| Endpoint Changes | Peer source IP:port changes between handshakes | Roaming or hijack detection |
| Interface Events | wg-quick up/down, interface create/destroy | Service availability |
| Kernel Warnings | Invalid handshake, flood detection, key rotation | Attack detection |
Key WireGuard Log Patterns
| Source | Pattern | Meaning |
|---|---|---|
dmesg | Receiving handshake initiation from peer N | Peer connecting |
dmesg | Keypair N created for peer N | Session keys established |
dmesg | Invalid handshake initiation | Potential scan or attack |
journalctl | wg-quick[]: [#] ip link add wg0 type wireguard | Interface created |
wg show | latest handshake: (none) | Peer never connected |
Security Checks
| Check | Method | Alert Condition |
|---|---|---|
| Unknown endpoint IP | Compare wg show endpoints against whitelist | Endpoint not in allowed list |
| Excessive transfer | Track rx/tx delta per interval | Transfer exceeds 10x baseline |
| Handshake flood | Count Invalid handshake kernel messages | More than 100 per minute |
| Config change | Hash /etc/wireguard/wg0.conf | File 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 showpermission 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.