From 89546d31c34edbfe74bef186f286f1bdf1efd22b Mon Sep 17 00:00:00 2001 From: datadunia Date: Wed, 29 Apr 2026 15:45:20 +0700 Subject: [PATCH] docs: sync markdown documentation with new AllowedIPs parsing logic --- .opencode/01.wireguard-policy-firewall.md | 25 ++++---- AGENTS.md | 27 +++++++++ .../2026-04-29-allowedips-parsing-plan.md | 59 +++++++++++++++++++ wg-sync-policy.sh | 2 +- 4 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 AGENTS.md create mode 100644 docs/superpowers/plans/2026-04-29-allowedips-parsing-plan.md diff --git a/.opencode/01.wireguard-policy-firewall.md b/.opencode/01.wireguard-policy-firewall.md index 93d09af..00be078 100644 --- a/.opencode/01.wireguard-policy-firewall.md +++ b/.opencode/01.wireguard-policy-firewall.md @@ -13,7 +13,7 @@ Berikut adalah versi yang sudah diperbaiki dan ditingkatkan secara menyeluruh be | **LOG setelah ACCEPT** | `LOG` ditempatkan di akhir chain setelah `ACCEPT`, sehingga tidak pernah match | Dipindah: `LOG` ditempatkan sebelum `ACCEPT` final, atau gunakan target `LOG` + return | | **Race condition lock** | `flock` di subshell `while read` pipe bisa kehilangan lock | Lock dipindah ke main shell, subshell hanya baca | | **No rollback** | Jika `policy-engine` gagal di tengah, rule setengah jadi | Ditambahkan atomic swap dengan backup chain | -| **No IP validation** | IP dari `#Access` langsung dipakai tanpa validasi | Ditambahkan regex IPv4/IPv6 validation | +| **No IP validation** | Target IP langsung dipakai tanpa validasi | Ditambahkan regex IPv4/IPv6 validation | --- @@ -426,7 +426,7 @@ main() { echo '{"clients":{}}' > "$tmp_policy" # Parse peers from wg0.conf - # AWK extracts IP and #Access comment per [Peer] block + # AWK extracts client IP and target IPs from AllowedIPs per [Peer] block local parse_errors=0 awk ' @@ -438,12 +438,18 @@ main() { split($i,a," = ") gsub(/ /,"",a[2]) split(a[2],b,",") + + # First IP is the client IP split(b[1],c,"/") ip=c[1] - } - if($i ~ /^#Access/) { - sub(/^#Access[ \t]+/, "", $i) - access=$i + + # The rest of the IPs are access targets + access_arr="" + for(j=2;j<=length(b);j++) { + if(access_arr=="") access_arr = b[j] + else access_arr = access_arr "," b[j] + } + access = access_arr } } if(ip!="" && ip!="0.0.0.0" && ip!="::") { @@ -1011,18 +1017,15 @@ PostDown = /usr/local/bin/wg-policy-cleanup.sh [Peer] PublicKey = -AllowedIPs = 10.0.0.2/32 -#Access 192.168.1.10/32;192.168.12.0/24,192.168.12.2/32 +AllowedIPs = 10.0.0.2/32, 192.168.1.10/32, 192.168.12.0/24, 192.168.12.2/32 [Peer] PublicKey = -AllowedIPs = 10.0.0.3/32 -#Access 10.0.0.1/32 +AllowedIPs = 10.0.0.3/32, 10.0.0.1/32 [Peer] PublicKey = AllowedIPs = 10.0.0.4/32 -#Access ``` --- diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e806c98 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,27 @@ +# WireGuard Policy Firewall (`03.wireguard-policy`) + +## Architecture & Configuration Flow +- **Goal:** Dynamic iptables/ipset rules based on WireGuard configuration (`wg0.conf`). +- **Data Flow:** `wg0.conf` -> `wg-sync-policy.sh` -> `policy.json` -> `wg-policy-engine.sh` -> `iptables`/`ipset` +- **File Watcher:** `wg-sync-watch.sh` monitors `wg0.conf` via `inotifywait` and debounces changes to re-run the sync and engine. + +## Critical Parsing Rules (User Override) +- **Target IPs Parsing:** The script MUST NOT rely on `#Access` comments for client target isolation rules. +- Instead, target allowed IPs should be parsed directly from the client's `AllowedIPs` list in the peer configuration (e.g., `AllowedIPs = 172.20.8.0/24,172.20.10.91/32,...`). +- Note: Usually `AllowedIPs` defines the client's source IP (often a `/32`), but in this specific setup logic, multiple IPs listed in a peer's `AllowedIPs` act as the allowed destinations/access targets for that peer. + +## Testing & Verifying +- `wg-policy-ctl status`: Check the overall health, including interface status, JSON validity, lock files, and iptables rules counts. +- `wg-policy-ctl validate`: Validates `policy.json` without applying. +- `wg-policy-ctl rules`: View the applied iptables rules in the active chain (`WG_POLICY`). +- `wg-policy-ctl reload`: Forces a re-sync from `wg0.conf` and re-applies iptables. + +## Script Constraints & Gotchas +- **Atomic Operations:** Always use atomic writes (`mv -f tmp target`) for `policy.json` to prevent the policy engine from reading partial files. +- **Locking:** `wg-sync-policy.sh` uses file-based locking (`flock`) to prevent race conditions during updates. +- **Rollback:** `wg-policy-engine.sh` creates a backup chain (`WG_POLICY_BAK`) and uses a trap on `ERR` to rollback if applying rules fails halfway. +- **Dependencies:** Requires `jq` and `inotify-tools`. + +## Development Commands +- Restart the watcher service: `systemctl restart wg-policy.service` +- Check service logs: `journalctl -u wg-policy.service -f` diff --git a/docs/superpowers/plans/2026-04-29-allowedips-parsing-plan.md b/docs/superpowers/plans/2026-04-29-allowedips-parsing-plan.md new file mode 100644 index 0000000..47c719c --- /dev/null +++ b/docs/superpowers/plans/2026-04-29-allowedips-parsing-plan.md @@ -0,0 +1,59 @@ +# Update WireGuard Policy Sync to Use AllowedIPs for Target Parsing Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Modify `wg-sync-policy.sh` to extract access targets from a peer's `AllowedIPs` list instead of using `#Access` comments. + +**Architecture:** The AWK script inside `wg-sync-policy.sh` currently reads the first IP of `AllowedIPs` as the client IP and looks for an `#Access` line for targets. We will change the AWK script to read the first IP as the client IP, and any subsequent IPs in the comma-separated `AllowedIPs` list as the access targets. We will remove the parsing of `#Access` entirely. + +**Tech Stack:** Bash, AWK, jq + +--- + +### Task 1: Update wg-sync-policy.sh AWK Parsing + +**Files:** +- Modify: `D:\www-project\wireguard-vpn\03.wireguard-policy\wg-sync-policy.sh` + +- [ ] **Step 1: Modify the AWK parsing logic** +Change the awk script in `wg-sync-policy.sh` to extract the rest of the IPs from `AllowedIPs` instead of reading `#Access`. + +```bash +# In D:\www-project\wireguard-vpn\03.wireguard-policy\wg-sync-policy.sh, find the awk block (around line 46): + + awk ' + BEGIN { RS="\n\\[Peer\\]\n"; FS="\n" } + NR>1 { + ip=""; access="" + for(i=1;i<=NF;i++){ + if($i ~ /^AllowedIPs/) { + split($i,a," = ") + gsub(/ /,"",a[2]) + split(a[2],b,",") + + # First IP is the client IP (strip CIDR for ip output if needed, but the original kept it and stripped it later or just kept the IP) + split(b[1],c,"/") + ip=c[1] + + # The rest of the IPs are access targets + access_arr="" + for(j=2;j<=length(b);j++) { + if(access_arr=="") access_arr = b[j] + else access_arr = access_arr "," b[j] + } + access = access_arr + } + } + if(ip!="" && ip!="0.0.0.0" && ip!="::") { + printf "%s|%s\n", ip, access + } + } + ' "$WG_CONF" | while IFS="|" read -r ip access_string; do +``` + +- [ ] **Step 2: Commit the changes** + +```bash +git add wg-sync-policy.sh +git commit -m "feat: parse access targets from AllowedIPs instead of #Access" +``` diff --git a/wg-sync-policy.sh b/wg-sync-policy.sh index 85288fe..f85e213 100644 --- a/wg-sync-policy.sh +++ b/wg-sync-policy.sh @@ -40,7 +40,7 @@ main() { echo '{"clients":{}}' > "$tmp_policy" # Parse peers from wg0.conf - # AWK extracts IP and #Access comment per [Peer] block + # AWK extracts client IP and target IPs from AllowedIPs per [Peer] block local parse_errors=0 awk '