diff mbox series

[firewall4] ruleset: add missing pre_* chains

Message ID 20220518122619.159926-1-fe@dev.tdt.de
State Superseded
Headers show
Series [firewall4] ruleset: add missing pre_* chains | expand

Commit Message

Florian Eckert May 18, 2022, 12:26 p.m. UTC
There is the option to add a user change, but if the rule applies, the
fw4 rules are still processed. This is because these chains are
top-level chains that only have a different priority.

This priority indicates whether they are processed before or after the
fw4 chains.

So that rules can also be processed in the context of the fw4 and are
not passed on to the next toplevel chain in the event of an apply. The
rule must be processed in the context of the fw4 tables. This commit
adds a pre chain for input, output and forward.

Firewall rules, that are not handeled by the fw4  can then be hooked into
this, which are then processed in the context of the fw4 and are thus
allowed through by the fw4 in the event of an accept.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
(cherry picked from commit 596f9f7973560210a8ccf386d7017aaa07ea77d2)
---
 root/usr/share/firewall4/templates/ruleset.uc | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

Comments

Jo-Philipp Wich May 18, 2022, 1:38 p.m. UTC | #1
Hi,

can't you do the same by dropping a snippet into /etc/nftables.d/ which simply
registers chain with lower priority hooks? In fact there already is an example
[1].

So in order to achieve what you want, create an
`/etc/nftables.d/10-pre-chains.nft with the following contents:

-- 8< --
chain pre_input {
  type filter hook input priority -1; policy accept;
}

chain pre_forward {
  type filter hook forward priority -1; policy accept;
}

chain pre_output {
  type filter hook output priority -1; policy accept;
}
-- >8 --


Since nftables makes it easy to have many hooks, I doubt that such a generic,
mostly unused facility is needed at all. If your package/process/use case
requires staging custom rules before the default ones, drop a partial into
/etc/nftables.d/ which declares own chains with lower priority hooks along
with the rules you need.

~ Jo


1:
https://git.openwrt.org/?p=project/firewall4.git;a=blob;f=root/etc/nftables.d/10-custom-filter-chains.nft;h=4cb421308f2f8b084add77fc51f8430596d83abf;hb=b2682251a173103490a4a2556fb87e4df1d627b3#l8
Florian Eckert May 19, 2022, 1:22 p.m. UTC | #2
Hi,


> can't you do the same by dropping a snippet into /etc/nftables.d/ which 
> simply
> registers chain with lower priority hooks? In fact there already is an 
> example
> [1].

Specifically, it's about the firewall rules that the strongswan sets 
with the updown plugin on a connection SA up/down.
Currently, the iptables or ip6tables command is used on updown.
By using nft with fw4, iptables-nft or ip6tables-nft is now used 
trancperently used.
Currently strongswan updown is broken when using fw4 with 
iptables-nft/ip6tables-nft
So I rewrite the updown script to use native nft instead of 
iptables-nft/ip6tables-nft.


> So in order to achieve what you want, create an
> `/etc/nftables.d/10-pre-chains.nft with the following contents:
> 
> -- 8< --
> chain pre_input {
>   type filter hook input priority -1; policy accept;
> }
> 
> chain pre_forward {
>   type filter hook forward priority -1; policy accept;
> }
> 
> chain pre_output {
>   type filter hook output priority -1; policy accept;
> }
> -- >8 --

I have already seen that and I have also tried it and put my rules for 
my task in separate toplevel chains as you suggest.
But this does not work as expected. The packages are recognized by my 
new chain with a less priority.
However, they are then discarded by the next chain with a higher 
priority of fw4.

> Since nftables makes it easy to have many hooks, I doubt that such a 
> generic,
> mostly unused facility is needed at all. If your package/process/use 
> case
> requires staging custom rules before the default ones, drop a partial 
> into
> /etc/nftables.d/ which declares own chains with lower priority hooks 
> along
> with the rules you need.

Rules for strongswan in seperate chains with lower priority (not 
working):
         chain s_pre_input {
                 type filter hook input priority filter - 1; policy 
accept;
                 iifname "eth0" meta ipsec exists ipsec in reqid 1 ip 
saddr 192.168.17.0/24 ip daddr 192.168.99.0/24 accept comment 
"!strongswan: reqid in 1 input"
         }

         chain s_pre_forward {
                 type filter hook forward priority filter - 1; policy 
accept;
                 iifname "eth0" meta ipsec exists ipsec in reqid 1 ip 
saddr 192.168.17.0/24 ip daddr 192.168.99.0/24 accept comment 
"!strongswan: reqid in 1 forward"
                 oifname "eth0" meta ipsec exists ipsec out reqid 1 ip 
saddr 192.168.99.0/24 ip daddr 192.168.17.0/24 accept comment 
"!strongswan: reqid out 1 forward"
         }

         chain s_pre_output {
                 type filter hook output priority filter - 1; policy 
accept;
                 oifname "eth0" ipsec out reqid 1 ip saddr 
192.168.99.0/24 ip daddr 192.168.17.0/24 accept comment "!strongswan: 
reqid out 1 output"
         }

         chain s_pre_srcnat {
                 type nat hook postrouting priority srcnat - 1; policy 
accept;
                 ip saddr 192.168.99.0/24 ip daddr 192.168.17.0/24 accept 
comment "!strongswan: reqid none 1 srcnat"
         }

