Use multiple ipset in fw rule? are these rules valid?

in /etc/config/firewall I have the following [example] ipsets

config ipset
    option name 'MGMT_PORTS'
    option family 'ipv4'
    list match 'dest_port'
    list entry '22'
    list entry '80'
    list entry '443'
    list entry '8006'
config ipset
    option name 'MGMT_TARGETS'
    list match 'dest_ip'
    option family 'ipv4'
    list entry '10.10.20.1'
    list entry '10.10.30.2'
    list entry '10.10.40.3
config ipset
    option name 'TRUSTED_CLIENTS'
    list match 'src_ip'
    option family 'ipv4'
    list entry '10.10.10.10'
    list entry '10.10.50.11'

and also the following rules

config rule
option name 'MGMT-INPUT'
option src '*'
list proto 'tcp'
option ipset 'MGMT_PORTS'
option ipset 'MGMT_TARGETS'
option ipset 'TRUSTED_CLIENTS'
option target 'ACCEPT'

config rule
option name 'MGMT-FORWARD'
option src '*'
optiondest'*'
list proto 'tcp'
option ipset 'MGMT_PORTS'
option ipset 'MGMT_TARGETS'
option ipset 'TRUSTED_CLIENTS'
option target 'ACCEPT'

when I reload firewall I am not getting any explicit failures or warnings that these are invalid, but I am also not 100% sure they are completely valid or in play since the web GUI only permits using a single ipset and I haven’t been able to determine via other means

In other words, is this valid in Owrt 24.10.2 ?

What you have written is invalid to start. I think you mean to write

list ipset ‘ipset1’

list ipset ‘ipset2’

Otherwise you’re just setting the same option repeatedly and overwriting it.

Secondly, I don’t think it is supported.

1 Like

thanks for your input.

yes I just tried

list ipset ‘ipset1’
list ipset ‘ipset2’
etc

and those are definitely invalid.

I was also under the impression only one of the multiples listed was actually active… I am still trying to wrap my head around fw4 / nftables and how to make custom rules that the UCI syntax and/or the config files do not support directly.

You can define your ipsets using the uci syntax as you have already.

To create custom rules that are not supported by uci/fw4 you can create nft files and place them in appropriate files/folders to inject them into the firewall.

I think I may have just got it sorted…good enough at least.

In /etc/nftables.d/ I created a file mgmt.nft that contains:

# ------------------------
# INPUT chain rule
# ------------------------
chain allow_mgmt_input {
    type filter hook input priority 100; policy accept;

    ip saddr @TRUSTED_CLIENTS ip daddr @MGMT_TARGETS tcp dport @MGMT_PORTS accept
}

# ------------------------
# FORWARD chain rule
# ------------------------
chain allow_mgmt_forward {
    type filter hook forward priority 100; policy accept;

    ip saddr @TRUSTED_CLIENTS ip daddr @MGMT_TARGETS tcp dport @MGMT_PORTS accept
}

and upon reloading the firewall I can see:

not sure how right or wrong that is, but I was originally trying to contain those chains inside their own table but either my syntax was wrong or I was putting everything in the wrong place(s) because the firewall reload commands were throwing a bunch of errors about it until I dropped it down to just the chain rules only. I am still confused as to chains vs tables vs rules etc and all of the positions involved: pre, post, etc.

1 Like

Turns out I couldn’t get the rule above to work. I figure, likely because of incorrect priority / positioning in the chain(s).

I tried the same rule by creating a config section in the firewall config file per an example or two referenced in the docs and had luck getting those snippets to work. The snippets inserted at the front into the main “input” and “forward” chains themselves.

I would like to learn how to use nftables the other way I posted above in the long term, but my setup is working how I want it to for now.

Also, when adding the snippets via /etc/firewall/config, I am not sure if it is possible or how to add more than a single config-based rule or config line at a time in the referenced file(s)?

I know sets have more flexibility for dynamic updates, but have you tried the basic rules with adding the IPs and ports manually?

config rule
        option src '*'
        option dest '*'
        option name 'MGMT-FORWARD'
        list proto 'tcp'
        list src_ip '10.10.10.10'
        list src_ip '10.10.50.11'
        list dest_ip '10.10.20.1'
        list dest_ip '10.10.30.2'
        list dest_ip '10.10.40.3'
        option dest_port '22 80 443 8086'
        option target 'ACCEPT'

config rule
        option src '*'
        option name 'MGMT-INPUT'
        list proto 'tcp'
        list src_ip '10.10.10.10'
        list src_ip '10.10.50.11'
        list dest_ip '10.10.20.1'
        list dest_ip '10.10.30.2'
        list dest_ip '10.10.40.3'
        option dest_port '22 80 443 8086'
        option target 'ACCEPT'

How the uci rules get inserted into the base chains in the inet fw4 table:

chain input {
		type filter hook input priority filter; policy drop;

		iif "lo" accept comment "!fw4: Accept traffic from loopback"

		ct state vmap { established : accept, related : accept, invalid : drop } comment "!fw4: Handle inbound flows"
		tcp flags & (fin | syn | rst | ack) == syn jump syn_flood comment "!fw4: Rate limit TCP syn packets"
		ip saddr { 10.10.10.10, 10.10.50.11 } ip daddr { 10.10.20.1, 10.10.30.2, 10.10.40.3 } tcp dport { 22, 80, 443, 8086 } counter accept comment "!fw4: MGMT-INPUT"
		iifname "br-lan" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic"
		iifname "eth1" jump input_wan comment "!fw4: Handle wan IPv4/IPv6 input traffic"
		jump handle_reject
}

chain forward {
		type filter hook forward priority filter; policy drop;

		meta l4proto { tcp, udp } flow offload @ft;
		ct state vmap { established : accept, related : accept, invalid : drop } comment "!fw4: Handle forwarded flows"
		ip saddr { 10.10.10.10, 10.10.50.11 } ip daddr { 10.10.20.1, 10.10.30.2, 10.10.40.3 } tcp dport { 22, 80, 443, 8086 } counter accept comment "!fw4: MGMT-FORWARD"
		iifname "br-lan" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
		iifname "eth1" jump forward_wan comment "!fw4: Handle wan IPv4/IPv6 forward traffic"
}

Yeah, I understand I can do individual static / manually-defined rules (as I once had) but I am more interested in leveraging the power and utility of sets, tags, etc. and learning more of the finer details as I go.

Fair enough. The complexity using an alternative table and chain with its own hook and priority is that you need to think about the behavior of accept and drop rules across chains when both may have their own policy in addition to specific accept or drop rules.

accept Terminate ruleset evaluation and accept the packet. The packet can still be dropped later by another hook, for instance accept in the forward hook still allows one to drop the packet later in the postrouting hook, or another forward base chain that has a higher priority number and is evaluated afterwards in the processing pipeline.

drop Terminate ruleset evaluation and drop the packet. The drop occurs instantly, no further chains or hooks are evaluated. It is not possible to accept the packet in a later chain again, as those are not evaluated anymore for the packet.

See "Verdict Statements" in the man page:

Since the original input chain had a drop policy, your custom input chain may not see the packets anymore to test your custom rule.

I don't know that the expected behavior is well documented anywhere, but it can make your head hurt.

2 Likes