Files
Hermes-Skills/devops/network-failover/references/wireguard-auto-switch.md
T
Hermes Skills Manager 6770bc9b9d Initial commit: Hermes Agent skills collection
- Trading skills (OKX, dividend, lottery, quantitative)
- Creative skills (ASCII art, diagrams, video)
- Development skills (GitHub, debugging, TDD)
- Research skills (arXiv, blog monitoring)
- Productivity skills (email, documents, notes)
- MCP integration skills
- Custom user skills
2026-07-05 02:31:15 -04:00

3.2 KiB

WireGuard Auto-Switch — Full Implementation

Complete script + systemd timer for automatic WireGuard failover.

Auto-Switch Script

Path: ~/.hermes/scripts/wg-auto-switch.sh

#!/bin/bash
WG_IF="wg0"
LOG="/var/log/wg-auto-switch.log"
TARGETS=("8.8.8.8" "1.1.1.1" "208.67.222.222")
FAIL_THRESHOLD=3
RECOVER_THRESHOLD=2
FAIL_FILE="/tmp/wg-auto-fail-count"
RECOVER_FILE="/tmp/wg-auto-recover-count"

log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG"; }

check_network() {
    for target in "${TARGETS[@]}"; do
        if curl -s --max-time 3 --head "http://$target" > /dev/null 2>&1; then return 0; fi
        if ping -c 1 -W 2 "$target" > /dev/null 2>&1; then return 0; fi
    done
    return 1
}

wg_is_up() { ip link show "$WG_IF" > /dev/null 2>&1; }
get_count() { [ -f "$1" ] && cat "$1" || echo 0; }

if check_network; then
    if wg_is_up; then
        count=$(($(get_count "$RECOVER_FILE") + 1))
        echo "$count" > "$RECOVER_FILE"
        [ "$count" -ge "$RECOVER_THRESHOLD" ] && {
            log "✅ Network recovered, disconnecting WireGuard"
            sudo wg-quick down "$WG_IF" 2>>"$LOG"
            echo 0 > "$FAIL_FILE"; echo 0 > "$RECOVER_FILE"
        }
    else
        echo 0 > "$FAIL_FILE"; echo 0 > "$RECOVER_FILE"
    fi
else
    if ! wg_is_up; then
        count=$(($(get_count "$FAIL_FILE") + 1))
        echo "$count" > "$FAIL_FILE"
        [ "$count" -ge "$FAIL_THRESHOLD" ] && {
            log "❌ Network restricted (${count} failures), starting WireGuard"
            sudo wg-quick up "$WG_IF" 2>>"$LOG"
            echo 0 > "$FAIL_FILE"; echo 0 > "$RECOVER_FILE"
        }
    else
        log "⚠️ WireGuard connected but still no network"
    fi
fi

Systemd Timer Setup

# Make script executable
chmod +x ~/.hermes/scripts/wg-auto-switch.sh

# Create service unit
sudo tee /etc/systemd/system/wg-auto-switch.service << 'EOF'
[Unit]
Description=WireGuard Auto Switch - Network Check
After=network.target

[Service]
Type=oneshot
ExecStart=/home/openclaw/.hermes/scripts/wg-auto-switch.sh
User=openclaw
EOF

# Create timer unit
sudo tee /etc/systemd/system/wg-auto-switch.timer << 'EOF'
[Unit]
Description=Run WireGuard auto switch every 30 seconds

[Timer]
OnBootSec=30
OnUnitActiveSec=30
AccuracySec=5

[Install]
WantedBy=timers.target
EOF

# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable --now wg-auto-switch.timer

Monitoring

sudo systemctl status wg-auto-switch.timer
tail -f /var/log/wg-auto-switch.log
sudo wg show

Tuning

Parameter Default Effect
FAIL_THRESHOLD 3 Consecutive failures before VPN activates (higher = slower to react, less flapping)
RECOVER_THRESHOLD 2 Consecutive successes before VPN deactivates
Timer interval 30s How often to check (in /etc/systemd/system/wg-auto-switch.timer)
curl --max-time 3s Per-target timeout
ping -W 2s Ping timeout

For stricter environments (GFW deep packet inspection), add DNS-over-HTTPS check:

# Add to check_network() as a third test type
if curl -s --max-time 5 "https://dns.google/resolve?name=google.com&type=A" | grep -q '"Answer"'; then
    return 0
fi