16 KiB
Firewall InitNetwork Fix — INPUT vs FORWARD Chain Bugs
TL;DR
Quick Summary: Fix 3 bugs in
InitNetwork()that prevent WireGuard clients from reaching the server and Docker containers. ICMP echo-reply blocked, Docker DNAT traffic dropped, and missing base INPUT rules.Deliverables:
- Fixed
nftables_linux.goInitNetwork() with correct ICMP, Docker bridge, and INPUT rules- Updated
manager.goif needed- Server rebuilt and deployed via
update.sh --forceEstimated Effort: Short Parallel Execution: YES - 2 waves Critical Path: Task 1 → Task 4 (verify)
Context
Original Request
User reported firewall rules from dashboard not working. Traced through multiple debugging sessions to find 3 root-cause bugs in InitNetwork() base rules:
icmp type echo-requestonly allows incoming pings TO server, not echo-reply FROM peers- No FORWARD rules for Docker bridge — WireGuard traffic DNAT'd to containers gets dropped
- Server→peer traffic works (OUTPUT default accept) but replies hit INPUT chain and get dropped
Interview Summary
- Key Discussions: Extensive debugging on live server (172.20.8.191). User tested each fix manually via SSH. Confirmed Docker DNAT intercepts port 80 traffic via iptables PREROUTING, redirecting to container 172.24.0.4.
- Research Findings: Docker uses iptables DNAT while NexusGuard uses nftables filter — both coexist. Traffic flow: WireGuard → INPUT (nftables) → ACCEPT → Docker PREROUTING (iptables DNAT) → destination changes to container IP → FORWARD chain (nftables) → DROP (no bridge rule).
- User Constraints: No local binary builds (Docker only). No temp/debug files. Admin-only firewall (JWT protected).
Metis Review (if consulted)
N/A — bugs are clear from source code analysis, no ambiguity requiring consultation.
Work Objectives
Core Objective
Fix 3 bugs in InitNetwork() that prevent WireGuard peer-to-server and peer-to-Docker-container connectivity.
Concrete Deliverables
- Fixed
apps/server-core/internal/firewall/nftables_linux.goInitNetwork() - Fixed
apps/server-core/internal/firewall/manager.goif interface changes needed - Server rebuilt and deployed
- nftables verified working on live server
Definition of Done
nft list chain ip nexusguard inputshowsmeta l4proto icmp accept(noticmp type echo-request)nft list chain ip nexusguard forwardshowsfwd_wg_dockerrules for 172.24.0.0/16 and 172.17.0.0/16- Client (gogo3 10.172.21.3) can ping server (10.172.21.1)
- Server (10.172.21.1) can ping client (10.172.21.3)
- Client can curl http://10.172.21.1:80 and get 200
Must Have
meta l4proto icmpreplacesicmp type echo-requestin INPUT chainfwd_wg_dockerrules added to FORWARD chain in InitNetwork()- Existing peer routing rules (AddForwardRule) still work
- Existing DB firewall rules (syncRuleToFirewall) still work
Must NOT Have (Guardrails)
- Do NOT
nft flush table nexusguard— destroys all rules - Do NOT change the FirewallRule model or API endpoints
- Do NOT modify peer_sync.go or devices.go
- Do NOT create temp/debug files in project root
- Do NOT change the firewall chain routing logic (dest==server→INPUT, else→FORWARD)
- Do NOT remove the
input_wg_droporwg_isolation_defaultbase rules
Verification Strategy
ZERO HUMAN INTERVENTION — ALL verification is agent-executed. No exceptions.
Test Decision
- Infrastructure exists: NO (no nftables unit tests)
- Automated tests: None (nftables rules tested via live server SSH)
- Framework: None needed — live server verification
QA Policy
Every task includes agent-executed QA scenarios.
Evidence saved to .sisyphus/evidence/task-{N}-{scenario-slug}.{ext}.
- nft verification: SSH to server, run nft commands, verify rules present
- Connectivity: SSH to server, run ping/curl tests
Execution Strategy
Parallel Execution Waves
Wave 1 (Start Immediately — 1 agent):
├── Task 1: Fix InitNetwork() in nftables_linux.go (quick)
Wave 2 (After Wave 1 — 1 agent):
├── Task 2: Commit + Push + Deploy (quick)
├── Task 3: Verify nft rules on live server (quick)
Wave FINAL (After Wave 2 — reviewer):
├── Task F1: Plan compliance audit (oracle)
├── Task F2: Code quality review (unspecified-high)
├── Task F3: Real manual QA (unspecified-high)
├── Task F4: Scope fidelity check (deep)
-> F1-F4 can run in parallel
Critical Path: Task 1 → Task 2 → Task 3 → F1-F4
Dependency Matrix
| Task | Depends On | Blocks |
|---|---|---|
| Task 1 | None | Task 2 |
| Task 2 | Task 1 | Task 3 |
| Task 3 | Task 2 | F1-F4 |
| F1-F4 | Task 3 | None |
Agent Dispatch Summary
- Wave 1: T1 →
quick - Wave 2: T2 →
quick, T3 →quick - FINAL: F1 →
oracle, F2 →unspecified-high, F3 →unspecified-high, F4 →deep
TODOs
-
1. Fix InitNetwork() in nftables_linux.go
What to do:
- In
apps/server-core/internal/firewall/nftables_linux.go, line 48: changeicmp type echo-requesttometa l4proto icmp. Also update the comment frominput_icmptoinput_icmp_all. - In the same function, after the
input_wg_droprule block (around line 64), add Docker bridge accept rules to FORWARD chain:nft insert rule ip nexusguard forward ip saddr <wgSubnet> ip daddr 172.24.0.0/16 accept comment "fwd_wg_docker"nft insert rule ip nexusguard forward ip saddr <wgSubnet> ip daddr 172.17.0.0/16 accept comment "fwd_wg_docker0"
- These Docker rules should be inserted AFTER
fwd_estaband BEFORE thewg_isolationdrop rule. Usenft insert rulewith position or append after fwd_estab. - Add dedup checks (same pattern as existing rules):
grep -q 'fwd_wg_docker'before inserting.
Must NOT do:
- Do NOT change AddForwardRule, AddFirewallRule, AddInputFirewallRule, or RemoveFirewallRule
- Do NOT change the chain routing logic in syncRuleToFirewall
- Do NOT flush or recreate any chains
- Do NOT change manager.go interface
Recommended Agent Profile:
- Category:
quick- Reason: Single-file change, 3 specific line edits, clear patterns to follow
- Skills: []
- No special skills needed — straightforward Go code edit
Parallelization:
- Can Run In Parallel: NO
- Parallel Group: Wave 1 (solo)
- Blocks: Task 2 (commit/deploy)
- Blocked By: None (can start immediately)
References:
apps/server-core/internal/firewall/nftables_linux.go:25-68— InitNetwork() function, all 3 bugs are hereapps/server-core/internal/firewall/nftables_linux.go:30-38— existing FORWARD chain setup (fwd_estab, wg_isolation) — Docker rules go between theseapps/server-core/internal/firewall/nftables_linux.go:40-64— existing INPUT chain setup — ICMP fix at line 48apps/server-core/main.go:210-259— startup re-apply code that calls AddForwardRule and AddInputFirewallRule — do NOT modifyapps/server-core/internal/firewall/manager.go:5-18— NetManager interface — do NOT modify
Acceptance Criteria:
- Line 48 reads
meta l4proto icmpnoticmp type echo-request - Comment reads
input_icmp_allnotinput_icmp - FORWARD chain has dedup check for
fwd_wg_dockerbefore inserting go vet ./internal/firewall/...passes- No other lines in InitNetwork() changed
QA Scenarios:
Scenario: Verify ICMP rule is correct Tool: Bash (grep) Steps: 1. grep "meta l4proto icmp" apps/server-core/internal/firewall/nftables_linux.go 2. grep "icmp type echo-request" apps/server-core/internal/firewall/nftables_linux.go Expected Result: First grep returns match, second grep returns nothing Evidence: .sisyphus/evidence/task-1-icmp-rule.txt Scenario: Verify Docker bridge rules exist Tool: Bash (grep) Steps: 1. grep "fwd_wg_docker" apps/server-core/internal/firewall/nftables_linux.go 2. grep "172.24.0.0/16" apps/server-core/internal/firewall/nftables_linux.go 3. grep "172.17.0.0/16" apps/server-core/internal/firewall/nftables_linux.go Expected Result: All 3 greps return matches Evidence: .sisyphus/evidence/task-1-docker-rules.txt Scenario: Verify dedup check pattern Tool: Bash (grep) Steps: 1. grep "fwd_wg_docker" apps/server-core/internal/firewall/nftables_linux.go | head -5 Expected Result: Shows both the grep check command AND the nft insert command Evidence: .sisyphus/evidence/task-1-dedup-pattern.txtCommit: YES
- Message:
fix(nftables): InitNetwork ICMP all, Docker bridge accept, base INPUT rules - Files:
apps/server-core/internal/firewall/nftables_linux.go - Pre-commit:
go vet ./internal/firewall/...
- In
-
2. Commit, Push, Deploy to Server
What to do:
- In
apps/server-core/:git add -A && git commitwith the fix message, thengit push - In root
Nexus-Guard-Suite/:git add apps/server-core && git commit && git push - SSH to server:
cd /root/Nexus-Guard-Suite && bash update.sh --force - Wait for deployment to complete
Must NOT do:
- Do NOT build binary locally
- Do NOT create temp files on server
- Do NOT use
nft flushon server - Do NOT modify any code files
Recommended Agent Profile:
- Category:
quick- Reason: Simple git + SSH commands, well-documented in AGENTS.md
- Skills: []
Parallelization:
- Can Run In Parallel: NO
- Parallel Group: Wave 2 (solo)
- Blocks: Task 3 (verify)
- Blocked By: Task 1 (code change)
References:
D:\www-project\NexusGuard\connect_remote.txt— SSH credentials (HOST=172.20.8.191, USER=root)D:\www-project\NexusGuard\update.sh— Docker rebuild script
Acceptance Criteria:
- Submodule HEAD updated (new commit hash)
- Root repo HEAD updated
- Server container restarted successfully
docker psshows server-core running
QA Scenarios:
Scenario: Verify deployment Tool: SSH (bash) Steps: 1. ssh root@172.20.8.191 'docker ps | grep server-core' 2. ssh root@172.20.8.191 'docker logs nexus-guard-suite-server-core-1 2>&1 | tail -5' Expected Result: Container running, logs show clean startup Evidence: .sisyphus/evidence/task-2-deployment.txtCommit: NO (commit done as part of task)
- In
-
3. Verify nftables Rules and Connectivity on Live Server
What to do:
- SSH to server, run
nft list table ip nexusguardand verify:- INPUT chain has
meta l4proto icmp accept comment "input_icmp_all" - FORWARD chain has
fwd_wg_dockerrules for 172.24.0.0/16 and 172.17.0.0/16 - All existing rules intact (server_wg1, input_estab, input_wg_api, etc.)
- INPUT chain has
- Test from server:
ping -c 3 10.172.21.3— should get replies - Ask user to test from client:
ping 10.172.21.1andcurl -v http://10.172.21.1:80 - Verify nft counters increment when traffic flows
Must NOT do:
- Do NOT modify any nft rules during verification
- Do NOT flush or recreate chains
Recommended Agent Profile:
- Category:
quick- Reason: SSH verification commands only
- Skills: []
Parallelization:
- Can Run In Parallel: NO
- Parallel Group: Wave 2 (after Task 2)
- Blocks: F1-F4
- Blocked By: Task 2 (deployment)
References:
D:\www-project\NexusGuard\connect_remote.txt— SSH credentialsD:\www-project\NexusGuard\AGENTS.md— WireGuard AllowedIPs architecture rules
Acceptance Criteria:
- INPUT chain has
meta l4proto icmp(noticmp type echo-request) - FORWARD chain has
fwd_wg_dockerfor 172.24.0.0/16 - FORWARD chain has
fwd_wg_docker0for 172.17.0.0/16 - Server can ping gogo3 (10.172.21.3)
- Client can ping server (10.172.21.1)
- Client can curl http://10.172.21.1:80
QA Scenarios:
Scenario: Verify INPUT chain ICMP rule Tool: SSH (bash) Steps: 1. ssh root@172.20.8.191 'nft list chain ip nexusguard input | grep icmp' Expected Result: Shows `meta l4proto icmp accept comment "input_icmp_all"` Evidence: .sisyphus/evidence/task-3-input-icmp.txt Scenario: Verify FORWARD chain Docker rules Tool: SSH (bash) Steps: 1. ssh root@172.20.8.191 'nft list chain ip nexusguard forward | grep docker' Expected Result: Shows both fwd_wg_docker (172.24.0.0/16) and fwd_wg_docker0 (172.17.0.0/16) Evidence: .sisyphus/evidence/task-3-forward-docker.txt Scenario: Server ping client Tool: SSH (bash) Steps: 1. ssh root@172.20.8.191 'ping -c 3 10.172.21.3' Expected Result: 3 replies, 0% packet loss Evidence: .sisyphus/evidence/task-3-ping-client.txt Scenario: Client connectivity (requires user) Tool: User prompt Steps: 1. Ask user to run from gogo3 client: `ping 10.172.21.1` 2. Ask user to run from gogo3 client: `curl -v http://10.172.21.1:80` Expected Result: Ping replies, curl returns 200 Evidence: User provides outputCommit: NO
- SSH to server, run
Final Verification Wave (MANDATORY — after ALL implementation tasks)
4 review agents run in PARALLEL. ALL must APPROVE. Rejection → fix → re-run.
-
F1. Plan Compliance Audit —
oracleRead the plan end-to-end. For each "Must Have": verify implementation exists (read file, curl endpoint, check schema). For each "Must NOT Have": search codebase for forbidden patterns — reject with file:line if found. Check evidence files exist in .sisyphus/evidence/. Compare deliverables against plan. Output:Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT -
F2. Code Quality Review —
unspecified-highRungo vet ./...on changed packages. Review all changed files for: empty catches, console.logs in prod code, commented-out code, unused imports. Check AI slop: excessive comments, over-abstraction, generic variable names. Output:Build [PASS/FAIL] | Files [N clean/N issues] | VERDICT -
F3. Real Manual QA —
unspecified-high(equipment: SSH to 172.20.8.191) SSH to server. Run:nft list table ip nexusguardand verify rules. Then test:ping 10.172.21.3from server. From client:ping 10.172.21.1andcurl -v http://10.172.21.1:80. Test negative case: verify that WG isolation default drop still blocks unauthorized traffic. Output:Connectivity [N/N pass] | Firewall [N correct rules] | Negative [PASS/FAIL] | VERDICT -
F4. Scope Fidelity Check —
deepFor each task: read "What to do", read actual diff (git log/diff). Verify 1:1 — everything in spec was built (no missing), nothing beyond spec was built (no creep). Check "Must NOT do" compliance. Flag unauthorized changes. Output:Tasks [N/N compliant] | Contamination [CLEAN/N issues] | VERDICT
Commit Strategy
- Task 1:
fix(nftables): InitNetwork ICMP, Docker bridge, INPUT base rules→apps/server-core/ - Task 2: Submodule push + root push + deploy via
update.sh --force
Success Criteria
Verification Commands
# From server (SSH root@172.20.8.191):
nft list chain ip nexusguard input
# Expected: meta l4proto icmp accept comment "input_icmp_all"
nft list chain ip nexusguard forward
# Expected: fwd_wg_docker accept for 172.24.0.0/16 and 172.17.0.0/16
# From client (gogo3):
ping 10.172.21.1
# Expected: replies
# From server:
ping 10.172.21.3
# Expected: replies
# From client:
curl -s -o /dev/null -w "%{http_code}" http://10.172.21.1:80
# Expected: 200
Final Checklist
- All "Must Have" present
- All "Must NOT Have" absent
- Server deployed and running
- Both peers can ping server
- Server can ping both peers
- Port 80 accessible from WireGuard client