From f0cc3171690d3c0aa9e5e08128b8922d36c92add Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 29 Apr 2022 14:48:16 +0200 Subject: [PATCH] fw4: refactor family selection for forwarding rules Use the common `infer_family()` helper when parsing `forwarding` sections to simplify the code. Also add some test coverage for the changed code. Signed-off-by: Jo-Philipp Wich --- root/usr/share/ucode/fw4.uc | 32 +-- tests/04_forwardings/01_family_selections | 246 ++++++++++++++++++++++ 2 files changed, 254 insertions(+), 24 deletions(-) create mode 100644 tests/04_forwardings/01_family_selections diff --git a/root/usr/share/ucode/fw4.uc b/root/usr/share/ucode/fw4.uc index 4ca1d79..76360c8 100644 --- a/root/usr/share/ucode/fw4.uc +++ b/root/usr/share/ucode/fw4.uc @@ -2099,7 +2099,7 @@ return { proto: { any: true } }; - f.name ||= `Accept ${fwd.src.any ? "any" : fwd.src.zone.name} to ${fwd.dest.any ? "any" : fwd.dest.zone.name} forwarding`; + f.name ||= `Accept ${fwd.src.any ? "any" : fwd.src.zone.name} to ${fwd.dest.any ? "any" : fwd.dest.zone.name} ${family ? `${this.nfproto(family, true)} ` : ''}forwarding`; f.chain = fwd.src.any ? "forward" : `forward_${fwd.src.zone.name}`; if (fwd.dest.any) @@ -2111,31 +2111,15 @@ return { }; - let family = fwd.family; - /* inherit family restrictions from related zones */ - if (family === 0 || family === null) { - let f1 = fwd.src.zone ? fwd.src.zone.family : 0; - let f2 = fwd.dest.zone ? fwd.dest.zone.family : 0; - - if (f1 && f2 && f1 != f2) { - this.warn_section(data, - `references src ${fwd.src.zone.name} restricted to ${this.nfproto(f1, true)} and dest ${fwd.dest.zone.name} restricted to ${this.nfproto(f2, true)}, ignoring forwarding`); - - return; - } - else if (f1) { - this.warn_section(data, - `inheriting ${this.nfproto(f1, true)} restriction from src ${fwd.src.zone.name}`); - - family = f1; - } - else if (f2) { - this.warn_section(data, - `inheriting ${this.nfproto(f2, true)} restriction from dest ${fwd.dest.zone.name}`); + let family = infer_family(fwd.family, [ + fwd.src?.zone, "source zone", + fwd.dest?.zone, "destination zone" + ]); - family = f2; - } + if (type(family) == "string") { + this.warn_section(data, `${family}, skipping`); + return; } add_rule(family, fwd); diff --git a/tests/04_forwardings/01_family_selections b/tests/04_forwardings/01_family_selections new file mode 100644 index 0000000..c7b0345 --- /dev/null +++ b/tests/04_forwardings/01_family_selections @@ -0,0 +1,246 @@ +Test that the zone family is honoured when setting up inter-zone forwarding rules. + +-- Testcase -- +{% + include("./root/usr/share/firewall4/main.uc", { + getenv: function(varname) { + switch (varname) { + case 'ACTION': + return 'print'; + } + } + }) +%} +-- End -- + +-- File uci/helpers.json -- +{} +-- End -- + +-- File uci/firewall.json -- +{ + "zone": [ + { + "name": "wanA", + "device": [ "eth0" ], + "auto_helper": 0 + }, + + { + "name": "wanB", + "device": [ "eth1" ], + "auto_helper": 0 + }, + + { + "name": "lan", + "device": [ "eth2" ], + "auto_helper": 0 + } + ], + + "forwarding": [ + { + ".description": "This should only allow IPv6 forwarding from lan to wanA", + "src": "lan", + "dest": "wanA", + "family": "IPv6" + }, + + { + ".description": "This should only allow IPv4 forwarding from lan to wanB", + "src": "lan", + "dest": "wanB", + "family": "IPv4" + } + ] +} +-- End -- + +-- Expect stdout -- +table inet fw4 +flush table inet fw4 + +table inet fw4 { + # + # Set definitions + # + + + # + # Defines + # + + define wanA_devices = { "eth0" } + define wanB_devices = { "eth1" } + define lan_devices = { "eth2" } + + # + # User includes + # + + include "/etc/nftables.d/*.nft" + + + # + # Filter rules + # + + chain input { + type filter hook input priority filter; policy drop; + + iifname "lo" accept comment "!fw4: Accept traffic from loopback" + + ct state established,related accept comment "!fw4: Allow inbound established and related flows" + iifname "eth0" jump input_wanA comment "!fw4: Handle wanA IPv4/IPv6 input traffic" + iifname "eth1" jump input_wanB comment "!fw4: Handle wanB IPv4/IPv6 input traffic" + iifname "eth2" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic" + } + + chain forward { + type filter hook forward priority filter; policy drop; + + ct state established,related accept comment "!fw4: Allow forwarded established and related flows" + iifname "eth0" jump forward_wanA comment "!fw4: Handle wanA IPv4/IPv6 forward traffic" + iifname "eth1" jump forward_wanB comment "!fw4: Handle wanB IPv4/IPv6 forward traffic" + iifname "eth2" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic" + } + + chain output { + type filter hook output priority filter; policy drop; + + oifname "lo" accept comment "!fw4: Accept traffic towards loopback" + + ct state established,related accept comment "!fw4: Allow outbound established and related flows" + oifname "eth0" jump output_wanA comment "!fw4: Handle wanA IPv4/IPv6 output traffic" + oifname "eth1" jump output_wanB comment "!fw4: Handle wanB IPv4/IPv6 output traffic" + oifname "eth2" jump output_lan comment "!fw4: Handle lan IPv4/IPv6 output traffic" + } + + chain handle_reject { + meta l4proto tcp reject with tcp reset comment "!fw4: Reject TCP traffic" + reject with icmpx type port-unreachable comment "!fw4: Reject any other traffic" + } + + chain input_wanA { + jump drop_from_wanA + } + + chain output_wanA { + jump drop_to_wanA + } + + chain forward_wanA { + jump drop_to_wanA + } + + chain accept_to_wanA { + oifname "eth0" counter accept comment "!fw4: accept wanA IPv4/IPv6 traffic" + } + + chain drop_from_wanA { + iifname "eth0" counter drop comment "!fw4: drop wanA IPv4/IPv6 traffic" + } + + chain drop_to_wanA { + oifname "eth0" counter drop comment "!fw4: drop wanA IPv4/IPv6 traffic" + } + + chain input_wanB { + jump drop_from_wanB + } + + chain output_wanB { + jump drop_to_wanB + } + + chain forward_wanB { + jump drop_to_wanB + } + + chain accept_to_wanB { + oifname "eth1" counter accept comment "!fw4: accept wanB IPv4/IPv6 traffic" + } + + chain drop_from_wanB { + iifname "eth1" counter drop comment "!fw4: drop wanB IPv4/IPv6 traffic" + } + + chain drop_to_wanB { + oifname "eth1" counter drop comment "!fw4: drop wanB IPv4/IPv6 traffic" + } + + chain input_lan { + jump drop_from_lan + } + + chain output_lan { + jump drop_to_lan + } + + chain forward_lan { + meta nfproto ipv6 jump accept_to_wanA comment "!fw4: Accept lan to wanA IPv6 forwarding" + meta nfproto ipv4 jump accept_to_wanB comment "!fw4: Accept lan to wanB IPv4 forwarding" + jump drop_to_lan + } + + chain drop_from_lan { + iifname "eth2" counter drop comment "!fw4: drop lan IPv4/IPv6 traffic" + } + + chain drop_to_lan { + oifname "eth2" counter drop comment "!fw4: drop lan IPv4/IPv6 traffic" + } + + + # + # NAT rules + # + + chain dstnat { + type nat hook prerouting priority dstnat; policy accept; + } + + chain srcnat { + type nat hook postrouting priority srcnat; policy accept; + } + + + # + # Raw rules (notrack & helper) + # + + chain raw_prerouting { + type filter hook prerouting priority raw; policy accept; + } + + chain raw_output { + type filter hook output priority raw; policy accept; + } + + + # + # Mangle rules + # + + chain mangle_prerouting { + type filter hook prerouting priority mangle; policy accept; + } + + chain mangle_postrouting { + type filter hook postrouting priority mangle; policy accept; + } + + chain mangle_input { + type filter hook input priority mangle; policy accept; + } + + chain mangle_output { + type filter hook output priority mangle; policy accept; + } + + chain mangle_forward { + type filter hook forward priority mangle; policy accept; + } +} +-- End -- -- 2.30.2