Files
wireguard-vpn/wg-policy-ctl

186 lines
5.0 KiB
Bash

#!/bin/bash
# wg-policy-ctl — CLI management tool for WireGuard Policy Firewall
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/wg-policy-lib.sh"
usage() {
cat <<EOF
Usage: $(basename "$0") <command>
Commands:
status Show full health check report
policy Display current policy.json formatted
rules Show current iptables rules in WG_POLICY chain
ipset Show ipset contents
log Tail WG_DROP logs (last 50 lines)
reload Force re-sync and re-apply policy
backup Manual backup of policy + iptables
stats Show connection and rule statistics
validate Validate policy.json without applying
help Show this help
EOF
}
cmd_status() {
echo "========================================="
echo " WireGuard Policy Firewall Status"
echo " $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================="
echo ""
health_check
}
cmd_policy() {
if [[ -f "$POLICY_FILE" ]]; then
jq '.' "$POLICY_FILE"
else
log_error "policy.json not found"
exit 1
fi
}
cmd_rules() {
echo "=== IPv4 Chain: $CHAIN ==="
if iptables -L "$CHAIN" -n -v --line-numbers 2>/dev/null; then
echo ""
else
echo "(chain not found)"
fi
echo "=== FORWARD references ==="
iptables -L FORWARD -n -v --line-numbers 2>/dev/null | grep -i "$CHAIN" || echo "(none)"
if command -v ip6tables &>/dev/null; then
echo ""
echo "=== IPv6 Chain: $CHAIN ==="
ip6tables -L "$CHAIN" -n -v --line-numbers 2>/dev/null || echo "(chain not found)"
fi
}
cmd_ipset() {
for set_name in "$IPSET_V4" "$IPSET_V6"; do
echo "=== ipset: $set_name ==="
if ipset list "$set_name" 2>/dev/null; then
echo ""
else
echo "(not found)"
echo ""
fi
done
}
cmd_log() {
echo "=== Recent WG_DROP log entries ==="
(journalctl -k --no-pager -n 50 2>/dev/null || dmesg | tail -50) | grep "$LOG_PREFIX" || echo "(no entries)"
}
cmd_reload() {
log_info "Force reloading policy..."
if retry /usr/local/bin/wg-sync-policy.sh; then
if retry /usr/local/bin/wg-policy-engine.sh; then
log_info "Reload complete"
else
log_error "Engine failed"
exit 1
fi
else
log_error "Sync failed"
exit 1
fi
}
cmd_backup() {
backup_policy
backup_iptables
log_info "Manual backup complete. Files in: $BACKUP_DIR"
}
cmd_stats() {
echo "=== Client Count ==="
jq '(.clients // {}) | length' "$POLICY_FILE" 2>/dev/null || echo "N/A"
echo ""
echo "=== Clients with Access ==="
jq -r '.clients // {} | to_entries[] | select(.value.access | length > 0) | "\(.key): \(.value.access | join(", "))"' "$POLICY_FILE" 2>/dev/null || echo "N/A"
echo ""
echo "=== Clients without Access (Internet Only) ==="
jq -r '.clients // {} | to_entries[] | select(.value.access | length == 0) | .key' "$POLICY_FILE" 2>/dev/null || echo "N/A"
echo ""
echo "=== Active iptables rules ==="
iptables -L "$CHAIN" -n 2>/dev/null | tail -n +3 | wc -l || echo "N/A"
echo ""
echo "=== Drop count (since boot) ==="
iptables -L "$CHAIN" -n -v 2>/dev/null | grep "DROP" | awk '{sum += $1} END {print sum+0, "packets dropped"}'
echo ""
echo "=== ipset entries ==="
for set_name in "$IPSET_V4" "$IPSET_V6"; do
local count
count=$(ipset list "$set_name" 2>/dev/null | grep -c '^[0-9a-f:]' || echo 0)
echo " $set_name: $count entries"
done
}
cmd_validate() {
log_info "Validating policy.json..."
if [[ ! -f "$POLICY_FILE" ]]; then
log_error "File not found: $POLICY_FILE"
exit 1
fi
if ! jq empty "$POLICY_FILE" 2>/dev/null; then
log_error "Invalid JSON"
exit 1
fi
local errors=0
local total=0
jq -r '.clients // {} | to_entries[] | "\(.key)|\(.value.access // [] | join(","))"' "$POLICY_FILE" | \
while IFS="|" read -r ip access_str; do
(( total++ ))
if ! validate_cidr "$ip"; then
log_error "Invalid client IP: $ip"
(( errors++ )) || true
fi
if [[ -n "$access_str" ]]; then
IFS=',' read -ra targets <<< "$access_str"
for target in "${targets[@]}"; do
if ! validate_cidr "$target"; then
log_error "Invalid access target for $ip: $target"
(( errors++ )) || true
fi
done
fi
done
if (( errors > 0 )); then
log_error "Validation failed: $errors errors"
exit 1
else
log_info "Validation passed: $total clients, 0 errors"
fi
}
# === DISPATCH ===
case "${1:-help}" in
status) cmd_status ;;
policy) cmd_policy ;;
rules) cmd_rules ;;
ipset) cmd_ipset ;;
log) cmd_log ;;
reload) cmd_reload ;;
backup) cmd_backup ;;
stats) cmd_stats ;;
validate) cmd_validate ;;
help|*) usage ;;
esac