With the following setup:
#!/usr/sbin/nft -f
add table ip filter
add chain ip filter input { type filter hook input priority 0; }
add set ip filter nat-group-1 { type ipv4_addr; }
add set ip filter nat-group-2 { type ipv4_addr; }
add set ip filter nat-group-3 { type ipv4_addr; }
add set ip filter nat-group-4 { type ipv4_addr; }
add set ip filter nat-group-5 { type ipv4_addr; }
add rule ip filter input ip saddr @nat-group-1 tcp dport 22 drop
add table ip nat
add chain ip nat postrouting {type nat hook postrouting priority srcnat; policy accept; }
add rule ip nat postrouting ip saddr @nat-group-1 snat to 192.168.1.0/24 persistent
add rule ip nat postrouting ip saddr @nat-group-2 snat to 192.168.2.0/24 persistent
I get the error message
Error: No such file or directory; did you mean set ‘nat-group-1’ in table ip ‘filter’?
I do not know how to reference a set from another table. Is this possible? Suspect one can get around this issue by duplicating the set in the two tables, but the error message makes me hopeful that there is some syntax that I'm not aware of.
I will be referencing the set in both tables.
Problem
Contrary for example with iptables' companion ipset which lives outside of iptables and thus doesn't have any scope limit by the way both interact, the scope of an nftables set is limited to the table where it's defined.
It's simply not possible to reference an other table from a table, so all objects in an other table can't be referenced, including sets defined in an other table.
Solution
One should think differently when using nftables than from using iptables: tables roles are not fixed.
Whenever possible, the same table should be used from different hook types, if they are to work together.
For OP's case,
chain ip filter input
andchain ip nat postrouting
can just be put in the same table, because it's the same family (ip
). So just rewrite the ruleset slightly. For example let's call the common tablemultinat
and just rewrite mechanically (eg:sed 's/ip filter/ip multinat/g;s/ip nat/ip multinat/g'
. Adding again an existing table is not an error but just a no-op) everything into this table:Now the set in the table can be access from both chains, because they are all in the same table. Contrary to iptables, it doesn't matter that the chains in the table have a different hook types.
Other cases
Now the same change can't be applied between tables of different families (
netdev
,bridge
,arp
,ip
ip6
,inet
).Between
ip
,ip6
andinet
(which is the combination of IPv4 and IPv6) the solution is still simple: put everything into aninet
family table and adapt a few rules where one has to disambiguate betweenip
andip6
.For the other cases, one other method is to mark packets or flows in the first happening chain where it can make a decision so the later happening chain can retrieve the mark without having to check again.
If none of this can be done, then I see no other way than duplicate the sets in multiple tables.