Iptables generator funciton bugfix
This commit is contained in:
@@ -39,7 +39,10 @@ describe("buildHostIptablesScripts", () => {
|
|||||||
|
|
||||||
expect(res.success).toBe(true);
|
expect(res.success).toBe(true);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0FWD -s 10.0.0.2/32 -j ACCEPT",
|
"iptables -A WGUI0FWD -s 10.0.0.2/32 -o eth0 -j ACCEPT",
|
||||||
|
);
|
||||||
|
expect(res.post_up).toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.2/32 -o wgui0 -j ACCEPT",
|
||||||
);
|
);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0IN -s 10.0.0.2/32 -j ACCEPT",
|
"iptables -A WGUI0IN -s 10.0.0.2/32 -j ACCEPT",
|
||||||
@@ -67,7 +70,10 @@ describe("buildHostIptablesScripts", () => {
|
|||||||
|
|
||||||
expect(res.success).toBe(true);
|
expect(res.success).toBe(true);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0FWD -s 10.0.0.3/32 -p tcp -m multiport --dports 80,443 -j ACCEPT",
|
"iptables -A WGUI0FWD -s 10.0.0.3/32 -o eth0 -p tcp -m multiport --dports 80,443 -j ACCEPT",
|
||||||
|
);
|
||||||
|
expect(res.post_up).toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.3/32 -o wgui0 -p tcp -m multiport --dports 80,443 -j ACCEPT",
|
||||||
);
|
);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0IN -s 10.0.0.3/32 -p tcp -m multiport --dports 80,443 -j ACCEPT",
|
"iptables -A WGUI0IN -s 10.0.0.3/32 -p tcp -m multiport --dports 80,443 -j ACCEPT",
|
||||||
@@ -95,10 +101,16 @@ describe("buildHostIptablesScripts", () => {
|
|||||||
|
|
||||||
expect(res.success).toBe(true);
|
expect(res.success).toBe(true);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0FWD -s 10.0.0.4/32 -p tcp --dport 53 -j ACCEPT",
|
"iptables -A WGUI0FWD -s 10.0.0.4/32 -o eth0 -p tcp --dport 53 -j ACCEPT",
|
||||||
);
|
);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0FWD -s 10.0.0.4/32 -p udp --dport 53 -j ACCEPT",
|
"iptables -A WGUI0FWD -s 10.0.0.4/32 -o eth0 -p udp --dport 53 -j ACCEPT",
|
||||||
|
);
|
||||||
|
expect(res.post_up).toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.4/32 -o wgui0 -p tcp --dport 53 -j ACCEPT",
|
||||||
|
);
|
||||||
|
expect(res.post_up).toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.4/32 -o wgui0 -p udp --dport 53 -j ACCEPT",
|
||||||
);
|
);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0IN -s 10.0.0.4/32 -p tcp --dport 53 -j ACCEPT",
|
"iptables -A WGUI0IN -s 10.0.0.4/32 -p tcp --dport 53 -j ACCEPT",
|
||||||
@@ -184,7 +196,7 @@ describe("buildHostIptablesScripts", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("all access accepts the client on forward and input regardless of host_subnet", () => {
|
test("all access scopes same-host forward traffic to the host's own subnet", () => {
|
||||||
const res = buildHostIptablesScripts({
|
const res = buildHostIptablesScripts({
|
||||||
...base,
|
...base,
|
||||||
host_subnet: "10.6.0.0/24",
|
host_subnet: "10.6.0.0/24",
|
||||||
@@ -199,13 +211,14 @@ describe("buildHostIptablesScripts", () => {
|
|||||||
|
|
||||||
expect(res.success).toBe(true);
|
expect(res.success).toBe(true);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0FWD -s 10.0.0.7/32 -j ACCEPT",
|
"iptables -A WGUI0FWD -s 10.0.0.7/32 -o eth0 -j ACCEPT",
|
||||||
);
|
);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0IN -s 10.0.0.7/32 -j ACCEPT",
|
"iptables -A WGUI0FWD -s 10.0.0.7/32 -o wgui0 -d 10.6.0.0/24 -j ACCEPT",
|
||||||
|
);
|
||||||
|
expect(res.post_up).toContain(
|
||||||
|
"iptables -A WGUI0IN -s 10.0.0.7/32 -d 10.6.0.0/24 -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 mirrored onto both forward and input chains", () => {
|
test("port-only rules are mirrored onto both forward and input chains", () => {
|
||||||
@@ -228,13 +241,76 @@ describe("buildHostIptablesScripts", () => {
|
|||||||
|
|
||||||
expect(res.success).toBe(true);
|
expect(res.success).toBe(true);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0FWD -s 10.0.0.8/32 -p tcp --dport 53 -j ACCEPT",
|
"iptables -A WGUI0FWD -s 10.0.0.8/32 -o eth0 -p tcp --dport 53 -j ACCEPT",
|
||||||
|
);
|
||||||
|
expect(res.post_up).toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.8/32 -o wgui0 -p tcp --dport 53 -j ACCEPT",
|
||||||
);
|
);
|
||||||
expect(res.post_up).toContain(
|
expect(res.post_up).toContain(
|
||||||
"iptables -A WGUI0IN -s 10.0.0.8/32 -p tcp --dport 53 -j ACCEPT",
|
"iptables -A WGUI0IN -s 10.0.0.8/32 -p tcp --dport 53 -j ACCEPT",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("client-to-client traffic on the same host is accepted via the scoped forward rule", () => {
|
||||||
|
const res = buildHostIptablesScripts({
|
||||||
|
...base,
|
||||||
|
host_subnet: "10.0.0.0/24",
|
||||||
|
clients: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
wg_ip_address: "10.0.0.2",
|
||||||
|
rules: [{ rule_type: "all" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.success).toBe(true);
|
||||||
|
expect(res.post_up).toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.2/32 -o wgui0 -d 10.0.0.0/24 -j ACCEPT",
|
||||||
|
);
|
||||||
|
expect(res.post_up).toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.2/32 -o eth0 -j ACCEPT",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("clients cannot jump to another host on the same machine", () => {
|
||||||
|
const res = buildHostIptablesScripts({
|
||||||
|
...base,
|
||||||
|
host_subnet: "10.0.0.0/24",
|
||||||
|
clients: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
wg_ip_address: "10.0.0.2",
|
||||||
|
rules: [{ rule_type: "all" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
wg_ip_address: "10.0.0.3",
|
||||||
|
rules: [{ rule_type: "all" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.success).toBe(true);
|
||||||
|
const post_up = res.post_up ?? "";
|
||||||
|
|
||||||
|
expect(post_up).not.toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.2/32 -j ACCEPT",
|
||||||
|
);
|
||||||
|
expect(post_up).not.toContain(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.3/32 -j ACCEPT",
|
||||||
|
);
|
||||||
|
|
||||||
|
const scoped_accept_index = post_up.indexOf(
|
||||||
|
"iptables -A WGUI0FWD -s 10.0.0.2/32 -o wgui0 -d 10.0.0.0/24 -j ACCEPT",
|
||||||
|
);
|
||||||
|
const catch_all_drop_index = post_up.indexOf(
|
||||||
|
"iptables -A WGUI0FWD -j DROP",
|
||||||
|
);
|
||||||
|
expect(scoped_accept_index).toBeGreaterThan(-1);
|
||||||
|
expect(catch_all_drop_index).toBeGreaterThan(scoped_accept_index);
|
||||||
|
});
|
||||||
|
|
||||||
test("rejects oversized host id", () => {
|
test("rejects oversized host id", () => {
|
||||||
const res = buildHostIptablesScripts({
|
const res = buildHostIptablesScripts({
|
||||||
...base,
|
...base,
|
||||||
|
|||||||
@@ -85,14 +85,18 @@ function acceptLines({
|
|||||||
source,
|
source,
|
||||||
protocol,
|
protocol,
|
||||||
ports,
|
ports,
|
||||||
host_wg_ip,
|
wg_interface,
|
||||||
|
target_interface,
|
||||||
|
host_subnet,
|
||||||
}: {
|
}: {
|
||||||
forward_chain: string;
|
forward_chain: string;
|
||||||
input_chain: string;
|
input_chain: string;
|
||||||
source: string;
|
source: string;
|
||||||
protocol?: string;
|
protocol?: string;
|
||||||
ports: string[];
|
ports: string[];
|
||||||
host_wg_ip?: string;
|
wg_interface: string;
|
||||||
|
target_interface: string;
|
||||||
|
host_subnet?: string;
|
||||||
}) {
|
}) {
|
||||||
const lines: string[] = [];
|
const lines: string[] = [];
|
||||||
const protocols = protocolsForRule({
|
const protocols = protocolsForRule({
|
||||||
@@ -114,6 +118,19 @@ function acceptLines({
|
|||||||
joinArgs([
|
joinArgs([
|
||||||
`iptables -A ${forward_chain}`,
|
`iptables -A ${forward_chain}`,
|
||||||
`-s ${source}`,
|
`-s ${source}`,
|
||||||
|
`-o ${target_interface}`,
|
||||||
|
proto ? `-p ${proto}` : undefined,
|
||||||
|
port_match_str,
|
||||||
|
`-j ACCEPT`,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
lines.push(
|
||||||
|
joinArgs([
|
||||||
|
`iptables -A ${forward_chain}`,
|
||||||
|
`-s ${source}`,
|
||||||
|
`-o ${wg_interface}`,
|
||||||
|
host_subnet ? `-d ${host_subnet}` : undefined,
|
||||||
proto ? `-p ${proto}` : undefined,
|
proto ? `-p ${proto}` : undefined,
|
||||||
port_match_str,
|
port_match_str,
|
||||||
`-j ACCEPT`,
|
`-j ACCEPT`,
|
||||||
@@ -124,7 +141,7 @@ function acceptLines({
|
|||||||
joinArgs([
|
joinArgs([
|
||||||
`iptables -A ${input_chain}`,
|
`iptables -A ${input_chain}`,
|
||||||
`-s ${source}`,
|
`-s ${source}`,
|
||||||
host_wg_ip ? `-d ${host_wg_ip}` : undefined,
|
host_subnet ? `-d ${host_subnet}` : undefined,
|
||||||
proto ? `-p ${proto}` : undefined,
|
proto ? `-p ${proto}` : undefined,
|
||||||
port_match_str,
|
port_match_str,
|
||||||
`-j ACCEPT`,
|
`-j ACCEPT`,
|
||||||
@@ -176,9 +193,7 @@ export default function buildHostIptablesScripts({
|
|||||||
const { forward, input } = deriveIptablesChainNames({ host_id });
|
const { forward, input } = deriveIptablesChainNames({ host_id });
|
||||||
|
|
||||||
const masquerade_match = scoped_subnet ? `-s ${scoped_subnet} ` : ``;
|
const masquerade_match = scoped_subnet ? `-s ${scoped_subnet} ` : ``;
|
||||||
const accept_lines: string[] = [
|
const accept_lines: string[] = [];
|
||||||
`iptables -A ${forward} -o ${interface_name} -j DROP`,
|
|
||||||
];
|
|
||||||
const host_clients = clients || [];
|
const host_clients = clients || [];
|
||||||
|
|
||||||
for (let i = 0; i < host_clients.length; i++) {
|
for (let i = 0; i < host_clients.length; i++) {
|
||||||
@@ -225,10 +240,25 @@ export default function buildHostIptablesScripts({
|
|||||||
|
|
||||||
if (rule.rule_type == "all") {
|
if (rule.rule_type == "all") {
|
||||||
accept_lines.push(
|
accept_lines.push(
|
||||||
`iptables -A ${forward} -s ${source} -j ACCEPT`,
|
joinArgs([
|
||||||
scoped_subnet
|
`iptables -A ${forward}`,
|
||||||
? `iptables -A ${input} -s ${source} -d ${scoped_subnet} -j ACCEPT`
|
`-s ${source}`,
|
||||||
: `iptables -A ${input} -s ${source} -j ACCEPT`,
|
`-o ${target_interface}`,
|
||||||
|
`-j ACCEPT`,
|
||||||
|
]),
|
||||||
|
joinArgs([
|
||||||
|
`iptables -A ${forward}`,
|
||||||
|
`-s ${source}`,
|
||||||
|
`-o ${interface_name}`,
|
||||||
|
scoped_subnet ? `-d ${scoped_subnet}` : undefined,
|
||||||
|
`-j ACCEPT`,
|
||||||
|
]),
|
||||||
|
joinArgs([
|
||||||
|
`iptables -A ${input}`,
|
||||||
|
`-s ${source}`,
|
||||||
|
scoped_subnet ? `-d ${scoped_subnet}` : undefined,
|
||||||
|
`-j ACCEPT`,
|
||||||
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -250,7 +280,9 @@ export default function buildHostIptablesScripts({
|
|||||||
source,
|
source,
|
||||||
protocol: rule.protocol || "any",
|
protocol: rule.protocol || "any",
|
||||||
ports: parsed_ports.ports,
|
ports: parsed_ports.ports,
|
||||||
host_wg_ip: scoped_subnet,
|
wg_interface: interface_name,
|
||||||
|
target_interface,
|
||||||
|
host_subnet: scoped_subnet,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user