# ============================================ # Rule Management # ============================================ function fw::block_ip() { local client_ip="$1" target_ip="$2" fw::_forward_exists -s "$client_ip" -d "$target_ip" -j DROP \ || iptables -I FORWARD 1 -s "$client_ip" -d "$target_ip" -j DROP fw::_forward_exists -s "$client_ip" -d "$target_ip" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" \ || iptables -I FORWARD 1 -s "$client_ip" -d "$target_ip" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" } function fw::unblock_ip() { local client_ip="$1" target_ip="$2" fw::_forward_exists -s "$client_ip" -d "$target_ip" -j LOG --log-prefix "wgctl-dropped:" \ && iptables -D FORWARD -s "$client_ip" -d "$target_ip" -j LOG --log-prefix "wgctl-dropped: " --log-level 4 2>/dev/null || true fw::_forward_exists -s "$client_ip" -d "$target_ip" -j DROP \ && iptables -D FORWARD -s "$client_ip" -d "$target_ip" -j DROP 2>/dev/null || true } function fw::block_port() { local client_ip="$1" target_ip="$2" port="$3" proto="${4:-tcp}" fw::_forward_exists -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j DROP \ || iptables -I FORWARD 1 -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j DROP fw::_forward_exists -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" \ || iptables -I FORWARD 1 -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" } function fw::unblock_port() { local client_ip="$1" target_ip="$2" port="$3" proto="${4:-tcp}" fw::_forward_exists -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j DROP \ && iptables -D FORWARD -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j DROP 2>/dev/null || true } function fw::block_all() { local client_ip="$1" client_name="$2" iptables -A FORWARD -s "$client_ip" -j DROP log::debug "Blocked all traffic from: ${client_ip}" } function fw::unblock_all() { local client_ip="$1" iptables -D FORWARD -s "$client_ip" -j DROP 2>/dev/null || true monitor::unwatch "$client_ip" log::debug "Unblocked all traffic from: ${client_ip}" } function fw::block_subnet() { local client_ip="$1" target_subnet="$2" fw::_forward_exists -s "$client_ip" -d "$target_subnet" -j DROP \ || iptables -A FORWARD -s "$client_ip" -d "$target_subnet" -j DROP fw::_forward_exists -s "$client_ip" -d "$target_subnet" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" \ || iptables -A FORWARD -s "$client_ip" -d "$target_subnet" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" log::wg_block "Blocked ${client_ip} → subnet ${target_subnet}" } function fw::unblock_subnet() { local client_ip="$1" target_subnet="$2" fw::_forward_exists -s "$client_ip" -d "$target_subnet" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" \ && iptables -D FORWARD -s "$client_ip" -d "$target_subnet" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" 2>/dev/null || true fw::_forward_exists -s "$client_ip" -d "$target_subnet" -j NFLOG --nflog-group 1 --nflog-prefix "wgctl-drop:" \ && iptables -D FORWARD -s "$client_ip" -d "$target_subnet" -j DROP 2>/dev/null || true log::wg_unblock "Unblocked ${client_ip} → subnet ${target_subnet}" } function fw::allow_ip() { local client_ip="$1" target_ip="$2" fw::_forward_exists -s "$client_ip" -d "$target_ip" -j ACCEPT \ || iptables -I FORWARD 1 -s "$client_ip" -d "$target_ip" -j ACCEPT } function fw::unallow_ip() { local client_ip="$1" target_ip="$2" fw::_forward_exists -s "$client_ip" -d "$target_ip" -j ACCEPT \ && iptables -D FORWARD -s "$client_ip" -d "$target_ip" -j ACCEPT 2>/dev/null || true } function fw::allow_port() { local client_ip="$1" target_ip="$2" port="$3" proto="${4:-tcp}" fw::_forward_exists -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j ACCEPT \ || iptables -I FORWARD 1 -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j ACCEPT } function fw::unallow_port() { local client_ip="$1" target_ip="$2" port="$3" proto="${4:-tcp}" fw::_forward_exists -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j ACCEPT \ && iptables -D FORWARD -s "$client_ip" -d "$target_ip" -p "$proto" --dport "$port" -j ACCEPT 2>/dev/null || true } function fw::flush_peer() { local client_ip="${1:?client_ip required}" log::debug "flush_peer: starting for $client_ip" # Collect line numbers into array local linenums=() while IFS= read -r linenum; do [[ -n "$linenum" ]] && linenums+=("$linenum") done < <(iptables -L FORWARD -n --line-numbers | grep -F "$client_ip" | awk '{print $1}') # Delete in reverse order (highest number first) local count=0 local i for (( i=${#linenums[@]}-1; i>=0; i-- )); do iptables -D FORWARD "${linenums[$i]}" 2>/dev/null || true (( count++ )) || true done log::debug "flush_peer: removed $count FORWARD rules for: $client_ip" }