Difference between revisions of "Moving from ipset to nftables"

From nftables wiki
Jump to navigation Jump to search
(create page with basic content)
 
 
(7 intermediate revisions by 3 users not shown)
Line 1: Line 1:
If you are [[Moving from iptables to nftables | moving from iptables to nftables]] and you used [[ipset]], some considerations should be taken into account.
If you use [[ipset]] with iptables, you need to consider the following when [[Moving from iptables to nftables | moving to nftables]]:


* There are no translation/compat tools right now to help in the task. This may change in the future.
* Since ipset 7.12, there is the ''ipset-translate'' utility that automatically transform ipsets into nftables [[Sets|sets]]. This utility translates ipset set types into nftables set data types, which will often result in [[Concatenations | concatenated]] types. For example, an ipset of type ''hash:net,port,net'' becomes an nftables set of type ''ipv4_addr . inet_service . ipv4_addr''.
* ipset uses explicit set types, like '''hash:net,port,net''' which you need to translate to nftables native data types (like '''ipv4_addr . inet_service . ipv4_addr''')
* nftables support mappings and dictionaries, so you could take actions directly from matching elements in the set.


In most cases, direct equivalencies can be found of ipset features. In most cases, it worth evaluating nftables native features to benefit from them when migrating from ipset to nftables.
* nftables sets do not support negated elements, as with ipset ''nomatch''. To translate an ipset that has ''nomatch'' elements you can use a pair of nftables sets, one for the usual positive elements and one for negated elements, along with compound rule expressions like ''ip saddr @pos_set  ip saddr != @neg_set''.
 
* After the initial translation, it is recommended to have a look at nftables [[Maps|maps]] and [[Verdict_Maps_(vmaps)|verdict maps]] to make your ruleset more efficient.
 
The translation from ipset to nftables is straightforward with the ''ipset-translate'' utility:
 
<source lang="bash">
ipset-translate restore < sets.ipset
</source>
 
Following is an example of translating a basic iptables/ipset configuration into nftables.
 
Here is the iptables/ipset setup:
<source>
user@debian:~ $ sudo ipset save > sets.ipset
user@debian:~ $ sudo cat sets.ipset
create myset hash:ip,port,ip family inet hashsize 1024 maxelem 65536
add myset 172.16.0.1,tcp:80,10.0.0.1
 
user@debian:~ $ sudo ipset-translate restore < sets.ipset
add table inet global
add set inet global myset { type ipv4_addr . inet_proto . inet_service . ipv4_addr; size 65536; }
add element inet global myset { 172.16.0.1 . tcp . 80 . 10.0.0.1 }
</source>
 
The translation utility defines a dummy ''inet'' table whose name is ''global'', you can mangle this output to make it fit into your existing ruleset.
 
Now, you have to manually translate the rules that contain ''-m set'' in your ruleset:
 
<source lang="bash">
user@debian:~ $ sudo iptables-save
# Generated by iptables-save v1.8.3 on Wed Oct 30 11:26:41 2019
*filter
:INPUT ACCEPT [3:212]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [4:250]
-A INPUT -m set --match-set myset src,dst,dst -j ACCEPT
COMMIT
</source>
 
The above translates into nftables as:
 
<source>
user@debian:~ $ sudo nft list ruleset
table inet filter {
map myset {
type ipv4_addr . inet_service . ipv4_addr : verdict
elements = { 172.16.0.1 . 80 . 10.0.0.1 : accept }
}
 
chain input {
type filter hook input priority filter; policy accept;
meta nfproto ipv4 ip saddr . tcp dport . ip daddr vmap @myset
}
}
</source>
 
Note that we have used an nftables [[Verdict_Maps_(vmaps)|verdict&nbsp;map]], which takes action directly from each map element. Using such powerful new structures can greatly reduce the number of rules required by your filtering policy, compared with iptables/ipset.
 
We recommend reading about [[Concatenations | concatenations]].
 
Here are some additional examples of nftables equivalents for some ipset data types:
 
'''hash:net,net'''
 
<source lang="bash">
% nft add rule tablename chainname ip saddr . ip daddr vmap { 10.10.10.0/24 . 10.10.20.0/24 : accept }
</source>
 
'''hash:net,port,net'''
 
