diff --git a/src/functions/backend/setup/build-host-iptables-scripts.test.ts b/src/functions/backend/setup/build-host-iptables-scripts.test.ts index efd5669..f94f2ad 100644 --- a/src/functions/backend/setup/build-host-iptables-scripts.test.ts +++ b/src/functions/backend/setup/build-host-iptables-scripts.test.ts @@ -21,7 +21,7 @@ describe("buildHostIptablesScripts", () => { expect(res.post_up).not.toContain("WGUI0FWD -s"); expect(res.post_down).toContain("iptables -X WGUI0FWD"); expect(res.post_down).toContain( - "iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE 2>/dev/null || true", + "iptables -t nat -D POSTROUTING -j MASQUERADE 2>/dev/null || true", ); }); @@ -67,11 +67,12 @@ describe("buildHostIptablesScripts", () => { expect(res.success).toBe(true); expect(res.post_up).toContain( - "iptables -A WGUI0FWD -s 10.0.0.3/32 -d 192.168.1.10/32 -p tcp -m multiport --dports 80,443 -j ACCEPT", + "iptables -A WGUI0FWD -s 10.0.0.3/32 -p tcp -m multiport --dports 80,443 -j ACCEPT", ); - expect(res.post_up).not.toContain( - "iptables -A WGUI0IN -s 10.0.0.3/32 -d 192.168.1.10/32 -p tcp -m multiport --dports 80,443 -j ACCEPT", + expect(res.post_up).toContain( + "iptables -A WGUI0IN -s 10.0.0.3/32 -p tcp -m multiport --dports 80,443 -j ACCEPT", ); + expect(res.post_up).not.toContain("-d 192.168.1.10/32"); }); test("protocol any with ports emits tcp and udp", () => { @@ -99,6 +100,12 @@ describe("buildHostIptablesScripts", () => { expect(res.post_up).toContain( "iptables -A WGUI0FWD -s 10.0.0.4/32 -p udp --dport 53 -j ACCEPT", ); + expect(res.post_up).toContain( + "iptables -A WGUI0IN -s 10.0.0.4/32 -p tcp --dport 53 -j ACCEPT", + ); + expect(res.post_up).toContain( + "iptables -A WGUI0IN -s 10.0.0.4/32 -p udp --dport 53 -j ACCEPT", + ); }); test("rejects invalid destination", () => { @@ -149,17 +156,17 @@ describe("buildHostIptablesScripts", () => { expect(res.success).toBe(true); expect(res.post_up).toContain( - "iptables -t nat -C POSTROUTING -s 10.2.0.0/24 -o eth0 -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -s 10.2.0.0/24 -o eth0 -j MASQUERADE", + "iptables -t nat -C POSTROUTING -s 10.2.0.0/24 -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -s 10.2.0.0/24 -j MASQUERADE", ); expect(res.post_up).not.toContain( "iptables -t nat -A POSTROUTING -i eth0 -j MASQUERADE", ); expect(res.post_down).toContain( - "iptables -t nat -D POSTROUTING -s 10.2.0.0/24 -o eth0 -j MASQUERADE 2>/dev/null || true", + "iptables -t nat -D POSTROUTING -s 10.2.0.0/24 -j MASQUERADE 2>/dev/null || true", ); }); - test("masquerade falls back to the target interface without a subnet", () => { + test("masquerade without a subnet applies to all postrouting traffic", () => { const res = buildHostIptablesScripts({ ...base, clients: [ @@ -173,11 +180,11 @@ describe("buildHostIptablesScripts", () => { expect(res.success).toBe(true); expect(res.post_up).toContain( - "iptables -t nat -C POSTROUTING -o eth0 -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE", + "iptables -t nat -C POSTROUTING -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -j MASQUERADE", ); }); - test("all access with host_subnet is scoped to the subnet", () => { + test("all access accepts the client on forward and input regardless of host_subnet", () => { const res = buildHostIptablesScripts({ ...base, host_subnet: "10.6.0.0/24", @@ -192,17 +199,16 @@ describe("buildHostIptablesScripts", () => { expect(res.success).toBe(true); expect(res.post_up).toContain( - "iptables -A WGUI0FWD -s 10.0.0.7/32 -d 10.6.0.0/24 -j ACCEPT", + "iptables -A WGUI0FWD -s 10.0.0.7/32 -j ACCEPT", ); expect(res.post_up).toContain( "iptables -A WGUI0IN -s 10.0.0.7/32 -j ACCEPT", ); - expect(res.post_up).not.toContain( - "iptables -A WGUI0FWD -s 10.0.0.7/32 -o eth0 -j ACCEPT", - ); + expect(res.post_up).not.toContain("-d 10.6.0.0/24"); + expect(res.post_up).not.toContain("-o eth0"); }); - test("port-only rules are not mirrored onto the input chain", () => { + test("port-only rules are mirrored onto both forward and input chains", () => { const res = buildHostIptablesScripts({ ...base, clients: [ @@ -224,7 +230,7 @@ describe("buildHostIptablesScripts", () => { expect(res.post_up).toContain( "iptables -A WGUI0FWD -s 10.0.0.8/32 -p tcp --dport 53 -j ACCEPT", ); - expect(res.post_up).not.toContain( + expect(res.post_up).toContain( "iptables -A WGUI0IN -s 10.0.0.8/32 -p tcp --dport 53 -j ACCEPT", ); }); diff --git a/src/functions/backend/setup/build-host-iptables-scripts.ts b/src/functions/backend/setup/build-host-iptables-scripts.ts index 5befcb2..37e23d8 100644 --- a/src/functions/backend/setup/build-host-iptables-scripts.ts +++ b/src/functions/backend/setup/build-host-iptables-scripts.ts @@ -322,6 +322,11 @@ export default function buildHostIptablesScripts({ } } + accept_lines.push( + `# Prevent clients from forwarding traffic back into the WireGuard network`, + `iptables -A ${forward} -o ${interface_name} -j DROP`, + ); + const post_up = [ `#!/bin/bash`, ``,