From: Jo-Philipp Wich Date: Tue, 25 Oct 2022 19:03:00 +0000 (+0200) Subject: ruleset: drop ctstate invalid traffic for masq-enabled zones X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=119ee1a06d4a5e5fd01ec1a242d21d6f355d7ff6;p=project%2Ffirewall4.git ruleset: drop ctstate invalid traffic for masq-enabled zones For NAT enabled zones, stage rules to drop forwarded traffic with conntrack state "invalid" and honor `masq_allow_invalid` option to inhibit those rules. This ports the corresponding firewall3 logic to firewall4. Ref: https://forum.openwrt.org/t/x/140790 Signed-off-by: Jo-Philipp Wich --- diff --git a/root/usr/share/firewall4/templates/ruleset.uc b/root/usr/share/firewall4/templates/ruleset.uc index d6333f1..d6eedfd 100644 --- a/root/usr/share/firewall4/templates/ruleset.uc +++ b/root/usr/share/firewall4/templates/ruleset.uc @@ -265,6 +265,9 @@ table inet fw4 { {% if (zone.dflags[verdict]): %} chain {{ verdict }}_to_{{ zone.name }} { {% for (let rule in zone.match_rules): %} +{% if (verdict == "accept" && (zone.masq || zone.masq6) && !zone.masq_allow_invalid): %} + {%+ include("zone-drop-invalid.uc", { fw4, zone, rule }) %} +{% endif %} {%+ include("zone-verdict.uc", { fw4, zone, rule, egress: true, verdict }) %} {% endfor %} } diff --git a/root/usr/share/firewall4/templates/zone-drop-invalid.uc b/root/usr/share/firewall4/templates/zone-drop-invalid.uc new file mode 100644 index 0000000..d16bc0b --- /dev/null +++ b/root/usr/share/firewall4/templates/zone-drop-invalid.uc @@ -0,0 +1,8 @@ +{%+ if (zone.masq ^ zone.masq6): -%} + meta nfproto {{ fw4.nfproto(zone.masq ? 4 : 6) }} {%+ endif -%} +{%+ include("zone-match.uc", { egress: true, rule }) -%} +ct state invalid {%+ if (zone.counter): -%} + counter {%+ endif -%} +{%+ if (zone.log & 1): -%} + log prefix "drop {{ zone.name }} invalid ct state: " {%+ endif -%} +drop comment "!fw4: Prevent NAT leakage" diff --git a/tests/01_configuration/01_ruleset b/tests/01_configuration/01_ruleset index e30ca76..c4fd5b4 100644 --- a/tests/01_configuration/01_ruleset +++ b/tests/01_configuration/01_ruleset @@ -213,6 +213,7 @@ table inet fw4 { } chain accept_to_wan { + meta nfproto ipv4 oifname "pppoe-wan" ct state invalid counter drop comment "!fw4: Prevent NAT leakage" oifname "pppoe-wan" counter accept comment "!fw4: accept wan IPv4/IPv6 traffic" } diff --git a/tests/02_zones/02_masq b/tests/02_zones/02_masq index 369cdd6..1b1098f 100644 --- a/tests/02_zones/02_masq +++ b/tests/02_zones/02_masq @@ -151,6 +151,7 @@ table inet fw4 { } chain accept_to_test1 { + meta nfproto ipv4 oifname "zone1" ct state invalid counter drop comment "!fw4: Prevent NAT leakage" oifname "zone1" counter accept comment "!fw4: accept test1 IPv4/IPv6 traffic" } diff --git a/tests/02_zones/03_masq_src_dest_restrictions b/tests/02_zones/03_masq_src_dest_restrictions index 2cb0ce4..011ef89 100644 --- a/tests/02_zones/03_masq_src_dest_restrictions +++ b/tests/02_zones/03_masq_src_dest_restrictions @@ -171,6 +171,7 @@ table inet fw4 { } chain accept_to_test1 { + meta nfproto ipv4 oifname "zone1" ct state invalid counter drop comment "!fw4: Prevent NAT leakage" oifname "zone1" counter accept comment "!fw4: accept test1 IPv4/IPv6 traffic" } diff --git a/tests/02_zones/04_masq_allow_invalid b/tests/02_zones/04_masq_allow_invalid new file mode 100644 index 0000000..5a404b9 --- /dev/null +++ b/tests/02_zones/04_masq_allow_invalid @@ -0,0 +1,179 @@ +Testing that dropping of invalid conntrack state traffic can be inhibited. + +-- Testcase -- +{% + include("./root/usr/share/firewall4/main.uc", { + getenv: function(varname) { + switch (varname) { + case 'ACTION': + return 'print'; + } + } + }) +%} +-- End -- + +-- File uci/helpers.json -- +{} +-- End -- + +-- File fs/open~_sys_class_net_zone1_flags.txt -- +0x1103 +-- End -- + +-- File fs/open~_sys_class_net_zone2_flags.txt -- +0x1103 +-- End -- + +-- File uci/firewall.json -- +{ + "zone": [ + { + ".description": "No ct state invalid drop rule should be generated", + "name": "test1", + "input": "ACCEPT", + "output": "ACCEPT", + "forward": "ACCEPT", + "device": "zone1", + "masq": "1", + "masq_allow_invalid": 1 + } + ] +} +-- End -- + +-- Expect stdout -- +table inet fw4 +flush table inet fw4 + +table inet fw4 { + # + # Defines + # + + define test1_devices = { "zone1" } + define test1_subnets = { } + + + # + # 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 "zone1" jump input_test1 comment "!fw4: Handle test1 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 "zone1" jump forward_test1 comment "!fw4: Handle test1 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 "zone1" jump output_test1 comment "!fw4: Handle test1 IPv4/IPv6 output traffic" + } + + chain prerouting { + type filter hook prerouting priority filter; policy accept; + } + + 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_test1 { + jump accept_from_test1 + } + + chain output_test1 { + jump accept_to_test1 + } + + chain forward_test1 { + jump accept_to_test1 + } + + chain accept_from_test1 { + iifname "zone1" counter accept comment "!fw4: accept test1 IPv4/IPv6 traffic" + } + + chain accept_to_test1 { + oifname "zone1" counter accept comment "!fw4: accept test1 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; + oifname "zone1" jump srcnat_test1 comment "!fw4: Handle test1 IPv4/IPv6 srcnat traffic" + } + + chain srcnat_test1 { + meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 test1 traffic" + } + + + # + # Raw rules (notrack) + # + + 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 route hook output priority mangle; policy accept; + } + + chain mangle_forward { + type filter hook forward priority mangle; policy accept; + } +} +-- End --