<source lang="bash">
% nft add rule tablename chainname ip saddr . tcp dport . ip daddr vmap { 10.10.10.0/24 . 80 . 10.10.20.0/24 : accept }
</source>
 
'''hash:net,iface'''
 
<source lang="bash">
% nft add rule tablename chainname ip saddr . iif vmap { 10.10.10.0/24 . eth0 : accept }
</source>
 
NOTE that before Linux kernel 5.6 and nftables 0.9.4 the CIDR notation used above was not yet available. If you are unable to upgrade, you can work around this limitation as noted in the [[Concatenations#Network_addresses|concatenation&nbsp;examples]].


== See also ==
== See also ==
Line 11: Line 90:
* [[Concatenations]]
* [[Concatenations]]
* [[Sets]]
* [[Sets]]
* [[Dictionaries]]
* [[Maps]]
* [[Maps]]
* [[Verdict_Maps_(vmaps) | Verdict maps]]
* [[Legacy xtables tools]]

Latest revision as of 12:01, 28 June 2021

If you use ipset with iptables, you need to consider the following when moving to nftables:

  • Since ipset 7.12, there is the ipset-translate utility that automatically transform ipsets into nftables sets. This utility translates ipset set types into nftables set data types, which will often result in concatenated types. For example, an ipset of type hash:net,port,net becomes an nftables set of type ipv4_addr . inet_service . ipv4_addr.
  • nftables sets do not support negated elements, as with ipset nomatch. To translate an ipset that has nomatch elements you can use a pair of nftables sets, one for the usual positive elements and one for negated elements, along with compound rule expressions like ip saddr @pos_set  ip saddr != @neg_set.
  • After the initial translation, it is recommended to have a look at nftables maps and verdict maps to make your ruleset more efficient.

The translation from ipset to nftables is straightforward with the ipset-translate utility:

ipset-translate restore < sets.ipset

Following is an example of translating a basic iptables/ipset configuration into nftables.

Here is the iptables/ipset setup:

user@debian:~ $ sudo ipset save > sets.ipset
user@debian:~ $ sudo cat sets.ipset
create myset hash:ip,port,ip family inet hashsize 1024 maxelem 65536
add myset 172.16.0.1,tcp:80,10.0.0.1

user@debian:~ $ sudo ipset-translate restore < sets.ipset
add table inet global
add set inet global myset { type ipv4_addr . inet_proto . inet_service . ipv4_addr; size 65536; }
add element inet global myset { 172.16.0.1 . tcp . 80 . 10.0.0.1 }

The translation utility defines a dummy inet table whose name is global, you can mangle this output to make it fit into your existing ruleset.

Now, you have to manually translate the rules that contain -m set in your ruleset:

user@debian:~ $ sudo iptables-save
# Generated by iptables-save v1.8.3 on Wed Oct 30 11:26:41 2019
*filter
:INPUT ACCEPT [3:212]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [4:250]
-A INPUT -m set --match-set myset src,dst,dst -j ACCEPT
COMMIT

The above translates into nftables as:

user@debian:~ $ sudo nft list ruleset
table inet filter {
	map myset {
		type ipv4_addr . inet_service . ipv4_addr : verdict
		elements = { 172.16.0.1 . 80 . 10.0.0.1 : accept }
	}

	chain input {
		type filter hook input priority filter; policy accept;
		meta nfproto ipv4 ip saddr . tcp dport . ip daddr vmap @myset
	}
}

Note that we have used an nftables verdict map, which takes action directly from each map element. Using such powerful new structures can greatly reduce the number of rules required by your filtering policy, compared with iptables/ipset.

We recommend reading about concatenations.

Here are some additional examples of nftables equivalents for some ipset data types:

hash:net,net

% nft add rule tablename chainname ip saddr . ip daddr vmap { 10.10.10.0/24 . 10.10.20.0/24 : accept }

hash:net,port,net

% nft add rule tablename chainname ip saddr . tcp dport . ip daddr vmap { 10.10.10.0/24 . 80 . 10.10.20.0/24 : accept }

hash:net,iface

% nft add rule tablename chainname ip saddr . iif vmap { 10.10.10.0/24 . eth0 : accept }

NOTE that before Linux kernel 5.6 and nftables 0.9.4 the CIDR notation used above was not yet available. If you are unable to upgrade, you can work around this limitation as noted in the concatenation examples.

See also