#!/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 < 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