Rules for strongswan in a pre chain with a jump (working):

         chain pre_input {
                 iifname "eth0" meta ipsec exists ipsec in reqid 1 ip 
saddr 192.168.17.0/24 ip daddr 192.168.99.0/24 accept comment 
"!strongswan: reqid in 1 input"
         }

         chain input {
                 type filter hook input priority filter; policy drop;
                 iifname "lo" accept comment "!fw4: Accept traffic from 
loopback"
                 jump pre_input
                 ct state established,related accept comment "!fw4: Allow 
inbound established and related flows"
                 tcp flags syn / fin,syn,rst,ack jump syn_flood comment 
"!fw4: Rate limit TCP syn packets"
                 iifname "eth1" jump input_lan comment "!fw4: Handle lan 
IPv4/IPv6 input traffic"
                 iifname "eth0" jump input_wan comment "!fw4: Handle wan 
IPv4/IPv6 input traffic"
                 jump handle_reject
         }

         chain pre_forward {
                 iifname "eth0" meta ipsec exists ipsec in reqid 1 ip 
saddr 192.168.17.0/24 ip daddr 192.168.99.0/24 accept comment 
"!strongswan: reqid in 1 forward"
                 oifname "eth0" meta ipsec exists ipsec out reqid 1 ip 
saddr 192.168.99.0/24 ip daddr 192.168.17.0/24 accept comment 
"!strongswan: reqid out 1 forward"
         }

         chain forward {
                 type filter hook forward priority filter; policy drop;
                 jump pre_forward
                 ct state established,related accept comment "!fw4: Allow 
forwarded established and related flows"
                 iifname "eth1" jump forward_lan comment "!fw4: Handle 
lan IPv4/IPv6 forward traffic"
                 iifname "eth0" jump forward_wan comment "!fw4: Handle 
wan IPv4/IPv6 forward traffic"
                 jump handle_reject
         }

         chain pre_output {
                 oifname "eth0" ipsec out reqid 1 ip saddr 
192.168.99.0/24 ip daddr 192.168.17.0/24 accept comment "!strongswan: 
reqid out 1 output"
         }

         chain pre_srcnat {
                 ip saddr 192.168.99.0/24 ip daddr 192.168.17.0/24 accept 
comment "!strongswan: reqid none 1 srcnat"
         }

         chain srcnat {
                 type nat hook postrouting priority srcnat; policy 
accept;
                 jump pre_srcnat
                 oifname "eth0" jump srcnat_wan comment "!fw4: Handle wan 
IPv4/IPv6 srcnat traffic"
         }



I'm not sure yet. But I suspect that if a package in a chain with a 
lower priority is recognized as accepted,
it will simply be passed on to the next chain with a higher priority.
And this is then the filter chain fw4, where the package is dropped.
Because no rules matches.

I have not found anything in the documentation of nftables.
But if I put the rules in a pre_* chain with a jump then the strongswan 
works with nft and if I put the rules with a lower priority in a 
separate toplevel chain without a jump then it doesn't work.

In order for this to work with ipsec and nft, the kernel module 
kmod-nft-xfrm must be built [1].

Best regards

Florian

[1] https://github.com/openwrt/openwrt/pull/9909
Florian Eckert May 24, 2022, 2:28 p.m. UTC | #3
Hello Jo-Philipp

I found the following summary that describes my problem. See my link 
[1].
And why me need this pre_* hooks in fw4 as I suggested.

I have found the following description about priority and accept.
This is the paragraph:

Base chain priority:

Each nftables base chain is assigned a priority that defines its 
ordering among other base chains, flowtables, and Netfilter internal 
operations at the same hook. For example, a chain on the prerouting hook 
with priority -300 will be placed before connection tracking operations.

NOTE: If a packet is accepted and there is another chain, bearing the 
same hook type and with a later priority, then the packet will 
subsequently traverse this other chain. Hence, an accept verdict - be it 
by way of a rule or the default chain policy - isn't necessarily final. 
However, the same is not true of packets that are subjected to a drop 
verdict. Instead, drops take immediate effect, with no further rules or 
chains being evaluated.

 From my point of view it makes sense to add my changes in fw4, otherwise 
it won't work.
When I read it like this then your suggestion does not work?



Kind regards

Florian

[1] 
https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_types
diff mbox series

Patch

diff --git a/root/usr/share/firewall4/templates/ruleset.uc b/root/usr/share/firewall4/templates/ruleset.uc
index 0142d5a..79401d2 100644
--- a/root/usr/share/firewall4/templates/ruleset.uc
+++ b/root/usr/share/firewall4/templates/ruleset.uc
@@ -67,11 +67,16 @@  table inet fw4 {
 	# Filter rules
 	#
 
+	chain pre_input {
+
+	}
+
 	chain input {
 		type filter hook input priority filter; policy {{ fw4.input_policy(true) }};
 
 		iifname "lo" accept comment "!fw4: Accept traffic from loopback"
 
+		jump pre_input
 		ct state established,related accept comment "!fw4: Allow inbound established and related flows"
 {% if (fw4.default_option("drop_invalid")): %}
 		ct state invalid drop comment "!fw4: Drop flows with invalid conntrack state"
@@ -90,9 +95,14 @@  table inet fw4 {
 {% endif %}
 	}
 
+	chain pre_forward {
+
+	}
+
 	chain forward {
 		type filter hook forward priority filter; policy {{ fw4.forward_policy(true) }};
 
+		jump pre_forward
 {% if (length(flowtable_devices) > 0): %}
 		meta l4proto { tcp, udp } flow offload @ft;
 {% endif %}
@@ -111,11 +121,16 @@  table inet fw4 {
 {% endif %}
 	}
 
+	chain pre_output {
+
+	}
+
 	chain output {
 		type filter hook output priority filter; policy {{ fw4.output_policy(true) }};
 
 		oifname "lo" accept comment "!fw4: Accept traffic towards loopback"
 
+		jump pre_output
 		ct state established,related accept comment "!fw4: Allow outbound established and related flows"
 {% if (fw4.default_option("drop_invalid")): %}
 		ct state invalid drop comment "!fw4: Drop flows with invalid conntrack state"