<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://wiki.nftables.org/wiki-nftables/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Arturo</id>
	<title>nftables wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.nftables.org/wiki-nftables/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Arturo"/>
	<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php/Special:Contributions/Arturo"/>
	<updated>2026-05-15T08:55:16Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Ruleset_debug/tracing&amp;diff=1153</id>
		<title>Ruleset debug/tracing</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Ruleset_debug/tracing&amp;diff=1153"/>
		<updated>2024-10-16T13:13:50Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add see also section with external links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since nftables v0.6 and linux kernel 4.6, ruleset debug/tracing is supported.&lt;br /&gt;
&lt;br /&gt;
This is an equivalent of the old iptables method -J TRACE, but with some great improvements.&lt;br /&gt;
&lt;br /&gt;
The steps to enable debug/tracing is the following:&lt;br /&gt;
* give support in your ruleset for it (set nftrace in any of your rules)&lt;br /&gt;
* monitor the trace events from the nft tool&lt;br /&gt;
&lt;br /&gt;
= Enabling nftrace =&lt;br /&gt;
&lt;br /&gt;
To enable nftrace in a packet, use a rule with this statement:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta nftrace set 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After all, nftrace is part of the [[Setting packet metainformation|metainformation]] of a packet.&lt;br /&gt;
&lt;br /&gt;
Of course, you may only enable nftrace for a given matching packet.&lt;br /&gt;
In the example below, we only enable nftrace for tcp packets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip protocol tcp meta nftrace set 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adjusting nftrace to only your subset of desired packets is key to properly debug the ruleset, otherwise you may get a lot of debug/tracing information which may be overwhelming.&lt;br /&gt;
&lt;br /&gt;
= Use a chain to enable tracing =&lt;br /&gt;
&lt;br /&gt;
The recommended way to enable tracing is to add a chain for this purpose.&lt;br /&gt;
&lt;br /&gt;
Register a &#039;&#039;trace_chain&#039;&#039; to enable tracing. If you already have a prerouting chain, then make sure your &#039;&#039;trace_chain&#039;&#039; priority comes &#039;&#039;before&#039;&#039; your existing prerouting chain.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain filter trace_chain { type filter hook prerouting priority -301\; }&lt;br /&gt;
% nft add rule filter trace_chain meta nftrace set 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example assumes you have an existing raw prerouting chain (at priority -300), hence, this is registering a trace chain right before this chain (at priority -301).&lt;br /&gt;
&lt;br /&gt;
Once you are done with rule tracing, you can just delete this chain to disable it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain filter trace_chain&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= monitoring tracing events =&lt;br /&gt;
&lt;br /&gt;
In nftables, getting the debug/tracing events is a bit different from the iptables world.&lt;br /&gt;
Now, we have an event-based monitor for the kernel to notify the nft tool.&lt;br /&gt;
&lt;br /&gt;
The basic syntax is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft monitor trace&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each trace event is assigned an &#039;id&#039; for you to easily follow different packets in the same trace session.&lt;br /&gt;
&lt;br /&gt;
= Complete example =&lt;br /&gt;
&lt;br /&gt;
Here is complete example of this debug/tracing mechanism in work.&lt;br /&gt;
&lt;br /&gt;
Assuming you have this ruleset:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority filter; policy drop;&lt;br /&gt;
                ct state established,related counter packets 2 bytes 292 accept&lt;br /&gt;
                ct state new tcp dport 22 counter packets 0 bytes 0 accept&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Load this ruleset:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -f ruleset.nft&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add a chain that enables tracing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain ip filter trace_chain { type filter hook prerouting priority -1\; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This registers the &#039;&#039;trace_chain&#039;&#039; before the existing &#039;&#039;input&#039;&#039; chain.&lt;br /&gt;
&lt;br /&gt;
And the rule to enable the tracing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter trace_chain meta nftrace set 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Simple tracing test, by pinging one host:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% ping -c 1 8.8.8.8&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You run on a different terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft monitor trace&lt;br /&gt;
trace id a95ea7ef ip filter trace_chain packet: iif &amp;quot;enp0s25&amp;quot; ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640 &lt;br /&gt;
trace id a95ea7ef ip filter trace_chain rule meta nftrace set 1 (verdict continue)&lt;br /&gt;
trace id a95ea7ef ip filter trace_chain verdict continue &lt;br /&gt;
trace id a95ea7ef ip filter trace_chain policy accept &lt;br /&gt;
trace id a95ea7ef ip filter input packet: iif &amp;quot;enp0s25&amp;quot; ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640 &lt;br /&gt;
trace id a95ea7ef ip filter input rule ct state established,related counter packets 168 bytes 53513 accept (verdict accept)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The trace id uniquely identifies a packet. The trace describes the packet entering the chain initially.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
trace id a95ea7ef ip filter trace_chain packet: iif &amp;quot;enp0s25&amp;quot; ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the packet travel through the ruleset.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
Some external tools can automate all the steps described here, see:&lt;br /&gt;
* https://github.com/aborrero/nftables-tracer (python based)&lt;br /&gt;
* https://github.com/aojea/nftrace (golang based)&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=1097</id>
		<title>Sets</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=1097"/>
		<updated>2023-09-15T10:48:56Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Named sets specifications */ mention auto-merge&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;nftables&#039;&#039; comes with a built-in generic set infrastructure that allows you to use &#039;&#039;&#039;any&#039;&#039;&#039; supported selector to build sets. This infrastructure makes possible the representation of [[maps]] and [[Verdict_Maps_(vmaps) | verdict&amp;amp;nbsp;maps]].&lt;br /&gt;
&lt;br /&gt;
The set elements are internally represented using performance data structures such as hashtables and red-black trees.&lt;br /&gt;
&lt;br /&gt;
= Anonymous sets =&lt;br /&gt;
&lt;br /&gt;
Anonymous sets are those that are:&lt;br /&gt;
&lt;br /&gt;
* Bound to a rule, if the rule is removed, that set is released too.&lt;br /&gt;
* They have no specific name, the kernel internally allocates an identifier.&lt;br /&gt;
* They cannot be updated. So you cannot add and delete elements from it once it is bound to a rule.&lt;br /&gt;
&lt;br /&gt;
The following example shows how to create a simple set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter output tcp dport { 22, 23 } counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule above catches all traffic going to TCP ports 22 and 23, in case of matching the counters are updated.&lt;br /&gt;
&lt;br /&gt;
Eric Leblond in his [https://home.regit.org/2014/01/why-you-will-love-nftables/ Why you will love nftables] article shows a very simple example to compare iptables with nftables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -A INPUT -p tcp -m multiport --dports 23,80,443 -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which can be expressed in &#039;&#039;nftables&#039;&#039; with a couple of rules that provide a set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip6 filter input tcp dport {telnet, http, https} accept&lt;br /&gt;
% nft add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Named sets =&lt;br /&gt;
&lt;br /&gt;
You can use &#039;&#039;nft add set&#039;&#039; to create a named set. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter blackhole { type ipv4_addr\; comment \&amp;quot;drop all packets from these hosts\&amp;quot; \; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a set named &#039;&#039;blackhole&#039;&#039;. Set names must be 16 characters or less. The optional set &#039;&#039;comment&#039;&#039; attribute requires at least nftables 0.9.7 and kernel 5.10. The &#039;&#039;type&#039;&#039; keyword indicates the data type of elements to be stored in the set. In this case &#039;&#039;blackhole&#039;&#039; stores IPv4 addresses, which you can add using &#039;&#039;nft add element&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element ip filter blackhole { 192.168.3.4 }&lt;br /&gt;
% nft add element ip filter blackhole { 192.168.1.4, 192.168.1.5 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can use named sets from rules, as for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip saddr @blackhole drop&lt;br /&gt;
% nft add rule ip filter output ip daddr != @blackhole accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Named sets can be updated anytime.&lt;br /&gt;
&lt;br /&gt;
== nftables.conf syntax ==&lt;br /&gt;
&lt;br /&gt;
When working with nftables.conf, you can define sets in a number of ways. You can then reference those sets later on using &amp;lt;code&amp;gt;$VARIABLE_NAME&amp;lt;/code&amp;gt; notation.&lt;br /&gt;
&lt;br /&gt;
Here are some examples showing sets defined in one line, spanning multiple lines, and sets referencing other sets. The set is then used in a rule to allow incoming traffic from certain IP ranges.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define SIMPLE_SET = { 192.168.1.1, 192.168.1.2 }&lt;br /&gt;
&lt;br /&gt;
define CDN_EDGE = {&lt;br /&gt;
    192.168.1.1,&lt;br /&gt;
    192.168.1.2,&lt;br /&gt;
    192.168.1.3,&lt;br /&gt;
    10.0.0.0/8&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
define CDN_MONITORS = {&lt;br /&gt;
    192.168.1.10,&lt;br /&gt;
    192.168.1.20&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
define CDN = {&lt;br /&gt;
    $CDN_EDGE,&lt;br /&gt;
    $CDN_MONITORS&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Allow HTTP(S) from approved IP ranges only&lt;br /&gt;
tcp dport { http, https } ip saddr $CDN accept&lt;br /&gt;
udp dport { http, https } ip saddr $CDN accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Named sets specifications =&lt;br /&gt;
&lt;br /&gt;
Sets specifications are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;type&#039;&#039;&#039; or &#039;&#039;&#039;typeof&#039;&#039;&#039;, is obligatory and determines the data type of the set elements.&lt;br /&gt;
&lt;br /&gt;
Supported data types if using the &#039;&#039;&#039;type&#039;&#039;&#039; keyword are:&lt;br /&gt;
** &#039;&#039;ipv4_addr&#039;&#039;: IPv4 address&lt;br /&gt;
** &#039;&#039;ipv6_addr&#039;&#039;: IPv6 address.&lt;br /&gt;
** &#039;&#039;ether_addr&#039;&#039;: Ethernet address.&lt;br /&gt;
** &#039;&#039;inet_proto&#039;&#039;: Inet protocol type.&lt;br /&gt;
** &#039;&#039;inet_service&#039;&#039;: Internet service (read tcp port for example)&lt;br /&gt;
** &#039;&#039;mark&#039;&#039;: Mark type.&lt;br /&gt;
** &#039;&#039;ifname&#039;&#039;: Network interface name (eth0, eth1..)&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;typeof&#039;&#039;&#039; keyword is available since &#039;&#039;&#039;0.9.4&#039;&#039;&#039; and allows you to use a high level expression, then let nftables resolve the base type for you:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
	set s1 {&lt;br /&gt;
		typeof osf name&lt;br /&gt;
		elements = { &amp;quot;Linux&amp;quot; }&lt;br /&gt;
	}&lt;br /&gt;
	set s2 {&lt;br /&gt;
		typeof vlan id&lt;br /&gt;
		elements = { 2, 3, 103 }&lt;br /&gt;
	}&lt;br /&gt;
	set s3 {&lt;br /&gt;
		typeof ip daddr&lt;br /&gt;
		elements = { 1.1.1.1 }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;timeout&#039;&#039;&#039;, it determines how long an element stays in the set. The time string respects the format: &#039;&#039;&amp;quot;v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;dv&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;hv&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;mv&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;s&amp;quot;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft add set ip filter ports {type inet_service \; timeout 3h45s \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These commands create a table named &#039;&#039;filter&#039;&#039; and add a set named &#039;&#039;ports&#039;&#039; to it, where elements are deleted after 3 hours and 45 seconds of being added.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;flags&#039;&#039;&#039;, the available flags are:&lt;br /&gt;
** &#039;&#039;constant&#039;&#039; - set content may not change while bound&lt;br /&gt;
** &#039;&#039;interval&#039;&#039; - set contains intervals&lt;br /&gt;
** &#039;&#039;timeout&#039;&#039; - elements can be added with a timeout&lt;br /&gt;
&lt;br /&gt;
Multiple flags should be separated by comma:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter flags_set {type ipv4_addr\; flags constant, interval\;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;gc-interval&#039;&#039;&#039;, stands for garbage collection interval, can only be used if &#039;&#039;timeout&#039;&#039; or &#039;&#039;flags timeout&#039;&#039; are active. The interval follows the same format of &#039;&#039;timeouts&#039;&#039; time string &#039;&#039;&amp;quot;v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;dv&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;hv&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;mv&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;s&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;elements&#039;&#039;&#039;, initialize the set with some elements in it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter daddrs {type ipv4_addr \; flags timeout \; elements={192.168.1.1 timeout 10s, 192.168.1.2 timeout 30s} \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command creates a set name &#039;&#039;daddrs&#039;&#039; with elements &#039;&#039;192.168.1.1&#039;&#039;, which stays in it for 10s, and &#039;&#039;192.168.1.2&#039;&#039;, which stays for 30s.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;size&#039;&#039;&#039;, limits the maximum number of elements of the set. To create a set with maximum 2 elements type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter saddrs {type ipv4_addr \; size 2 \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;policy&#039;&#039;&#039;, determines set selection policy. Available values are:&lt;br /&gt;
** &#039;&#039;performance&#039;&#039; [default]&lt;br /&gt;
** &#039;&#039;memory&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;counter&#039;&#039;&#039;, (available since version &#039;&#039;&#039;0.9.5&#039;&#039;&#039;) which enables a counter per element:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
	set s {&lt;br /&gt;
		typeof ip saddr&lt;br /&gt;
		counter&lt;br /&gt;
		elements = { 1.1.1.1 counter packets 0 bytes 0, 1.1.1.2 counter packets 0 bytes 0,&lt;br /&gt;
			     1.1.1.3 counter packets 0 bytes 0, 1.1.1.4 counter packets 0 bytes 0 }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;auto-merge&#039;&#039;&#039;, to automatic merge adjacent/overlapping set elements. This is only valid for interval sets.&lt;br /&gt;
&lt;br /&gt;
For example, this origin set configuration will collapse the elements into the CIDR:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
	set myset {&lt;br /&gt;
		typeof ip saddr&lt;br /&gt;
        flags interval&lt;br /&gt;
        auto-merge&lt;br /&gt;
		elements = { 10.0.0.1,&lt;br /&gt;
                     10.0.0.2,&lt;br /&gt;
                     10.0.0.3,&lt;br /&gt;
			         10.0.0.0/8,&lt;br /&gt;
        }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Resulting in this when you list back the ruleset, because the CIDR already contains the individual elements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
	set myset {&lt;br /&gt;
		typeof ip saddr&lt;br /&gt;
        flags interval&lt;br /&gt;
        auto-merge&lt;br /&gt;
		elements = { 10.0.0.0/8,&lt;br /&gt;
        }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, note that not using &#039;&#039;&#039;auto-merge&#039;&#039;&#039; will make such ruleset fail to load with something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
/etc/nftables/ruleset.nft:38:21-29: Error: conflicting intervals specified&lt;br /&gt;
                    10.0.0.1 ,&lt;br /&gt;
             ~~~~~~~^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Listing named sets =&lt;br /&gt;
&lt;br /&gt;
You can list the content of a named set via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list set ip filter myset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Query for element membership in a set = &lt;br /&gt;
&lt;br /&gt;
You can also check if an element exists in the set from its key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft get element ip filter myset { 1.1.1.1 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example above checks if the IPv4 address 1.1.1.1 exists in the &#039;&#039;myset&#039;&#039; set.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=How_to_obtain_help/support&amp;diff=976</id>
		<title>How to obtain help/support</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=How_to_obtain_help/support&amp;diff=976"/>
		<updated>2021-05-27T09:58:52Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Community */ libera.chat&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are several ways of getting &#039;&#039;&#039;help and support&#039;&#039;&#039; for Netfilter products.&lt;br /&gt;
&lt;br /&gt;
= Community =&lt;br /&gt;
&lt;br /&gt;
Netfilter is a FLOSS community. Among other things this means that community support&lt;br /&gt;
is offered in a &#039;&#039;best effort&#039;&#039; approach.&lt;br /&gt;
&lt;br /&gt;
You may direct your help/support request to several support channels, which include:&lt;br /&gt;
&lt;br /&gt;
* The users mailing list: [mailto:netfilter@vger.kernel.org netfilter@vger.kernel.org], [https://marc.info/?l=netfilter archive]&lt;br /&gt;
* Our documentation (i.e., this wiki, manpages, [[Further_documentation |further documentation]], and other resources)&lt;br /&gt;
* IRC: #netfilter in [https://libera.chat libera.chat]&lt;br /&gt;
* External support tools and forums like stackoverflow, distribution specific channels, and so on&lt;br /&gt;
&lt;br /&gt;
Community support is usually not fully real-time, but the amount of knowledge that it contains is huge :-)&lt;br /&gt;
&lt;br /&gt;
= Enterprise =&lt;br /&gt;
&lt;br /&gt;
For some of our users it&#039;s important to have a professional paid support service associated with the software they are running.&lt;br /&gt;
There are &#039;&#039;&#039;a lot&#039;&#039;&#039; of enterprise businesses, vendors, and consulting firms who can provide support related to Netfilter software.&lt;br /&gt;
&lt;br /&gt;
The list below is not exhaustive, and contains no specific meaning, order or association with the Netfilter project, but are well-known in the community.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO: create the list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We usually love companies who contribute back to the community :-)&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=615</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=615"/>
		<updated>2021-02-04T10:55:49Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* NAT pooling */ typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform NAT. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
=== NAT pooling ===&lt;br /&gt;
&lt;br /&gt;
It is possible to specify source NAT pooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.2/31&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.4-10.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With transport protocol source port mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects outgoing 53/tcp traffic to a local proxy listening on port 10053/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat output tcp dport 853 redirect to 10053&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in prerouting and output chains of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking.&lt;br /&gt;
&lt;br /&gt;
This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot.&lt;br /&gt;
If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets.&lt;br /&gt;
&lt;br /&gt;
The example below sets IP/port for each packet (also valid in IPv6):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule ip raw prerouting ip protocol tcp ip daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
% nft add rule ip6 raw prerouting ip6 nexthdr tcp ip6 daddr set fe00::1 tcp dport set 10 notrack&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangle packet header fields | mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=614</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=614"/>
		<updated>2021-02-04T10:53:09Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Source NAT */ add example of SNAT pooling&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform NAT. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
=== NAT pooling ===&lt;br /&gt;
&lt;br /&gt;
It is possible to have specify source NAT pooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.2/31&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.4-10.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With transport protocol source port mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects outgoing 53/tcp traffic to a local proxy listening on port 10053/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat output tcp dport 853 redirect to 10053&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in prerouting and output chains of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking.&lt;br /&gt;
&lt;br /&gt;
This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot.&lt;br /&gt;
If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets.&lt;br /&gt;
&lt;br /&gt;
The example below sets IP/port for each packet (also valid in IPv6):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule ip raw prerouting ip protocol tcp ip daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
% nft add rule ip6 raw prerouting ip6 nexthdr tcp ip6 daddr set fe00::1 tcp dport set 10 notrack&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangle packet header fields | mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Using_configuration_management_systems&amp;diff=597</id>
		<title>Using configuration management systems</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Using_configuration_management_systems&amp;diff=597"/>
		<updated>2020-12-16T10:30:51Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* puppet */ add community module&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page shows a basic example on how to integrate nftables [[Scripting | scripting]] capabilities with configuration management systems (like puppet, ansible, chef, salt and others).&lt;br /&gt;
&lt;br /&gt;
The basic approach is to have a central point where we deploy nftables, with a ruleset layout that allows other files to be deployed and loaded atomically by nftables.&lt;br /&gt;
Other components (modules, or profiles, or whatever) then deploy specific rules or other configuration as required.&lt;br /&gt;
&lt;br /&gt;
= puppet =&lt;br /&gt;
&lt;br /&gt;
For the sake of the example this page uses puppet as reference, but the same concepts and mechanism could be applied to others.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; if you copy-paste this example make sure you adapt it to your environment. This code below is an example and hasn&#039;t been tested at all.&lt;br /&gt;
&lt;br /&gt;
== community module ==&lt;br /&gt;
&lt;br /&gt;
The community already developed deep integration between puppet and nftables and other related firewalling mechanisms (like firewalld).&lt;br /&gt;
&lt;br /&gt;
* https://forge.puppet.com/tags/nftables&lt;br /&gt;
* https://github.com/voxpupuli/puppet-nftables&lt;br /&gt;
&lt;br /&gt;
== raw example ==&lt;br /&gt;
&lt;br /&gt;
This a simplified raw example.&lt;br /&gt;
&lt;br /&gt;
=== a base puppet module ===&lt;br /&gt;
&lt;br /&gt;
A file like named this: &#039;&#039;&#039;modules/nftables/manifest/init.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
class nftables(&lt;br /&gt;
) {&lt;br /&gt;
    # install the package&lt;br /&gt;
    package { &#039;nftables&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;present&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # create a directory to hold the nftables config&lt;br /&gt;
    file { &#039;/etc/nftables/&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;directory&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # deploy the basic configuration file, i.e, the basic nftables ruleset skeleton&lt;br /&gt;
    file { &#039;/etc/nftables/ruleset.nft&#039;:&lt;br /&gt;
        ensure  =&amp;gt; &#039;present&#039;,&lt;br /&gt;
        source  =&amp;gt; &#039;puppet:///modules/nftables/nftables.nft&#039;,&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    # ensure nftables systemd service is running (at boot time, etc)&lt;br /&gt;
    service { &#039;nftables&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;running&#039;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We are installing this file (a file like: &#039;&#039;&#039;modules/nftables/files/nftables.nft&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
#!/usr/sbin/nft -f&lt;br /&gt;
&lt;br /&gt;
flush ruleset&lt;br /&gt;
&lt;br /&gt;
# create the basic ruleset skeleton&lt;br /&gt;
add table inet filter&lt;br /&gt;
add set inet filter allowed_ports { type inet_service ; }&lt;br /&gt;
add chain inet filter input { type filter hook input priority filter ; policy drop ; }&lt;br /&gt;
add rule inet filter input iif lo counter accept&lt;br /&gt;
add rule inet filter input ct state established,related counter accept&lt;br /&gt;
add rule inet filter input tcp dport @allowed_ports accept&lt;br /&gt;
add rule inet filter input counter&lt;br /&gt;
&lt;br /&gt;
# include all the other files that may be deployed by puppet&lt;br /&gt;
include &amp;quot;/etc/nftables/*puppet.nft&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== a module to introduce nftables config ===&lt;br /&gt;
&lt;br /&gt;
This module is responsible for injecting into the system the new nftables config.&lt;br /&gt;
A file named like : &#039;&#039;&#039;modules/nftables/manifest/rule.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
define nftables::rule(&lt;br /&gt;
    String $rule,&lt;br /&gt;
) {&lt;br /&gt;
   require ::nftables&lt;br /&gt;
&lt;br /&gt;
   file { &amp;quot;/etc/nftables/${name}_puppet.nft&amp;quot;:&lt;br /&gt;
       ensure  =&amp;gt; &#039;present&#039;,&lt;br /&gt;
       content =&amp;gt; $rule,&lt;br /&gt;
       notify  =&amp;gt; Service[&#039;nftables&#039;],&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== other modules adding nftables configuration ===&lt;br /&gt;
&lt;br /&gt;
In this example, we have an apache module that creates some additional rules and configuration for nftables.&lt;br /&gt;
&lt;br /&gt;
This is a file named like this: &#039;&#039;&#039;modules/apache/manifest/config.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
class ::apache::config(&lt;br /&gt;
) {&lt;br /&gt;
    package { &#039;apache&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;present&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    nftables::rule { &#039;apache_port_80&#039;:&lt;br /&gt;
        rule =&amp;gt; &#039;add element inet filter allowed_ports { 80 }&#039;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ansible =&lt;br /&gt;
&lt;br /&gt;
Check some examples on how people are using nftables with ansible:&lt;br /&gt;
&lt;br /&gt;
* https://github.com/ipr-cnrs/nftables&lt;br /&gt;
* https://github.com/Frzk/ansible-role-nftables&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Main_Page&amp;diff=578</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Main_Page&amp;diff=578"/>
		<updated>2020-11-23T11:08:28Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* External links */ add nftables &amp;amp; python external link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the &#039;&#039;nftables&#039;&#039; HOWTO documentation page. Here you will find documentation on how to build, install, configure and use nftables.&lt;br /&gt;
&lt;br /&gt;
If you have any suggestion to improve it, please send your comments to Netfilter users mailing list &amp;lt;netfilter@vger.kernel.org&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
&lt;br /&gt;
* [[What is nftables?]]&lt;br /&gt;
* [[Why nftables?]]&lt;br /&gt;
* [[Main differences with iptables]]&lt;br /&gt;
* [[Netfilter hooks]] and integration with existing Netfilter components.&lt;br /&gt;
* [[Adoption]]&lt;br /&gt;
* [[Legacy xtables tools]]&lt;br /&gt;
* [[How to obtain help/support]]&lt;br /&gt;
&lt;br /&gt;
= Getting started =&lt;br /&gt;
&lt;br /&gt;
* [[Building and installing nftables from sources]]&lt;br /&gt;
* Using [[nftables from distributions]]&lt;br /&gt;
* [[Troubleshooting|Troubleshooting and FAQ]]&lt;br /&gt;
* [[Quick reference-nftables in 10 minutes|Quick reference, nftables in 10 minutes]]&lt;br /&gt;
* [[nftables families|Understanding nftables families]]&lt;br /&gt;
&lt;br /&gt;
= Basic operation =&lt;br /&gt;
&lt;br /&gt;
* [[Configuring tables]]&lt;br /&gt;
* [[Configuring chains]]&lt;br /&gt;
* [[Simple rule management]]&lt;br /&gt;
* [[Atomic rule replacement]]&lt;br /&gt;
* [[Error reporting from the command line]]&lt;br /&gt;
* [[Building rules through expressions]]&lt;br /&gt;
* [[Operations at ruleset level]]&lt;br /&gt;
* [[Monitoring ruleset updates]]&lt;br /&gt;
* [[Scripting]]&lt;br /&gt;
* [[Ruleset debug/tracing]]&lt;br /&gt;
* [[Moving from iptables to nftables]]&lt;br /&gt;
* [[Moving from ipset to nftables]]&lt;br /&gt;
* [[Output text modifiers]]&lt;br /&gt;
&lt;br /&gt;
= Supported selectors for packet matching =&lt;br /&gt;
&lt;br /&gt;
* [[Matching packet header fields]]&lt;br /&gt;
* [[Matching packet metainformation]]&lt;br /&gt;
* [[Matching connection tracking stateful metainformation]]&lt;br /&gt;
* [[Rate limiting matchings]]&lt;br /&gt;
* [[Routing information]]&lt;br /&gt;
&lt;br /&gt;
= Possible actions on packets =&lt;br /&gt;
&lt;br /&gt;
* [[Accepting and dropping packets]]&lt;br /&gt;
* [[Jumping to chain]]&lt;br /&gt;
* [[Rejecting traffic]]&lt;br /&gt;
* [[Logging traffic]]&lt;br /&gt;
* [[Performing Network Address Translation (NAT)]]&lt;br /&gt;
* [[Setting packet metainformation]]&lt;br /&gt;
* [[Queueing to userspace]]&lt;br /&gt;
* [[Duplicating packets]]&lt;br /&gt;
* [[Mangle packet header fields]]&lt;br /&gt;
* [[Mangle TCP options]]&lt;br /&gt;
* [[Counters]]&lt;br /&gt;
* [[Load balancing]]&lt;br /&gt;
* [[Setting packet connection tracking metainformation]]&lt;br /&gt;
&lt;br /&gt;
Note that, unlike &#039;&#039;iptables&#039;&#039;, you can perform several actions in one single rule.&lt;br /&gt;
&lt;br /&gt;
= Advanced data structures for performance packet classification =&lt;br /&gt;
&lt;br /&gt;
You will have to redesign your rule-set to benefit from these new nice features:&lt;br /&gt;
&lt;br /&gt;
* [[Sets]]&lt;br /&gt;
* [[Dictionaries]]&lt;br /&gt;
* [[Intervals]]&lt;br /&gt;
* [[Maps]]&lt;br /&gt;
* [[Concatenations]]&lt;br /&gt;
* [[Meters|Metering]] (formerly known as flow tables before nftables 0.8.1 release)&lt;br /&gt;
* [[Updating sets from the packet path]]&lt;br /&gt;
* [[Element timeouts]]&lt;br /&gt;
* [[Math operations]]&lt;br /&gt;
* [[Stateful objects]]&lt;br /&gt;
* [[Flowtable]] (the fastpath network stack bypass)&lt;br /&gt;
&lt;br /&gt;
If you are already using [[ipset]] in your &#039;&#039;iptables&#039;&#039; rule-set, that transition may be a bit more simple to you.&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
&lt;br /&gt;
* [[Simple ruleset for a workstation]]&lt;br /&gt;
* [[Simple ruleset for a server]]&lt;br /&gt;
* [[Bridge filtering]]&lt;br /&gt;
* [[Multiple NATs using nftables maps]]&lt;br /&gt;
* [[Classic perimetral firewall example]]&lt;br /&gt;
* [[Port knocking example]]&lt;br /&gt;
* [[Classification to tc structure example]]&lt;br /&gt;
* [[Using configuration management systems]] (like puppet, ansible, etc)&lt;br /&gt;
* [[GeoIP matching]]&lt;br /&gt;
&lt;br /&gt;
= Development =&lt;br /&gt;
&lt;br /&gt;
Check [[Portal:DeveloperDocs|Portal:DeveloperDocs - documentation for netfilter developers]].&lt;br /&gt;
&lt;br /&gt;
Some hints on the general development progress:&lt;br /&gt;
&lt;br /&gt;
* [[List of updates since Linux kernel 3.13]]&lt;br /&gt;
* [[List of updates in the nft command line tool]]&lt;br /&gt;
* [[Supported features compared to xtables|Supported features compared to {ip,ip6,eb,arp}tables]]&lt;br /&gt;
* [[List of available translations via iptables-translate tool]]&lt;br /&gt;
&lt;br /&gt;
= External links =&lt;br /&gt;
&lt;br /&gt;
Watch some videos:&lt;br /&gt;
&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=FXTRRwXi3b4 Getting a grasp of nftables], thanks to [https://www.nluug.nl/index-en.html NLUUG association] for recording this.&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=CaYp0d2wiuU#t=1m47s The ultimate packet classifier for GNU/Linux], thanks to the FSFE for paying my trip to Barcelona and for recommending me as speaker to the KDE Spanish branch.&lt;br /&gt;
* [https://www.youtube.com/watch?v=Sy0JDX451ns Florian Westphal - Why nftables?]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=0wQfSfDVN94 NLUUG - Goodbye iptables, Hello nftables]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=Uf5ULkEWPL0 LCA2018 - nftables from a user perspective]&lt;br /&gt;
&lt;br /&gt;
Watch videos to track updates:&lt;br /&gt;
&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=qXVOA2MKA1s Netdev 2.1 - Netfilter mini-workshop (2017)]&lt;br /&gt;
* Watch [https://youtu.be/iCj10vEKPrw Netdev 2.2 - Netf‌ilter mini-workshop (2018)]&lt;br /&gt;
* Watch [https://youtu.be/0hqfzp6tpZo Netdev 0x12 - Netf‌ilter mini-workshop (2019)]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=GqGGo4svj7s&amp;amp;feature=youtu.be Netdev 0x14 - Netfilter mini-Workshop (2020)] &lt;br /&gt;
&lt;br /&gt;
Additional documentations and articles:&lt;br /&gt;
&lt;br /&gt;
* Tutorial [https://zasdfgbnm.github.io/2017/09/07/Extending-nftables/ Extending nftables by Xiang Gao]&lt;br /&gt;
* Article [http://ral-arturo.org/2017/05/05/debian-stretch-stable-nftables.html New in Debian stable Stretch: nftables]&lt;br /&gt;
* Article [https://ral-arturo.org/2020/11/22/python-nftables-tutorial.html How to use nftables from python] and git repository [https://github.com/aborrero/python-nftables-tutorial python-nftables-tutorial.git]&lt;br /&gt;
&lt;br /&gt;
= Thanks =&lt;br /&gt;
&lt;br /&gt;
To the NLnet foundation for initial sponsorship of this HOWTO:&lt;br /&gt;
&lt;br /&gt;
[https://nlnet.nl https://nlnet.nl/image/logo.gif]&lt;br /&gt;
&lt;br /&gt;
To Eric Leblond, for boostrapping the [https://home.regit.org/netfilter-en/nftables-quick-howto/ Nftables quick howto] in 2013.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Concatenations&amp;diff=542</id>
		<title>Concatenations</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Concatenations&amp;diff=542"/>
		<updated>2020-09-07T11:08:33Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Dictionary declarations */ mention some set options&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Linux kernel 4.1, nftables supports concatenations.&lt;br /&gt;
&lt;br /&gt;
This new feature allows you to put two or more selectors together to perform very fast lookups by combining them with [[sets]], [[dictionaries]], [[maps]] and [[meters]].&lt;br /&gt;
&lt;br /&gt;
= Literal sets =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip saddr . ip daddr . ip protocol { 1.1.1.1 . 2.2.2.2 . tcp, 1.1.1.1 . 3.3.3.3 . udp} counter accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So if the packet&#039;s source IP address AND destination IP address AND level 4 protocol match:&lt;br /&gt;
&lt;br /&gt;
* 1.1.1.1 and 2.2.2.2 and TCP.&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
* 1.1.1.1 and 3.3.3.3 and UDP.&lt;br /&gt;
&lt;br /&gt;
nftables updates the counter for this rule and then accepts the packet.&lt;br /&gt;
&lt;br /&gt;
= Dictionary declarations =&lt;br /&gt;
&lt;br /&gt;
The following example creates the &#039;&#039;whitelist&#039;&#039; dictionary using a concatenation of two selectors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter whitelist { type ipv4_addr . inet_service : verdict \; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you create the dictionary, you can use it from a rule that creates the following concatenation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input ip saddr . tcp dport vmap @whitelist&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Thus, the rule above looks up for a verdict based on the source IP address AND the TCP destination port.&lt;br /&gt;
&lt;br /&gt;
Since the dictionary is initially empty, you can dynamically populate this dictionary with elements through:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element filter whitelist { 1.2.3.4 . 22 : accept}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When declaring concatenations, you can use [[Sets | generic sets options]], such as the &#039;&#039;&#039;typeof&#039;&#039;&#039; keyword and the &#039;&#039;&#039;counter&#039;&#039;&#039; feature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet fmytable {&lt;br /&gt;
	set myset {&lt;br /&gt;
		typeof ip daddr . tcp dport&lt;br /&gt;
		counter&lt;br /&gt;
		elements = { 1.1.1.4 . 22 counter packets 0 bytes 0,&lt;br /&gt;
			     1.1.1.5 . 23 counter packets 0 bytes 0,&lt;br /&gt;
			     1.1.1.6 . 24 counter packets 0 bytes 0 }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Literal maps =&lt;br /&gt;
&lt;br /&gt;
The rule below determines the destination IP address that is used to perform DNAT to the packet based on:&lt;br /&gt;
&lt;br /&gt;
* the source IP address&lt;br /&gt;
&lt;br /&gt;
AND&lt;br /&gt;
&lt;br /&gt;
* the destination TCP port&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip nat prerouting dnat ip saddr . tcp dport map { 1.1.1.1 . 80 : 192.168.1.100, 2.2.2.2 . 8888 : 192.168.1.101 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
&lt;br /&gt;
Some concrete example concatenations so you get an idea on how powerful this new feature is.&lt;br /&gt;
&lt;br /&gt;
== Network addresses ==&lt;br /&gt;
&lt;br /&gt;
The example below implements a dictionary using network masks in each element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
    set myset {&lt;br /&gt;
        type ipv4_addr . ipv4_addr&lt;br /&gt;
        flags interval&lt;br /&gt;
        elements = { 192.168.0.0/16 . 172.16.0.0/25,&lt;br /&gt;
                     10.0.0.0/30 . 192.168.1.0/24,&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    chain mychain {&lt;br /&gt;
        ip saddr . ip daddr @myset counter accept&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: before kinux kernel 5.6 and nftables 0.9.4 the CIDR notation wasn&#039;t available, you would need to use a workaround:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . ip daddr and 255.255.255.0 vmap { 10.10.10.0 . 10.10.20.0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this is not an interval, this is masking the ip saddr and ip daddr, then concate both results. This concatenation is used to lookup for a matching of this the result in the map. This syntax may be compacted in future releases to support CIDR notation.&lt;br /&gt;
&lt;br /&gt;
This could be easily implemented using a named map as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map tablename myMap { type ipv4_addr . ipv4_addr : verdict \; }&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . ip saddr and 255.255.255.0 vmap @myMap&lt;br /&gt;
% nft add element tablename myMap { 10.10.10.0 . 10.10.20.0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interfaces ==&lt;br /&gt;
&lt;br /&gt;
The example below checks both input and output interfaces of a forwarded packet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname iif . oif vmap { eth0 . eth1 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note that using strings (for example iifname and oifname) and other variable sized data types is not supported yet.&lt;br /&gt;
&lt;br /&gt;
== Some ipset types ==&lt;br /&gt;
&lt;br /&gt;
These ipset types can be implemented in nftables using concatenations. Probably more equivalences exists, it just a matter of combining data types.&lt;br /&gt;
Of course, you could implement these as named maps/sets as well.&lt;br /&gt;
&lt;br /&gt;
See examples in the [[Moving_from_ipset_to_nftables | moving from ipset to nftables]] page.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Maps&amp;diff=541</id>
		<title>Maps</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Maps&amp;diff=541"/>
		<updated>2020-09-07T11:02:20Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add link to sets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Maps are yet another interesting feature that has been in &#039;&#039;nftables&#039;&#039; since the very beginning. You can use a map to look up for data based on some specific key that is used as input. Maps internally use the [[Sets | generic set infrastructure]] and therefore share some of their options and semantics.&lt;br /&gt;
&lt;br /&gt;
= Literal maps =&lt;br /&gt;
&lt;br /&gt;
The following example shows how the destination TCP port selects the destination IP address to DNAT the packet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip nat prerouting dnat tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is how you can express a classical port redirection when the real server are actually located behind the firewall. This can be read as it follows:&lt;br /&gt;
&lt;br /&gt;
* If the TCP destination port is 80, then the packet is DNAT&#039;ed to 192.168.1.100.&lt;br /&gt;
* If the TCP destination port is 8888, then the packet is DNAT&#039;ed to 192.168.1.101.&lt;br /&gt;
&lt;br /&gt;
= Map declarations =&lt;br /&gt;
&lt;br /&gt;
You can also declare maps that you can populate in a dynamic fashion, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map nat porttoip  { type inet_service: ipv4_addr\; }&lt;br /&gt;
% nft add element nat porttoip { 80 : 192.168.1.100, 8888 : 192.168.1.101 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example above shows that the &#039;&#039;porttoip&#039;&#039; map maintains the corresponde between Internet services (which is the datatype of a TCP destination port) and IP addresses.&lt;br /&gt;
&lt;br /&gt;
Then, you can use it from a rule like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip nat postrouting snat tcp dport map @porttoip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rules tells that the source IP address that is used for SNAT depends on TCP destination port. The content of the map can be dynamically updated by adding new elements.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Verdict_Maps_(vmaps)&amp;diff=540</id>
		<title>Verdict Maps (vmaps)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Verdict_Maps_(vmaps)&amp;diff=540"/>
		<updated>2020-09-07T11:01:37Z</updated>

		<summary type="html">&lt;p&gt;Arturo: link to sets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;dictionaries&#039;&#039;, also known as &#039;&#039;verdict maps&#039;&#039;, are one of the most interesting features available in &#039;&#039;nftables&#039;&#039;. Basically, they allow you to attach an action to an element. Dictionaries internally use the [[Sets | generic set infrastructure]] and therefore share some semantics and options.&lt;br /&gt;
&lt;br /&gt;
= Literal dictionaries =&lt;br /&gt;
&lt;br /&gt;
The following example shows how to create a tree of chains that whose traversal depends on the layer 4 protocol type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip protocol vmap { tcp : jump tcp-chain, udp : jump udp-chain , icmp : jump icmp-chain }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example above assumes that you&#039;ve already created the &#039;&#039;tcp-chain&#039;&#039;, &#039;&#039;udp-chain&#039;&#039; and &#039;&#039;icmp-chain&#039;&#039; [[Configuring chains|custom chains]]. Then, by attaching simple rules to account the traffic, ie.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter icmp-chain counter&lt;br /&gt;
% nft add rule filter tcp-chain counter&lt;br /&gt;
% nft add rule filter udp-chain counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can check that the classification is already happening:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
                 ip protocol vmap { udp : jump udp-chain, tcp : jump tcp-chain, icmp : jump icmp-chain}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain tcp-chain {&lt;br /&gt;
                 counter packets 4 bytes 520&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain udp-chain {&lt;br /&gt;
                 counter packets 4 bytes 678&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain icmp-chain {&lt;br /&gt;
                 counter packets 4 bytes 336&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you probably already noticed, one of the the good things of nftables is that you can use &#039;&#039;dictionaries&#039;&#039; to construct performance rule-sets. This rule-set arrangement allows you to reduce the amount of linear list inspections to classify your packets.&lt;br /&gt;
&lt;br /&gt;
= Dictionary declarations =&lt;br /&gt;
&lt;br /&gt;
You can also declarate dictionaries and populate its content dynamically, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter mydict { type ipv4_addr : verdict\; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add elements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element filter mydict { 192.168.0.10 : drop, 192.168.0.11 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can bind this set to a rule using the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input ip saddr vmap @mydict&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case you want to build your own dictionary, but you don&#039;t know what is the datatype name. Remember that you can inquire &#039;&#039;nft&#039;&#039; to know the datatype name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft describe tcp dport&lt;br /&gt;
payload expression, datatype inet_service (internet network service) (basetype integer), 16 bits&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the &#039;&#039;inet_service&#039;&#039; string after datatype.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=539</id>
		<title>Sets</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=539"/>
		<updated>2020-09-07T11:00:19Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Named sets specifications */ add info on counters&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;nftables&#039;&#039; comes with a built-in generic set infrastructure that allows you to use &#039;&#039;&#039;any&#039;&#039;&#039; supported selector to build sets. This infrastructure makes possible the representation of [[dictionaries]] and [[maps]].&lt;br /&gt;
&lt;br /&gt;
The set elements are internally represented using performance data structures such as hashtables and red-black trees.&lt;br /&gt;
&lt;br /&gt;
= Anonymous sets =&lt;br /&gt;
&lt;br /&gt;
Anonymous sets are those that are:&lt;br /&gt;
&lt;br /&gt;
* Bound to a rule, if the rule is removed, that set is released too.&lt;br /&gt;
* They have no specific name, the kernel internally allocates an identifier.&lt;br /&gt;
* They cannot be updated. So you cannot add and delete elements from it once it is bound to a rule.&lt;br /&gt;
&lt;br /&gt;
The following example shows how to create a simple set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter output tcp dport { 22, 23 } counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule above catches all traffic going to TCP ports 22 and 23, in case of matching the counters are updated.&lt;br /&gt;
&lt;br /&gt;
Eric Leblond in his [https://home.regit.org/2014/01/why-you-will-love-nftables/ Why you will love nftables] article shows a very simple example to compare iptables with nftables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -A INPUT -p tcp -m multiport --dports 23,80,443 -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which can be expressed in &#039;&#039;nftables&#039;&#039; with a couple of rules that provide a set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip6 filter input tcp dport {telnet, http, https} accept&lt;br /&gt;
% nft add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Named sets =&lt;br /&gt;
&lt;br /&gt;
You can create the named sets with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter blackhole { type ipv4_addr\;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;blackhole&#039;&#039; is the name of the set in this case. The &#039;&#039;type&#039;&#039; option indicates the data type that this set stores, which is an IPv4 address in this case. Current maximum name length is 16 characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element ip filter blackhole { 192.168.3.4 }&lt;br /&gt;
% nft add element ip filter blackhole { 192.168.1.4, 192.168.1.5 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can use it from the rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip saddr @blackhole drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Named sets can be updated anytime, so you can add and delete element from them.&lt;br /&gt;
&lt;br /&gt;
== nftables.conf syntax ==&lt;br /&gt;
&lt;br /&gt;
When working with nftables.conf, you can define sets in a number of ways. You can then reference those sets later on using &amp;lt;code&amp;gt;$VARIABLE_NAME&amp;lt;/code&amp;gt; notation.&lt;br /&gt;
&lt;br /&gt;
Here are some examples showing sets defined in one line, spanning multiple lines, and sets referencing other sets. The set is then used in a rule to allow incoming traffic from certain IP ranges.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define SIMPLE_SET = { 192.168.1.1, 192.168.1.2 }&lt;br /&gt;
&lt;br /&gt;
define CDN_EDGE = {&lt;br /&gt;
    192.168.1.1,&lt;br /&gt;
    192.168.1.2,&lt;br /&gt;
    192.168.1.3,&lt;br /&gt;
    10.0.0.0/8&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
define CDN_MONITORS = {&lt;br /&gt;
    192.168.1.10,&lt;br /&gt;
    192.168.1.20&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
define CDN = {&lt;br /&gt;
    $CDN_EDGE,&lt;br /&gt;
    $CDN_MONITORS&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Allow HTTP(S) from approved IP ranges only&lt;br /&gt;
tcp dport { http, https } ip saddr $CDN accept&lt;br /&gt;
udp dport { http, https } ip saddr $CDN accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Named sets specifications =&lt;br /&gt;
&lt;br /&gt;
Sets specifications are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;type&#039;&#039;&#039; or &#039;&#039;&#039;typeof&#039;&#039;&#039;, is obligatory and determines the data type of the set elements.&lt;br /&gt;
&lt;br /&gt;
Supported data types if using the &#039;&#039;&#039;type&#039;&#039;&#039; keyword are:&lt;br /&gt;
** &#039;&#039;ipv4_addr&#039;&#039;: IPv4 address&lt;br /&gt;
** &#039;&#039;ipv6_addr&#039;&#039;: IPv6 address.&lt;br /&gt;
** &#039;&#039;ether_addr&#039;&#039;: Ethernet address.&lt;br /&gt;
** &#039;&#039;inet_proto&#039;&#039;: Inet protocol type.&lt;br /&gt;
** &#039;&#039;inet_service&#039;&#039;: Internet service (read tcp port for example)&lt;br /&gt;
** &#039;&#039;mark&#039;&#039;: Mark type.&lt;br /&gt;
** &#039;&#039;ifname&#039;&#039;: Network interface name (eth0, eth1..)&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;typeof&#039;&#039;&#039; keyword is available since &#039;&#039;&#039;0.9.4&#039;&#039;&#039; and allows you to use a high level expression, then let nftables resolve the base type for you:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
	set s1 {&lt;br /&gt;
		typeof osf name&lt;br /&gt;
		elements = { &amp;quot;Linux&amp;quot; }&lt;br /&gt;
	}&lt;br /&gt;
	set s2 {&lt;br /&gt;
		typeof vlan id&lt;br /&gt;
		elements = { 2, 3, 103 }&lt;br /&gt;
	}&lt;br /&gt;
	set s3 {&lt;br /&gt;
		typeof ip daddr&lt;br /&gt;
		elements = { 1.1.1.1 }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;timeout&#039;&#039;&#039;, it determines how long an element stays in the set. The time string respects the format: &#039;&#039;&amp;quot;v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;dv&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;hv&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;mv&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;s&amp;quot;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft add set ip filter ports {type inet_service \; timeout 3h45s \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These commands create a table named &#039;&#039;filter&#039;&#039; and add a set named &#039;&#039;ports&#039;&#039; to it, where elements are deleted after 3 hours and 45 seconds of being added.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;flags&#039;&#039;&#039;, the available flags are:&lt;br /&gt;
** &#039;&#039;constant&#039;&#039; - set content may not change while bound&lt;br /&gt;
** &#039;&#039;interval&#039;&#039; - set contains intervals&lt;br /&gt;
** &#039;&#039;timeout&#039;&#039; - elements can be added with a timeout&lt;br /&gt;
&lt;br /&gt;
Multiple flags should be separated by comma:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter flags_set {type ipv4_addr\; flags constant, interval\;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;gc-interval&#039;&#039;&#039;, stands for garbage collection interval, can only be used if &#039;&#039;timeout&#039;&#039; or &#039;&#039;flags timeout&#039;&#039; are active. The interval follows the same format of &#039;&#039;timeouts&#039;&#039; time string &#039;&#039;&amp;quot;v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;dv&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;hv&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;mv&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;s&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;elements&#039;&#039;&#039;, initialize the set with some elements in it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter daddrs {type ipv4_addr \; flags timeout \; elements={192.168.1.1 timeout 10s, 192.168.1.2 timeout 30s} \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command creates a set name &#039;&#039;daddrs&#039;&#039; with elements &#039;&#039;192.168.1.1&#039;&#039;, which stays in it for 10s, and &#039;&#039;192.168.1.2&#039;&#039;, which stays for 30s.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;size&#039;&#039;&#039;, limits the maximum number of elements of the set. To create a set with maximum 2 elements type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter saddrs {type ipv4_addr \; size 2 \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;policy&#039;&#039;&#039;, determines set selection policy. Available values are:&lt;br /&gt;
** &#039;&#039;performance&#039;&#039; [default]&lt;br /&gt;
** &#039;&#039;memory&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;counter&#039;&#039;&#039;, (available since version &#039;&#039;&#039;0.9.5&#039;&#039;&#039;) which enables a counter per element:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
	set s {&lt;br /&gt;
		typeof ip saddr&lt;br /&gt;
		counter&lt;br /&gt;
		elements = { 1.1.1.1 counter packets 0 bytes 0, 1.1.1.2 counter packets 0 bytes 0,&lt;br /&gt;
			     1.1.1.3 counter packets 0 bytes 0, 1.1.1.4 counter packets 0 bytes 0 }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Listing named sets =&lt;br /&gt;
&lt;br /&gt;
You can list the content of a named set via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list set ip filter myset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=538</id>
		<title>Sets</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=538"/>
		<updated>2020-09-07T10:56:33Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Named sets specifications */ mention typeof&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;nftables&#039;&#039; comes with a built-in generic set infrastructure that allows you to use &#039;&#039;&#039;any&#039;&#039;&#039; supported selector to build sets. This infrastructure makes possible the representation of [[dictionaries]] and [[maps]].&lt;br /&gt;
&lt;br /&gt;
The set elements are internally represented using performance data structures such as hashtables and red-black trees.&lt;br /&gt;
&lt;br /&gt;
= Anonymous sets =&lt;br /&gt;
&lt;br /&gt;
Anonymous sets are those that are:&lt;br /&gt;
&lt;br /&gt;
* Bound to a rule, if the rule is removed, that set is released too.&lt;br /&gt;
* They have no specific name, the kernel internally allocates an identifier.&lt;br /&gt;
* They cannot be updated. So you cannot add and delete elements from it once it is bound to a rule.&lt;br /&gt;
&lt;br /&gt;
The following example shows how to create a simple set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter output tcp dport { 22, 23 } counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule above catches all traffic going to TCP ports 22 and 23, in case of matching the counters are updated.&lt;br /&gt;
&lt;br /&gt;
Eric Leblond in his [https://home.regit.org/2014/01/why-you-will-love-nftables/ Why you will love nftables] article shows a very simple example to compare iptables with nftables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -A INPUT -p tcp -m multiport --dports 23,80,443 -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which can be expressed in &#039;&#039;nftables&#039;&#039; with a couple of rules that provide a set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip6 filter input tcp dport {telnet, http, https} accept&lt;br /&gt;
% nft add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Named sets =&lt;br /&gt;
&lt;br /&gt;
You can create the named sets with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter blackhole { type ipv4_addr\;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;blackhole&#039;&#039; is the name of the set in this case. The &#039;&#039;type&#039;&#039; option indicates the data type that this set stores, which is an IPv4 address in this case. Current maximum name length is 16 characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element ip filter blackhole { 192.168.3.4 }&lt;br /&gt;
% nft add element ip filter blackhole { 192.168.1.4, 192.168.1.5 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can use it from the rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip saddr @blackhole drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Named sets can be updated anytime, so you can add and delete element from them.&lt;br /&gt;
&lt;br /&gt;
== nftables.conf syntax ==&lt;br /&gt;
&lt;br /&gt;
When working with nftables.conf, you can define sets in a number of ways. You can then reference those sets later on using &amp;lt;code&amp;gt;$VARIABLE_NAME&amp;lt;/code&amp;gt; notation.&lt;br /&gt;
&lt;br /&gt;
Here are some examples showing sets defined in one line, spanning multiple lines, and sets referencing other sets. The set is then used in a rule to allow incoming traffic from certain IP ranges.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
define SIMPLE_SET = { 192.168.1.1, 192.168.1.2 }&lt;br /&gt;
&lt;br /&gt;
define CDN_EDGE = {&lt;br /&gt;
    192.168.1.1,&lt;br /&gt;
    192.168.1.2,&lt;br /&gt;
    192.168.1.3,&lt;br /&gt;
    10.0.0.0/8&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
define CDN_MONITORS = {&lt;br /&gt;
    192.168.1.10,&lt;br /&gt;
    192.168.1.20&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
define CDN = {&lt;br /&gt;
    $CDN_EDGE,&lt;br /&gt;
    $CDN_MONITORS&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Allow HTTP(S) from approved IP ranges only&lt;br /&gt;
tcp dport { http, https } ip saddr $CDN accept&lt;br /&gt;
udp dport { http, https } ip saddr $CDN accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Named sets specifications =&lt;br /&gt;
&lt;br /&gt;
Sets specifications are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;type&#039;&#039;&#039; or &#039;&#039;&#039;typeof&#039;&#039;&#039;, is obligatory and determines the data type of the set elements.&lt;br /&gt;
&lt;br /&gt;
Supported data types if using the &#039;&#039;&#039;type&#039;&#039;&#039; keyword are:&lt;br /&gt;
** &#039;&#039;ipv4_addr&#039;&#039;: IPv4 address&lt;br /&gt;
** &#039;&#039;ipv6_addr&#039;&#039;: IPv6 address.&lt;br /&gt;
** &#039;&#039;ether_addr&#039;&#039;: Ethernet address.&lt;br /&gt;
** &#039;&#039;inet_proto&#039;&#039;: Inet protocol type.&lt;br /&gt;
** &#039;&#039;inet_service&#039;&#039;: Internet service (read tcp port for example)&lt;br /&gt;
** &#039;&#039;mark&#039;&#039;: Mark type.&lt;br /&gt;
** &#039;&#039;ifname&#039;&#039;: Network interface name (eth0, eth1..)&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;typeof&#039;&#039;&#039; keyword is available since &#039;&#039;&#039;0.9.4&#039;&#039;&#039; and allows you to use a high level expression, then let nftables resolve the base type for you:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
	set s1 {&lt;br /&gt;
		typeof osf name&lt;br /&gt;
		elements = { &amp;quot;Linux&amp;quot; }&lt;br /&gt;
	}&lt;br /&gt;
	set s2 {&lt;br /&gt;
		typeof vlan id&lt;br /&gt;
		elements = { 2, 3, 103 }&lt;br /&gt;
	}&lt;br /&gt;
	set s3 {&lt;br /&gt;
		typeof ip daddr&lt;br /&gt;
		elements = { 1.1.1.1 }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;timeout&#039;&#039;&#039;, it determines how long an element stays in the set. The time string respects the format: &#039;&#039;&amp;quot;v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;dv&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;hv&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;mv&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;s&amp;quot;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft add set ip filter ports {type inet_service \; timeout 3h45s \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These commands create a table named &#039;&#039;filter&#039;&#039; and add a set named &#039;&#039;ports&#039;&#039; to it, where elements are deleted after 3 hours and 45 seconds of being added.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;flags&#039;&#039;&#039;, the available flags are:&lt;br /&gt;
** &#039;&#039;constant&#039;&#039; - set content may not change while bound&lt;br /&gt;
** &#039;&#039;interval&#039;&#039; - set contains intervals&lt;br /&gt;
** &#039;&#039;timeout&#039;&#039; - elements can be added with a timeout&lt;br /&gt;
&lt;br /&gt;
Multiple flags should be separated by comma:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter flags_set {type ipv4_addr\; flags constant, interval\;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;gc-interval&#039;&#039;&#039;, stands for garbage collection interval, can only be used if &#039;&#039;timeout&#039;&#039; or &#039;&#039;flags timeout&#039;&#039; are active. The interval follows the same format of &#039;&#039;timeouts&#039;&#039; time string &#039;&#039;&amp;quot;v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;dv&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;hv&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;mv&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;s&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;elements&#039;&#039;&#039;, initialize the set with some elements in it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter daddrs {type ipv4_addr \; flags timeout \; elements={192.168.1.1 timeout 10s, 192.168.1.2 timeout 30s} \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command creates a set name &#039;&#039;daddrs&#039;&#039; with elements &#039;&#039;192.168.1.1&#039;&#039;, which stays in it for 10s, and &#039;&#039;192.168.1.2&#039;&#039;, which stays for 30s.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;size&#039;&#039;&#039;, limits the maximum number of elements of the set. To create a set with maximum 2 elements type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter saddrs {type ipv4_addr \; size 2 \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;policy&#039;&#039;&#039;, determines set selection policy. Available values are:&lt;br /&gt;
** &#039;&#039;performance&#039;&#039; [default]&lt;br /&gt;
** &#039;&#039;memory&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Listing named sets =&lt;br /&gt;
&lt;br /&gt;
You can list the content of a named set via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list set ip filter myset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Concatenations&amp;diff=537</id>
		<title>Concatenations</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Concatenations&amp;diff=537"/>
		<updated>2020-09-03T09:13:25Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Network addresses */ refresh example with interval contacts&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Linux kernel 4.1, nftables supports concatenations.&lt;br /&gt;
&lt;br /&gt;
This new feature allows you to put two or more selectors together to perform very fast lookups by combining them with [[sets]], [[dictionaries]], [[maps]] and [[meters]].&lt;br /&gt;
&lt;br /&gt;
= Literal sets =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip saddr . ip daddr . ip protocol { 1.1.1.1 . 2.2.2.2 . tcp, 1.1.1.1 . 3.3.3.3 . udp} counter accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So if the packet&#039;s source IP address AND destination IP address AND level 4 protocol match:&lt;br /&gt;
&lt;br /&gt;
* 1.1.1.1 and 2.2.2.2 and TCP.&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
* 1.1.1.1 and 3.3.3.3 and UDP.&lt;br /&gt;
&lt;br /&gt;
nftables updates the counter for this rule and then accepts the packet.&lt;br /&gt;
&lt;br /&gt;
= Dictionary declarations =&lt;br /&gt;
&lt;br /&gt;
The following example creates the &#039;&#039;whitelist&#039;&#039; dictionary using a concatenation of two selectors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter whitelist { type ipv4_addr . inet_service : verdict \; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you create the dictionary, you can use it from a rule that creates the following concatenation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input ip saddr . tcp dport vmap @whitelist&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Thus, the rule above looks up for a verdict based on the source IP address AND the TCP destination port.&lt;br /&gt;
&lt;br /&gt;
Since the dictionary is initially empty, you can dynamically populate this dictionary with elements through:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element filter whitelist { 1.2.3.4 . 22 : accept}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Literal maps =&lt;br /&gt;
&lt;br /&gt;
The rule below determines the destination IP address that is used to perform DNAT to the packet based on:&lt;br /&gt;
&lt;br /&gt;
* the source IP address&lt;br /&gt;
&lt;br /&gt;
AND&lt;br /&gt;
&lt;br /&gt;
* the destination TCP port&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip nat prerouting dnat ip saddr . tcp dport map { 1.1.1.1 . 80 : 192.168.1.100, 2.2.2.2 . 8888 : 192.168.1.101 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
&lt;br /&gt;
Some concrete example concatenations so you get an idea on how powerful this new feature is.&lt;br /&gt;
&lt;br /&gt;
== Network addresses ==&lt;br /&gt;
&lt;br /&gt;
The example below implements a dictionary using network masks in each element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
table inet mytable {&lt;br /&gt;
    set myset {&lt;br /&gt;
        type ipv4_addr . ipv4_addr&lt;br /&gt;
        flags interval&lt;br /&gt;
        elements = { 192.168.0.0/16 . 172.16.0.0/25,&lt;br /&gt;
                     10.0.0.0/30 . 192.168.1.0/24,&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    chain mychain {&lt;br /&gt;
        ip saddr . ip daddr @myset counter accept&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: before kinux kernel 5.6 and nftables 0.9.4 the CIDR notation wasn&#039;t available, you would need to use a workaround:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . ip daddr and 255.255.255.0 vmap { 10.10.10.0 . 10.10.20.0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this is not an interval, this is masking the ip saddr and ip daddr, then concate both results. This concatenation is used to lookup for a matching of this the result in the map. This syntax may be compacted in future releases to support CIDR notation.&lt;br /&gt;
&lt;br /&gt;
This could be easily implemented using a named map as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map tablename myMap { type ipv4_addr . ipv4_addr : verdict \; }&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . ip saddr and 255.255.255.0 vmap @myMap&lt;br /&gt;
% nft add element tablename myMap { 10.10.10.0 . 10.10.20.0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interfaces ==&lt;br /&gt;
&lt;br /&gt;
The example below checks both input and output interfaces of a forwarded packet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname iif . oif vmap { eth0 . eth1 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note that using strings (for example iifname and oifname) and other variable sized data types is not supported yet.&lt;br /&gt;
&lt;br /&gt;
== Some ipset types ==&lt;br /&gt;
&lt;br /&gt;
These ipset types can be implemented in nftables using concatenations. Probably more equivalences exists, it just a matter of combining data types.&lt;br /&gt;
Of course, you could implement these as named maps/sets as well.&lt;br /&gt;
&lt;br /&gt;
See examples in the [[Moving_from_ipset_to_nftables | moving from ipset to nftables]] page.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=List_of_updates_since_Linux_kernel_3.13&amp;diff=536</id>
		<title>List of updates since Linux kernel 3.13</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=List_of_updates_since_Linux_kernel_3.13&amp;diff=536"/>
		<updated>2020-09-03T09:06:44Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add 5.6 reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A listing of the development progress.&lt;br /&gt;
&lt;br /&gt;
== 5.6 ==&lt;br /&gt;
&lt;br /&gt;
* Support for ranges (intervals) in concatenations&lt;br /&gt;
&lt;br /&gt;
== 4.16 ==&lt;br /&gt;
&lt;br /&gt;
* flowtable support&lt;br /&gt;
&lt;br /&gt;
== 4.15 ==&lt;br /&gt;
&lt;br /&gt;
* Fetch single elements of a set (i.e, nft get element)&lt;br /&gt;
&lt;br /&gt;
== 4.10 ==&lt;br /&gt;
&lt;br /&gt;
* notrack support&lt;br /&gt;
&lt;br /&gt;
== 4.3 ==&lt;br /&gt;
&lt;br /&gt;
* Enhancements for the limit expression, support for ratelimit bytes/time unit.&lt;br /&gt;
* Dup expression (equivalent to the &#039;&#039;TEE&#039;&#039; target in iptables) for IPv4 and IPv6.&lt;br /&gt;
* VLAN header matching support when NIC support offloads.&lt;br /&gt;
&lt;br /&gt;
== 4.2 ==&lt;br /&gt;
&lt;br /&gt;
* New &#039;netdev&#039; family for filtering from ingress.&lt;br /&gt;
* Context to x_tables extensions to know if they run from nft_compat.&lt;br /&gt;
&lt;br /&gt;
== 4.1 ==&lt;br /&gt;
&lt;br /&gt;
Major updates in the generic set infrastructure:&lt;br /&gt;
&lt;br /&gt;
* Concatenations.&lt;br /&gt;
* Timeout per set elements.&lt;br /&gt;
* Comments per set elements.&lt;br /&gt;
* Dynamic set instantiation.&lt;br /&gt;
&lt;br /&gt;
== 4.0 ==&lt;br /&gt;
&lt;br /&gt;
* Mostly fixes.&lt;br /&gt;
&lt;br /&gt;
== 3.19 ==&lt;br /&gt;
&lt;br /&gt;
* redirect support.&lt;br /&gt;
&lt;br /&gt;
== 3.18 ==&lt;br /&gt;
&lt;br /&gt;
* masquerading support.&lt;br /&gt;
* meta cpu, devgroup matching.&lt;br /&gt;
* reject bridge support.&lt;br /&gt;
* destroy table and its content, ie. &#039;&#039;nft flush ruleset&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 3.17 ==&lt;br /&gt;
&lt;br /&gt;
* log and nflog support for ip, ip6, arp and bridge families.&lt;br /&gt;
&lt;br /&gt;
== 3.16 ==&lt;br /&gt;
&lt;br /&gt;
* connlabel support.&lt;br /&gt;
&lt;br /&gt;
== 3.15 ==&lt;br /&gt;
&lt;br /&gt;
* Comments per rule support.&lt;br /&gt;
* IPv4 reject support.&lt;br /&gt;
&lt;br /&gt;
== 3.14 ==&lt;br /&gt;
&lt;br /&gt;
* set packet mark support.&lt;br /&gt;
* nfqueue support (only for ip and ip6 families).&lt;br /&gt;
* rule tracing support.&lt;br /&gt;
* IPv6 and inet reject support.&lt;br /&gt;
&lt;br /&gt;
== 3.13 ==&lt;br /&gt;
&lt;br /&gt;
* nf_tables merged mainstream.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=List_of_updates_since_Linux_kernel_3.13&amp;diff=535</id>
		<title>List of updates since Linux kernel 3.13</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=List_of_updates_since_Linux_kernel_3.13&amp;diff=535"/>
		<updated>2020-09-03T09:05:58Z</updated>

		<summary type="html">&lt;p&gt;Arturo: sort in reverse order&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A listing of the development progress.&lt;br /&gt;
&lt;br /&gt;
== 4.16 ==&lt;br /&gt;
&lt;br /&gt;
* flowtable support&lt;br /&gt;
&lt;br /&gt;
== 4.15 ==&lt;br /&gt;
&lt;br /&gt;
* Fetch single elements of a set (i.e, nft get element)&lt;br /&gt;
&lt;br /&gt;
== 4.10 ==&lt;br /&gt;
&lt;br /&gt;
* notrack support&lt;br /&gt;
&lt;br /&gt;
== 4.3 ==&lt;br /&gt;
&lt;br /&gt;
* Enhancements for the limit expression, support for ratelimit bytes/time unit.&lt;br /&gt;
* Dup expression (equivalent to the &#039;&#039;TEE&#039;&#039; target in iptables) for IPv4 and IPv6.&lt;br /&gt;
* VLAN header matching support when NIC support offloads.&lt;br /&gt;
&lt;br /&gt;
== 4.2 ==&lt;br /&gt;
&lt;br /&gt;
* New &#039;netdev&#039; family for filtering from ingress.&lt;br /&gt;
* Context to x_tables extensions to know if they run from nft_compat.&lt;br /&gt;
&lt;br /&gt;
== 4.1 ==&lt;br /&gt;
&lt;br /&gt;
Major updates in the generic set infrastructure:&lt;br /&gt;
&lt;br /&gt;
* Concatenations.&lt;br /&gt;
* Timeout per set elements.&lt;br /&gt;
* Comments per set elements.&lt;br /&gt;
* Dynamic set instantiation.&lt;br /&gt;
&lt;br /&gt;
== 4.0 ==&lt;br /&gt;
&lt;br /&gt;
* Mostly fixes.&lt;br /&gt;
&lt;br /&gt;
== 3.19 ==&lt;br /&gt;
&lt;br /&gt;
* redirect support.&lt;br /&gt;
&lt;br /&gt;
== 3.18 ==&lt;br /&gt;
&lt;br /&gt;
* masquerading support.&lt;br /&gt;
* meta cpu, devgroup matching.&lt;br /&gt;
* reject bridge support.&lt;br /&gt;
* destroy table and its content, ie. &#039;&#039;nft flush ruleset&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 3.17 ==&lt;br /&gt;
&lt;br /&gt;
* log and nflog support for ip, ip6, arp and bridge families.&lt;br /&gt;
&lt;br /&gt;
== 3.16 ==&lt;br /&gt;
&lt;br /&gt;
* connlabel support.&lt;br /&gt;
&lt;br /&gt;
== 3.15 ==&lt;br /&gt;
&lt;br /&gt;
* Comments per rule support.&lt;br /&gt;
* IPv4 reject support.&lt;br /&gt;
&lt;br /&gt;
== 3.14 ==&lt;br /&gt;
&lt;br /&gt;
* set packet mark support.&lt;br /&gt;
* nfqueue support (only for ip and ip6 families).&lt;br /&gt;
* rule tracing support.&lt;br /&gt;
* IPv6 and inet reject support.&lt;br /&gt;
&lt;br /&gt;
== 3.13 ==&lt;br /&gt;
&lt;br /&gt;
* nf_tables merged mainstream.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=534</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=534"/>
		<updated>2020-09-03T08:56:11Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Base chain priority */ mention priority strings&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, you attach your [[Simple rule management|rules]] to chains. However, contrary to the &#039;&#039;iptables&#039;&#039; modus operandi, the &#039;&#039;nftables&#039;&#039; infrastructure comes with no predefined chains, so you need to register your base chains in first place before you can add any rule. This allows very flexible configurations.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
The syntax to add base chains is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain [&amp;lt;family&amp;gt;] &amp;lt;table-name&amp;gt; &amp;lt;chain-name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; priority &amp;lt;value&amp;gt; \; [policy &amp;lt;policy&amp;gt;] } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], ie. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The following example show how you can add new base chains to the &#039;&#039;foo&#039;&#039; table (that need to be created prior) through the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: nft re-uses special characters, such as curly braces and the semicolon.I&lt;br /&gt;
f you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need&lt;br /&gt;
to be escaped.  The most simple way to prevent the shell from attempting to parse the nft syntax&lt;br /&gt;
is to quote everything withing single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another.&lt;br /&gt;
For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order.  Its possible to give two base chains the same priority, but there&lt;br /&gt;
is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, ie. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a non-base chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain netdev foo dev0filter { type filter hook ingress device eth0 priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is obviously used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). The first packet that belongs to a flow always hits this chain, follow up packets not. Therefore, never use this chain for filtering. This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible hooks that you can use when you configure your chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: the routing decision for those packets didn&#039;t happen yet, so you don&#039;t know if they are addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: It happens after the routing decision, you can see packets that are directed to the local system and processes running in system.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: It also happens after the routing decision, you can see packet that are not directed to the local machine.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: to catch packets that are originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: After the routing decision for packets leaving the local system.&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only available at the &#039;&#039;netdev&#039;&#039; family): Since Linux kernel 4.2, you can filter traffic way before prerouting, after the packet is passed up from the NIC driver. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
The priority can be used to order the chains or to put them before or after some Netfilter internal operations. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with the priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: starting with nftables 0.9.6 you may use keywords instead of numbers to configure the chain priority. Check the nft manpage for reference.&lt;br /&gt;
&lt;br /&gt;
For reference, here&#039;s the list of different priority used in iptables:&lt;br /&gt;
&lt;br /&gt;
* NF_IP_PRI_CONNTRACK_DEFRAG (-400): priority of defragmentation&lt;br /&gt;
* NF_IP_PRI_RAW (-300): traditional priority of the raw table placed before connection tracking operation&lt;br /&gt;
* NF_IP_PRI_SELINUX_FIRST (-225): SELinux operations&lt;br /&gt;
* NF_IP_PRI_CONNTRACK (-200): Connection tracking operations&lt;br /&gt;
* NF_IP_PRI_MANGLE (-150): mangle operation&lt;br /&gt;
* NF_IP_PRI_NAT_DST (-100): destination NAT&lt;br /&gt;
* NF_IP_PRI_FILTER (0): filtering operation, the filter table&lt;br /&gt;
* NF_IP_PRI_SECURITY (50): Place of security table where secmark can be set for example&lt;br /&gt;
* NF_IP_PRI_NAT_SRC (100): source NAT&lt;br /&gt;
* NF_IP_PRI_SELINUX_LAST (225): SELinux at packet exit&lt;br /&gt;
* NF_IP_PRI_CONNTRACK_HELPER (300): connection tracking at exit&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: if a packet gets accepted and there is another base chain in the same hook which is ordered with a later priority, the packet will be evaluated &#039;&#039;&#039;again&#039;&#039;&#039;.&lt;br /&gt;
That is, packets will traverse chains in a given hook, until it is dropped or no more base chains exist. Drops take instant effect, no further rules or chains are evaluated.&lt;br /&gt;
&lt;br /&gt;
Example ruleset of this behavior:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table inet filter {&lt;br /&gt;
        # this chain is evaluated first due to priority&lt;br /&gt;
        chain ssh {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                # ssh packet accepted&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # this chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # the same ssh packet is dropped here by means of default policy&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If priority of the &#039;input chain&#039; above would be changed to -1, all packets would be dropped.&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding non-base chains =&lt;br /&gt;
&lt;br /&gt;
You can also create non-base chains as in &#039;&#039;iptables&#039;&#039; via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain ip &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this chain does &#039;&#039;&#039;not&#039;&#039;&#039; see any traffic as it is not attached to any hook, but it can be very useful to arrange your rule-set in a tree of chains by using the [[jumping to chain|jump to chain]] action.&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete the chains that you don&#039;t need, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will tell you that such chain is in used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip foo input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chain =&lt;br /&gt;
&lt;br /&gt;
You can also flush the content of a chain. If you want to flush all the rule in the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;foo&#039;&#039; table, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft flush chain foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft &#039;add chain ip filter input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
% nft &#039;add chain ip filter output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Multiple_NATs_using_nftables_maps&amp;diff=533</id>
		<title>Multiple NATs using nftables maps</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Multiple_NATs_using_nftables_maps&amp;diff=533"/>
		<updated>2020-08-28T11:02:09Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add see also section with pointer to general docs on NAT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Thanks to nftables [[Maps]], if you have a previous iptables NAT (destination NAT) ruleset like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% iptables -t nat -A PREROUTING -p tcp --dport 1000 -j DNAT --to-destination 1.1.1.1:1234&lt;br /&gt;
% iptables -t nat -A PREROUTING -p udp --dport 2000 -j DNAT --to-destination 2.2.2.2:2345&lt;br /&gt;
% iptables -t nat -A PREROUTING -p tcp --dport 3000 -j DNAT --to-destination 3.3.3.3:3456&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It can be easily translated to nftables in a single line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting dnat \&lt;br /&gt;
      tcp dport map { 1000 : 1.1.1.1, 2000 : 2.2.2.2, 3000 : 3.3.3.3} \&lt;br /&gt;
      : tcp dport map { 1000 : 1234, 2000 : 2345, 3000 : 3456 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Likewise, in iptables NAT (source NAT):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% iptables -t nat -A POSTROUTING -s 192.168.1.1 -j SNAT --to-source 1.1.1.1&lt;br /&gt;
% iptables -t nat -A POSTROUTING -s 192.168.2.2 -j SNAT --to-source 2.2.2.2&lt;br /&gt;
% iptables -t nat -A POSTROUTING -s 192.168.3.3 -j SNAT --to-source 3.3.3.3&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Translated to a nftables one-liner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting snat \&lt;br /&gt;
      ip saddr map { 192.168.1.1 : 1.1.1.1, 192.168.2.2 : 2.2.2.2, 192.168.3.3 : 3.3.3.3 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Performing_Network_Address_Translation_(NAT) | Performing NAT with nftables]]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=532</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=532"/>
		<updated>2020-08-28T11:01:23Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add see also section with pointer to example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform NAT. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in a prerouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking.&lt;br /&gt;
&lt;br /&gt;
This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot.&lt;br /&gt;
If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets.&lt;br /&gt;
&lt;br /&gt;
The example below sets IP/port for each packet (also valid in IPv6):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule ip raw prerouting ip protocol tcp ip daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
% nft add rule ip6 raw prerouting ip6 nexthdr tcp ip6 daddr set fe00::1 tcp dport set 10 notrack&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangle packet header fields | mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Simple_rule_management&amp;diff=530</id>
		<title>Simple rule management</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Simple_rule_management&amp;diff=530"/>
		<updated>2020-07-22T10:38:12Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Listing rules */ add pointer to output text modifiers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Appending new rules =&lt;br /&gt;
&lt;br /&gt;
To add new rules, you have to specify the corresponding table and the chain that you want to use, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output ip daddr 8.8.8.8 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;filter&#039;&#039; is the table and &#039;&#039;output&#039;&#039; is the chain. The example above adds a rule to match all packets seen by the output chain whose destination is 8.8.8.8, in case of matching it updates the rule counters. Note that counters are optional in &#039;&#039;nftables&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
For those familiar with iptables, the rule appending is equivalent to &#039;&#039;-A&#039;&#039; command in iptables.&lt;br /&gt;
&lt;br /&gt;
= Listing rules =&lt;br /&gt;
&lt;br /&gt;
You can list the rules that are contained by a table with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 0 bytes 0&lt;br /&gt;
                 tcp dport ssh counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also list rules by chain, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list chain filter ouput&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 0 bytes 0&lt;br /&gt;
                 tcp dport ssh counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are plenty of [[Output_text_modifiers | output text modifiers]] than can be used when listing your rules, to for example, translate IP addresses to DNS names, TCP protocols, etc.&lt;br /&gt;
&lt;br /&gt;
= Testing your rule =&lt;br /&gt;
&lt;br /&gt;
Let&#039;s test this rule with a simple ping to 8.8.8.8:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% ping -c 1 8.8.8.8&lt;br /&gt;
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.&lt;br /&gt;
64 bytes from 8.8.8.8: icmp_req=1 ttl=64 time=1.31 ms&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if we list the rule-set, we obtain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -nn list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 1 bytes 84&lt;br /&gt;
                 tcp dport 22 counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the counters have been updated.&lt;br /&gt;
&lt;br /&gt;
= Adding a rule at a given position =&lt;br /&gt;
&lt;br /&gt;
If you want to add a rule at a given position, you have to use the handle as reference:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter -n -a&lt;br /&gt;
table filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip protocol tcp counter packets 82 bytes 9680 # handle 8&lt;br /&gt;
                 ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to add a rule after the rule with handler number 8, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output position 8 ip daddr 127.0.0.8 drop &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can check the effect of that command by listing the rule-set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter -n -a&lt;br /&gt;
table filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip protocol tcp counter packets 190 bytes 21908 # handle 8&lt;br /&gt;
                 ip daddr 127.0.0.8 drop # handle 10&lt;br /&gt;
                 ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to insert a rule before the rule with handler number 8, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft insert rule filter output position 8 ip daddr 127.0.0.8 drop &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Removing rules =&lt;br /&gt;
&lt;br /&gt;
You have to obtain the &#039;&#039;handle&#039;&#039; to delete a rule via the &#039;&#039;&#039;-a&#039;&#039;&#039; option. The &#039;&#039;handle&#039;&#039; is automagically assigned by the kernel and it uniquely identifies the rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter -a&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 192.168.1.1 counter packets 1 bytes 84 # handle 5&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can delete the rule whose handle is &#039;&#039;5&#039;&#039; with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output handle 5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: There are plans to support rule deletion by passing:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output ip saddr 192.168.1.1 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
but this is &#039;&#039;&#039;not&#039;&#039;&#039; yet implemented. So you&#039;ll have to use the handle to delete rules until that feature is implemented.&lt;br /&gt;
&lt;br /&gt;
= Removing all the rules in a chain =&lt;br /&gt;
&lt;br /&gt;
You can delete &#039;&#039;&#039;all the rules&#039;&#039;&#039; in a chain with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also delete &#039;&#039;&#039;all the rules&#039;&#039;&#039; in a table with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft flush table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prepending new rules =&lt;br /&gt;
&lt;br /&gt;
To prepend new rules through the &#039;&#039;insert&#039;&#039; command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft insert rule filter output ip daddr 192.168.1.1 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This prepends a rule that will update per-rule packet and bytes counters for traffic addressed to 192.168.1.1.&lt;br /&gt;
&lt;br /&gt;
The equivalent in iptables is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% iptables -I OUTPUT -t filter -d 192.168.1.1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that iptables always provides per-rule counters.&lt;br /&gt;
&lt;br /&gt;
= Replacing rules =&lt;br /&gt;
&lt;br /&gt;
You can replace any rule via the &#039;&#039;replace&#039;&#039; command by indicating the rule handle. Therefore, first you have to list the ruleset with option &#039;&#039;-a&#039;&#039; to obtain the rule handle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft list ruleset -a&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                ip protocol tcp counter packets 0 bytes 0 # handle 2&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, assuming you want to replace rule with handle number 2, you have to specify this handle number and the new rule that you want to place instead of it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft replace rule filter input handle 2 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, when listing back the ruleset:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft list ruleset -a&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                counter packets 0 bytes 0 &lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can effective note that the rule has been replaced by a simple rule that counts any packets, instead of counting TCP packets as the previous rule was doing.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Output_text_modifiers&amp;diff=529</id>
		<title>Output text modifiers</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Output_text_modifiers&amp;diff=529"/>
		<updated>2020-07-22T10:36:59Z</updated>

		<summary type="html">&lt;p&gt;Arturo: create page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information on the several &#039;&#039;&#039;output text modifiers&#039;&#039;&#039; that nftables support when using the command line interface &#039;&#039;&#039;nft&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You can generally check all the output modifiers by using &#039;&#039;&#039;nft --help&#039;&#039;&#039; or reading the manpage &#039;&#039;&#039;nft(8)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  -n, numeric                   Print fully numerical output.&lt;br /&gt;
  -s, stateless                 Omit stateful information of ruleset.&lt;br /&gt;
  -N, reversedns                Translate IP addresses to names.&lt;br /&gt;
  -S, service                   Translate ports to service names as described in /etc/services.&lt;br /&gt;
  -a, handle                    Output rule handle.&lt;br /&gt;
  -j, json                      Format output in JSON&lt;br /&gt;
  -u, guid                      Print UID/GID as defined in /etc/passwd and /etc/group.&lt;br /&gt;
  -y, numeric-priority          Print chain priority numerically.&lt;br /&gt;
  -p, numeric-protocol          Print layer 4 protocols numerically.&lt;br /&gt;
  -T, numeric-time              Print time values numerically.&lt;br /&gt;
  -t, terse                     Omit contents of sets.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default output prints some information in numeric form and for well-known names it will use a string instead (like icmp types, conntrack status, chain priorities, etc).&lt;br /&gt;
Also, state information such as counter values and set elements are printed as well.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% nft list ruleset&lt;br /&gt;
table inet filter {&lt;br /&gt;
	set s {&lt;br /&gt;
		type inet_service&lt;br /&gt;
		elements = { 80, 443 }&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	chain input {&lt;br /&gt;
		type filter hook input priority filter; policy accept;&lt;br /&gt;
		counter packets 4447 bytes 1619415&lt;br /&gt;
		iif &amp;quot;lo&amp;quot; counter packets 337 bytes 25076 accept&lt;br /&gt;
		ct state established,related counter packets 44899 bytes 106405802 accept&lt;br /&gt;
		ip6 nexthdr ipv6-icmp icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter packets 1 bytes 72 accept&lt;br /&gt;
		tcp dport 22 drop&lt;br /&gt;
		ip saddr 8.8.8.8 drop&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== translation modifiers ==&lt;br /&gt;
&lt;br /&gt;
Translate various values to text equivalents, or the other way around. We can group here things like ports, DNS names, service names, UID/GID, etc.&lt;br /&gt;
&lt;br /&gt;
The options can be combined at will. The example below shows service names (instead of the integer number), chain priority value (instead of the well-known string), conntrack/protocol numbers and constants (instead of well-known strings) and shows reverse DNS names (instead of the numeric IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% nft -nNSy list ruleset&lt;br /&gt;
table inet filter {&lt;br /&gt;
	set s {&lt;br /&gt;
		type inet_service&lt;br /&gt;
		elements = { &amp;quot;http&amp;quot;, &amp;quot;https&amp;quot; }&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	chain input {&lt;br /&gt;
		type filter hook input priority 0; policy accept;&lt;br /&gt;
		iif &amp;quot;lo&amp;quot; counter packets 365 bytes 27092 accept&lt;br /&gt;
		ct state 0x2,0x4 counter packets 48535 bytes 142472901 accept&lt;br /&gt;
		ip6 nexthdr 58 icmpv6 type { 134, 135, 136 } counter packets 1 bytes 72 accept&lt;br /&gt;
		ip saddr dns.google counter packets 0 bytes 0&lt;br /&gt;
		tcp dport &amp;quot;ssh&amp;quot; accept&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that translating some elements might take additional operation time when generating the output. For example translating IP addresses to names require queries to DNS servers, which can be very slow for large rulesets (and therefore is disabled by default).&lt;br /&gt;
&lt;br /&gt;
== operations and parsing modifiers ==&lt;br /&gt;
&lt;br /&gt;
These modifiers add or remove information about the ruleset, generally useful when parsing the output or doing related operations.&lt;br /&gt;
&lt;br /&gt;
You can display the ruleset without stateful information (for example, without counter values), with handles, and with no set contents:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% nft -sta list ruleset&lt;br /&gt;
table inet filter { # handle 5&lt;br /&gt;
	set s { # handle 9&lt;br /&gt;
		type inet_service&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	chain input { # handle 1&lt;br /&gt;
		type filter hook input priority filter; policy accept;&lt;br /&gt;
		iif &amp;quot;lo&amp;quot; counter accept # handle 3&lt;br /&gt;
		ct state established,related counter accept # handle 4&lt;br /&gt;
		ip6 nexthdr ipv6-icmp icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept # handle 5&lt;br /&gt;
		ip saddr 8.8.8.8 counter # handle 8&lt;br /&gt;
		tcp dport 22 accept # handle 10&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Special mention to the JSON representation of the ruleset. The JSON will be printed in a single line fashion. Here we format the JSON using perl&#039;s json_pp utility:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% nft -j list ruleset | json_pp&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;nftables&amp;quot; : [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;metainfo&amp;quot; : {&lt;br /&gt;
            &amp;quot;json_schema_version&amp;quot; : 1,&lt;br /&gt;
            &amp;quot;release_name&amp;quot; : &amp;quot;Capital Idea #2&amp;quot;,&lt;br /&gt;
            &amp;quot;version&amp;quot; : &amp;quot;0.9.6&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;table&amp;quot; : {&lt;br /&gt;
            &amp;quot;family&amp;quot; : &amp;quot;inet&amp;quot;,&lt;br /&gt;
            &amp;quot;handle&amp;quot; : 5,&lt;br /&gt;
            &amp;quot;name&amp;quot; : &amp;quot;filter&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;set&amp;quot; : {&lt;br /&gt;
            &amp;quot;elem&amp;quot; : [&lt;br /&gt;
               80,&lt;br /&gt;
               443&lt;br /&gt;
            ],&lt;br /&gt;
            &amp;quot;family&amp;quot; : &amp;quot;inet&amp;quot;,&lt;br /&gt;
            &amp;quot;handle&amp;quot; : 9,&lt;br /&gt;
            &amp;quot;name&amp;quot; : &amp;quot;s&amp;quot;,&lt;br /&gt;
            &amp;quot;table&amp;quot; : &amp;quot;filter&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot; : &amp;quot;inet_service&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;chain&amp;quot; : {&lt;br /&gt;
            &amp;quot;family&amp;quot; : &amp;quot;inet&amp;quot;,&lt;br /&gt;
            &amp;quot;handle&amp;quot; : 1,&lt;br /&gt;
            &amp;quot;hook&amp;quot; : &amp;quot;input&amp;quot;,&lt;br /&gt;
            &amp;quot;name&amp;quot; : &amp;quot;input&amp;quot;,&lt;br /&gt;
            &amp;quot;policy&amp;quot; : &amp;quot;accept&amp;quot;,&lt;br /&gt;
            &amp;quot;prio&amp;quot; : 0,&lt;br /&gt;
            &amp;quot;table&amp;quot; : &amp;quot;filter&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot; : &amp;quot;filter&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;rule&amp;quot; : {&lt;br /&gt;
            &amp;quot;chain&amp;quot; : &amp;quot;input&amp;quot;,&lt;br /&gt;
            &amp;quot;expr&amp;quot; : [&lt;br /&gt;
               {&lt;br /&gt;
                  &amp;quot;counter&amp;quot; : {&lt;br /&gt;
                     &amp;quot;bytes&amp;quot; : 37707381,&lt;br /&gt;
                     &amp;quot;packets&amp;quot; : 8062&lt;br /&gt;
                  }&lt;br /&gt;
               }&lt;br /&gt;
            ],&lt;br /&gt;
            &amp;quot;family&amp;quot; : &amp;quot;inet&amp;quot;,&lt;br /&gt;
            &amp;quot;handle&amp;quot; : 7,&lt;br /&gt;
            &amp;quot;table&amp;quot; : &amp;quot;filter&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Main_Page&amp;diff=528</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Main_Page&amp;diff=528"/>
		<updated>2020-07-22T10:10:47Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Basic operation */ add link to the new page output text modifiers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the &#039;&#039;nftables&#039;&#039; HOWTO documentation page. Here you will find documentation on how to build, install, configure and use nftables.&lt;br /&gt;
&lt;br /&gt;
If you have any suggestion to improve it, please send your comments to Netfilter users mailing list &amp;lt;netfilter@vger.kernel.org&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
&lt;br /&gt;
* [[What is nftables?]]&lt;br /&gt;
* [[Why nftables?]]&lt;br /&gt;
* [[Main differences with iptables]]&lt;br /&gt;
* [[Netfilter hooks]] and integration with existing Netfilter components.&lt;br /&gt;
* [[Adoption]]&lt;br /&gt;
* [[Legacy xtables tools]]&lt;br /&gt;
* [[How to obtain help/support]]&lt;br /&gt;
&lt;br /&gt;
= Getting started =&lt;br /&gt;
&lt;br /&gt;
* [[Building and installing nftables from sources]]&lt;br /&gt;
* Using [[nftables from distributions]]&lt;br /&gt;
* [[Troubleshooting|Troubleshooting and FAQ]]&lt;br /&gt;
* [[Quick reference-nftables in 10 minutes|Quick reference, nftables in 10 minutes]]&lt;br /&gt;
* [[nftables families|Understanding nftables families]]&lt;br /&gt;
&lt;br /&gt;
= Basic operation =&lt;br /&gt;
&lt;br /&gt;
* [[Configuring tables]]&lt;br /&gt;
* [[Configuring chains]]&lt;br /&gt;
* [[Simple rule management]]&lt;br /&gt;
* [[Atomic rule replacement]]&lt;br /&gt;
* [[Error reporting from the command line]]&lt;br /&gt;
* [[Building rules through expressions]]&lt;br /&gt;
* [[Operations at ruleset level]]&lt;br /&gt;
* [[Monitoring ruleset updates]]&lt;br /&gt;
* [[Scripting]]&lt;br /&gt;
* [[Ruleset debug/tracing]]&lt;br /&gt;
* [[Moving from iptables to nftables]]&lt;br /&gt;
* [[Moving from ipset to nftables]]&lt;br /&gt;
* [[Output text modifiers]]&lt;br /&gt;
&lt;br /&gt;
= Supported selectors for packet matching =&lt;br /&gt;
&lt;br /&gt;
* [[Matching packet header fields]]&lt;br /&gt;
* [[Matching packet metainformation]]&lt;br /&gt;
* [[Matching connection tracking stateful metainformation]]&lt;br /&gt;
* [[Rate limiting matchings]]&lt;br /&gt;
* [[Routing information]]&lt;br /&gt;
&lt;br /&gt;
= Possible actions on packets =&lt;br /&gt;
&lt;br /&gt;
* [[Accepting and dropping packets]]&lt;br /&gt;
* [[Jumping to chain]]&lt;br /&gt;
* [[Rejecting traffic]]&lt;br /&gt;
* [[Logging traffic]]&lt;br /&gt;
* [[Performing Network Address Translation (NAT)]]&lt;br /&gt;
* [[Setting packet metainformation]]&lt;br /&gt;
* [[Queueing to userspace]]&lt;br /&gt;
* [[Duplicating packets]]&lt;br /&gt;
* [[Mangle packet header fields]]&lt;br /&gt;
* [[Mangle TCP options]]&lt;br /&gt;
* [[Counters]]&lt;br /&gt;
* [[Load balancing]]&lt;br /&gt;
* [[Setting packet connection tracking metainformation]]&lt;br /&gt;
&lt;br /&gt;
Note that, unlike &#039;&#039;iptables&#039;&#039;, you can perform several actions in one single rule.&lt;br /&gt;
&lt;br /&gt;
= Advanced data structures for performance packet classification =&lt;br /&gt;
&lt;br /&gt;
You will have to redesign your rule-set to benefit from these new nice features:&lt;br /&gt;
&lt;br /&gt;
* [[Sets]]&lt;br /&gt;
* [[Dictionaries]]&lt;br /&gt;
* [[Intervals]]&lt;br /&gt;
* [[Maps]]&lt;br /&gt;
* [[Concatenations]]&lt;br /&gt;
* [[Meters|Metering]] (formerly known as flow tables before nftables 0.8.1 release)&lt;br /&gt;
* [[Updating sets from the packet path]]&lt;br /&gt;
* [[Element timeouts]]&lt;br /&gt;
* [[Math operations]]&lt;br /&gt;
* [[Stateful objects]]&lt;br /&gt;
* [[Flowtable]] (the fastpath network stack bypass)&lt;br /&gt;
&lt;br /&gt;
If you are already using [[ipset]] in your &#039;&#039;iptables&#039;&#039; rule-set, that transition may be a bit more simple to you.&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
&lt;br /&gt;
* [[Simple ruleset for a workstation]]&lt;br /&gt;
* [[Simple ruleset for a server]]&lt;br /&gt;
* [[Bridge filtering]]&lt;br /&gt;
* [[Multiple NATs using nftables maps]]&lt;br /&gt;
* [[Classic perimetral firewall example]]&lt;br /&gt;
* [[Port knocking example]]&lt;br /&gt;
* [[Classification to tc structure example]]&lt;br /&gt;
* [[Using configuration management systems]] (like puppet, ansible, etc)&lt;br /&gt;
* [[GeoIP matching]]&lt;br /&gt;
&lt;br /&gt;
= Development =&lt;br /&gt;
&lt;br /&gt;
Check [[Portal:DeveloperDocs|Portal:DeveloperDocs - documentation for netfilter developers]].&lt;br /&gt;
&lt;br /&gt;
Some hints on the general development progress:&lt;br /&gt;
&lt;br /&gt;
* [[List of updates since Linux kernel 3.13]]&lt;br /&gt;
* [[List of updates in the nft command line tool]]&lt;br /&gt;
* [[Supported features compared to xtables|Supported features compared to {ip,ip6,eb,arp}tables]]&lt;br /&gt;
* [[List of available translations via iptables-translate tool]]&lt;br /&gt;
&lt;br /&gt;
= External links =&lt;br /&gt;
&lt;br /&gt;
Watch some videos:&lt;br /&gt;
&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=FXTRRwXi3b4 Getting a grasp of nftables], thanks to [https://www.nluug.nl/index-en.html NLUUG association] for recording this.&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=CaYp0d2wiuU#t=1m47s The ultimate packet classifier for GNU/Linux], thanks to the FSFE for paying my trip to Barcelona and for recommending me as speaker to the KDE Spanish branch.&lt;br /&gt;
* [https://www.youtube.com/watch?v=Sy0JDX451ns Florian Westphal - Why nftables?]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=qXVOA2MKA1s Netdev 2.1 - Netfilter workshop]&lt;br /&gt;
* Watch [https://youtu.be/iCj10vEKPrw Netdev 2.2 - Netf‌ilter mini-workshop]&lt;br /&gt;
* Watch [https://youtu.be/0hqfzp6tpZo Netdev 0x12 - Netf‌ilter mini-workshop]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=0wQfSfDVN94 NLUUG - Goodbye iptables, Hello nftables]&lt;br /&gt;
* Watch [https://www.youtube.com/watch?v=Uf5ULkEWPL0 LCA2018 - nftables from a user perspective]&lt;br /&gt;
&lt;br /&gt;
Additional documentations and articles:&lt;br /&gt;
&lt;br /&gt;
* Tutorial [https://zasdfgbnm.github.io/2017/09/07/Extending-nftables/ Extending nftables by Xiang Gao]&lt;br /&gt;
* Article [http://ral-arturo.org/2017/05/05/debian-stretch-stable-nftables.html New in Debian stable Stretch: nftables]&lt;br /&gt;
&lt;br /&gt;
= Thanks =&lt;br /&gt;
&lt;br /&gt;
To the NLnet foundation for initial sponsorship of this HOWTO:&lt;br /&gt;
&lt;br /&gt;
[https://nlnet.nl https://nlnet.nl/image/logo.gif]&lt;br /&gt;
&lt;br /&gt;
To Eric Leblond, for boostrapping the [https://home.regit.org/netfilter-en/nftables-quick-howto/ Nftables quick howto] in 2013.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Simple_rule_management&amp;diff=527</id>
		<title>Simple rule management</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Simple_rule_management&amp;diff=527"/>
		<updated>2020-07-22T10:09:18Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Listing rules */ modernize this information, will separate output modifiers to other page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Appending new rules =&lt;br /&gt;
&lt;br /&gt;
To add new rules, you have to specify the corresponding table and the chain that you want to use, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output ip daddr 8.8.8.8 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;filter&#039;&#039; is the table and &#039;&#039;output&#039;&#039; is the chain. The example above adds a rule to match all packets seen by the output chain whose destination is 8.8.8.8, in case of matching it updates the rule counters. Note that counters are optional in &#039;&#039;nftables&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
For those familiar with iptables, the rule appending is equivalent to &#039;&#039;-A&#039;&#039; command in iptables.&lt;br /&gt;
&lt;br /&gt;
= Listing rules =&lt;br /&gt;
&lt;br /&gt;
You can list the rules that are contained by a table with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 0 bytes 0&lt;br /&gt;
                 tcp dport ssh counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also list rules by chain, for example:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list chain filter ouput&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 0 bytes 0&lt;br /&gt;
                 tcp dport ssh counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Testing your rule =&lt;br /&gt;
&lt;br /&gt;
Let&#039;s test this rule with a simple ping to 8.8.8.8:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% ping -c 1 8.8.8.8&lt;br /&gt;
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.&lt;br /&gt;
64 bytes from 8.8.8.8: icmp_req=1 ttl=64 time=1.31 ms&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if we list the rule-set, we obtain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -nn list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 8.8.8.8 counter packets 1 bytes 84&lt;br /&gt;
                 tcp dport 22 counter packets 0 bytes 0&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the counters have been updated.&lt;br /&gt;
&lt;br /&gt;
= Adding a rule at a given position =&lt;br /&gt;
&lt;br /&gt;
If you want to add a rule at a given position, you have to use the handle as reference:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter -n -a&lt;br /&gt;
table filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip protocol tcp counter packets 82 bytes 9680 # handle 8&lt;br /&gt;
                 ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to add a rule after the rule with handler number 8, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output position 8 ip daddr 127.0.0.8 drop &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can check the effect of that command by listing the rule-set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter -n -a&lt;br /&gt;
table filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip protocol tcp counter packets 190 bytes 21908 # handle 8&lt;br /&gt;
                 ip daddr 127.0.0.8 drop # handle 10&lt;br /&gt;
                 ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to insert a rule before the rule with handler number 8, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft insert rule filter output position 8 ip daddr 127.0.0.8 drop &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Removing rules =&lt;br /&gt;
&lt;br /&gt;
You have to obtain the &#039;&#039;handle&#039;&#039; to delete a rule via the &#039;&#039;&#039;-a&#039;&#039;&#039; option. The &#039;&#039;handle&#039;&#039; is automagically assigned by the kernel and it uniquely identifies the rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter -a&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 ip daddr 192.168.1.1 counter packets 1 bytes 84 # handle 5&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can delete the rule whose handle is &#039;&#039;5&#039;&#039; with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output handle 5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: There are plans to support rule deletion by passing:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output ip saddr 192.168.1.1 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
but this is &#039;&#039;&#039;not&#039;&#039;&#039; yet implemented. So you&#039;ll have to use the handle to delete rules until that feature is implemented.&lt;br /&gt;
&lt;br /&gt;
= Removing all the rules in a chain =&lt;br /&gt;
&lt;br /&gt;
You can delete &#039;&#039;&#039;all the rules&#039;&#039;&#039; in a chain with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete rule filter output&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also delete &#039;&#039;&#039;all the rules&#039;&#039;&#039; in a table with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft flush table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prepending new rules =&lt;br /&gt;
&lt;br /&gt;
To prepend new rules through the &#039;&#039;insert&#039;&#039; command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft insert rule filter output ip daddr 192.168.1.1 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This prepends a rule that will update per-rule packet and bytes counters for traffic addressed to 192.168.1.1.&lt;br /&gt;
&lt;br /&gt;
The equivalent in iptables is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% iptables -I OUTPUT -t filter -d 192.168.1.1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that iptables always provides per-rule counters.&lt;br /&gt;
&lt;br /&gt;
= Replacing rules =&lt;br /&gt;
&lt;br /&gt;
You can replace any rule via the &#039;&#039;replace&#039;&#039; command by indicating the rule handle. Therefore, first you have to list the ruleset with option &#039;&#039;-a&#039;&#039; to obtain the rule handle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft list ruleset -a&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                ip protocol tcp counter packets 0 bytes 0 # handle 2&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, assuming you want to replace rule with handle number 2, you have to specify this handle number and the new rule that you want to place instead of it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft replace rule filter input handle 2 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, when listing back the ruleset:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft list ruleset -a&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                counter packets 0 bytes 0 &lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can effective note that the rule has been replaced by a simple rule that counts any packets, instead of counting TCP packets as the previous rule was doing.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=526</id>
		<title>Stateful objects</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=526"/>
		<updated>2020-07-21T13:34:22Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Listing stateful objects */ add more quota examples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Linux Kernel 4.10 and nft v0.8 nftables supports stateful objects.&lt;br /&gt;
&lt;br /&gt;
Stateful objects group stateful information of rules, the supported types are: &#039;&#039;&#039;counters&#039;&#039;&#039; and &#039;&#039;&#039;quotas&#039;&#039;&#039;. Stateful objects are attached to tables and have a unique name, defined by the user.&lt;br /&gt;
&lt;br /&gt;
= Creating stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can create a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; with the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table filter&lt;br /&gt;
% nft add counter filter https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a table named &#039;&#039;filter&#039;&#039;, then a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; named &#039;&#039;https-traffic&#039;&#039; and attaches it to the &#039;&#039;filter&#039;&#039; table.&lt;br /&gt;
&lt;br /&gt;
Creating a &#039;&#039;&#039;quota&#039;&#039;&#039; is similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add quota filter https-quota 25 mbytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A quota named &#039;&#039;https-quota&#039;&#039; is attached to the table &#039;&#039;filter&#039;&#039;, notice that you must specify the quota&#039;s size on creation.&lt;br /&gt;
&lt;br /&gt;
= Referencing stateful objects in rules =&lt;br /&gt;
&lt;br /&gt;
Stateful objects are referenced in rules by their names. They act as both actions and in the case of quotas also matches the simplest way is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain filter output { type filter hook output priority 0 \; }&lt;br /&gt;
% nft add rule filter output tcp dport https counter name https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a chain named &#039;&#039;output&#039;&#039; in the table &#039;&#039;filter&#039;&#039;, then a rule to counter the &#039;&#039;https&#039;&#039; packets generated by your machine and display them in the counter &#039;&#039;https-traffic&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
They can also be used with maps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output counter name tcp dport map { \&lt;br /&gt;
          https : &amp;quot;https-traffic&amp;quot;, \&lt;br /&gt;
          80 : &amp;quot;http-traffic&amp;quot;, \&lt;br /&gt;
          25 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          50 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          107 : &amp;quot;foo-counter&amp;quot; \&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, dynamic maps can be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter ports { type inet_service : quota \; }&lt;br /&gt;
% nft add rule filter output quota name tcp dport map @ports&lt;br /&gt;
% nft add quota filter http-quota over 25 mbytes&lt;br /&gt;
% nft add quota filter ssh-quota 10 kbytes&lt;br /&gt;
% nft add element filter ports { 80 : &amp;quot;http-quota&amp;quot; }&lt;br /&gt;
% nft add element filter ports { 22 : &amp;quot;ssh-quota&amp;quot; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When using quotas, the packet will be counted towards the quota, and if the quota matches (either up-to or over depending on quota type) the remaining actions will take place, otherwise not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
table inet foo {&lt;br /&gt;
   quota example { over 100 mbytes used 0 bytes }&lt;br /&gt;
&lt;br /&gt;
   chain dropafterquota { &lt;br /&gt;
      type filter hook postrouting priority 0; policy accept;&lt;br /&gt;
      udp port 5060 quota name &amp;quot;example&amp;quot; drop&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Will count all udp port 5060 packets towards the quota and drop all packets once the quota hits its &amp;quot;over 100 mbytes&amp;quot; threshold.&lt;br /&gt;
&lt;br /&gt;
= Listing stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can list the stateful information of objects individually via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counter filter https-traffic&lt;br /&gt;
table ip filter {&lt;br /&gt;
	counter https-traffic {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
% nft list quota ip filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s possible to list all stateful objects of the same type. Example with quotas:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list quotas&lt;br /&gt;
table inet filter {&lt;br /&gt;
	quota other-inet-quota {&lt;br /&gt;
		200 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		30 mbytes&lt;br /&gt;
	}&lt;br /&gt;
	quota http-quota {&lt;br /&gt;
		25 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example with counters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counters&lt;br /&gt;
table inet filter {&lt;br /&gt;
	counter mycounter {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
	counter mycounter2 {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
table ip filter {&lt;br /&gt;
	counter https-traffic {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And list all stateful objects of a type in a given table. Example with counters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counters table inet filter&lt;br /&gt;
table inet filter {&lt;br /&gt;
	counter mycounter {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
	counter mycounter2 {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example with quotas:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list quotas table ip filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		30 mbytes&lt;br /&gt;
	}&lt;br /&gt;
	quota http-quota {&lt;br /&gt;
		25 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resetting stateful objects =&lt;br /&gt;
&lt;br /&gt;
Resetting an object will atomically dump and reset its content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes used 217 kbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
% nft list quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other usages are similar to the command list, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset counters&lt;br /&gt;
% nft reset quotas table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At the moment (Jan 2019) resetting quotas does not reset anonymous quotas such as used in rules without names, see [https://bugzilla.netfilter.org/show_bug.cgi?id=1314 bug #1314]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=525</id>
		<title>Stateful objects</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=525"/>
		<updated>2020-07-21T13:30:34Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Listing stateful objects */ extend examples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Linux Kernel 4.10 and nft v0.8 nftables supports stateful objects.&lt;br /&gt;
&lt;br /&gt;
Stateful objects group stateful information of rules, the supported types are: &#039;&#039;&#039;counters&#039;&#039;&#039; and &#039;&#039;&#039;quotas&#039;&#039;&#039;. Stateful objects are attached to tables and have a unique name, defined by the user.&lt;br /&gt;
&lt;br /&gt;
= Creating stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can create a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; with the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table filter&lt;br /&gt;
% nft add counter filter https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a table named &#039;&#039;filter&#039;&#039;, then a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; named &#039;&#039;https-traffic&#039;&#039; and attaches it to the &#039;&#039;filter&#039;&#039; table.&lt;br /&gt;
&lt;br /&gt;
Creating a &#039;&#039;&#039;quota&#039;&#039;&#039; is similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add quota filter https-quota 25 mbytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A quota named &#039;&#039;https-quota&#039;&#039; is attached to the table &#039;&#039;filter&#039;&#039;, notice that you must specify the quota&#039;s size on creation.&lt;br /&gt;
&lt;br /&gt;
= Referencing stateful objects in rules =&lt;br /&gt;
&lt;br /&gt;
Stateful objects are referenced in rules by their names. They act as both actions and in the case of quotas also matches the simplest way is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain filter output { type filter hook output priority 0 \; }&lt;br /&gt;
% nft add rule filter output tcp dport https counter name https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a chain named &#039;&#039;output&#039;&#039; in the table &#039;&#039;filter&#039;&#039;, then a rule to counter the &#039;&#039;https&#039;&#039; packets generated by your machine and display them in the counter &#039;&#039;https-traffic&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
They can also be used with maps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output counter name tcp dport map { \&lt;br /&gt;
          https : &amp;quot;https-traffic&amp;quot;, \&lt;br /&gt;
          80 : &amp;quot;http-traffic&amp;quot;, \&lt;br /&gt;
          25 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          50 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          107 : &amp;quot;foo-counter&amp;quot; \&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, dynamic maps can be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter ports { type inet_service : quota \; }&lt;br /&gt;
% nft add rule filter output quota name tcp dport map @ports&lt;br /&gt;
% nft add quota filter http-quota over 25 mbytes&lt;br /&gt;
% nft add quota filter ssh-quota 10 kbytes&lt;br /&gt;
% nft add element filter ports { 80 : &amp;quot;http-quota&amp;quot; }&lt;br /&gt;
% nft add element filter ports { 22 : &amp;quot;ssh-quota&amp;quot; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When using quotas, the packet will be counted towards the quota, and if the quota matches (either up-to or over depending on quota type) the remaining actions will take place, otherwise not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
table inet foo {&lt;br /&gt;
   quota example { over 100 mbytes used 0 bytes }&lt;br /&gt;
&lt;br /&gt;
   chain dropafterquota { &lt;br /&gt;
      type filter hook postrouting priority 0; policy accept;&lt;br /&gt;
      udp port 5060 quota name &amp;quot;example&amp;quot; drop&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Will count all udp port 5060 packets towards the quota and drop all packets once the quota hits its &amp;quot;over 100 mbytes&amp;quot; threshold.&lt;br /&gt;
&lt;br /&gt;
= Listing stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can list the stateful information of objects individually via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counter filter https-traffic&lt;br /&gt;
table ip filter {&lt;br /&gt;
	counter https-traffic {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s possible to list all stateful objects of the same type. Example with quotas:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list quotas&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example with counters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counters&lt;br /&gt;
table inet filter {&lt;br /&gt;
	counter mycounter {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
	counter mycounter2 {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
table ip filter {&lt;br /&gt;
	counter https-traffic {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And list all stateful objects of a type in a given table. Example with counters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counters table inet filter&lt;br /&gt;
table inet filter {&lt;br /&gt;
	counter mycounter {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
	counter mycounter2 {&lt;br /&gt;
		packets 0 bytes 0&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resetting stateful objects =&lt;br /&gt;
&lt;br /&gt;
Resetting an object will atomically dump and reset its content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes used 217 kbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
% nft list quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other usages are similar to the command list, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset counters&lt;br /&gt;
% nft reset quotas table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At the moment (Jan 2019) resetting quotas does not reset anonymous quotas such as used in rules without names, see [https://bugzilla.netfilter.org/show_bug.cgi?id=1314 bug #1314]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=524</id>
		<title>Stateful objects</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=524"/>
		<updated>2020-07-21T13:23:02Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Creating stateful objects */ be more precise&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Linux Kernel 4.10 and nft v0.8 nftables supports stateful objects.&lt;br /&gt;
&lt;br /&gt;
Stateful objects group stateful information of rules, the supported types are: &#039;&#039;&#039;counters&#039;&#039;&#039; and &#039;&#039;&#039;quotas&#039;&#039;&#039;. Stateful objects are attached to tables and have a unique name, defined by the user.&lt;br /&gt;
&lt;br /&gt;
= Creating stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can create a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; with the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table filter&lt;br /&gt;
% nft add counter filter https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a table named &#039;&#039;filter&#039;&#039;, then a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; named &#039;&#039;https-traffic&#039;&#039; and attaches it to the &#039;&#039;filter&#039;&#039; table.&lt;br /&gt;
&lt;br /&gt;
Creating a &#039;&#039;&#039;quota&#039;&#039;&#039; is similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add quota filter https-quota 25 mbytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A quota named &#039;&#039;https-quota&#039;&#039; is attached to the table &#039;&#039;filter&#039;&#039;, notice that you must specify the quota&#039;s size on creation.&lt;br /&gt;
&lt;br /&gt;
= Referencing stateful objects in rules =&lt;br /&gt;
&lt;br /&gt;
Stateful objects are referenced in rules by their names. They act as both actions and in the case of quotas also matches the simplest way is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain filter output { type filter hook output priority 0 \; }&lt;br /&gt;
% nft add rule filter output tcp dport https counter name https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a chain named &#039;&#039;output&#039;&#039; in the table &#039;&#039;filter&#039;&#039;, then a rule to counter the &#039;&#039;https&#039;&#039; packets generated by your machine and display them in the counter &#039;&#039;https-traffic&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
They can also be used with maps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output counter name tcp dport map { \&lt;br /&gt;
          https : &amp;quot;https-traffic&amp;quot;, \&lt;br /&gt;
          80 : &amp;quot;http-traffic&amp;quot;, \&lt;br /&gt;
          25 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          50 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          107 : &amp;quot;foo-counter&amp;quot; \&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, dynamic maps can be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter ports { type inet_service : quota \; }&lt;br /&gt;
% nft add rule filter output quota name tcp dport map @ports&lt;br /&gt;
% nft add quota filter http-quota over 25 mbytes&lt;br /&gt;
% nft add quota filter ssh-quota 10 kbytes&lt;br /&gt;
% nft add element filter ports { 80 : &amp;quot;http-quota&amp;quot; }&lt;br /&gt;
% nft add element filter ports { 22 : &amp;quot;ssh-quota&amp;quot; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When using quotas, the packet will be counted towards the quota, and if the quota matches (either up-to or over depending on quota type) the remaining actions will take place, otherwise not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
table inet foo {&lt;br /&gt;
   quota example { over 100 mbytes used 0 bytes }&lt;br /&gt;
&lt;br /&gt;
   chain dropafterquota { &lt;br /&gt;
      type filter hook postrouting priority 0; policy accept;&lt;br /&gt;
      udp port 5060 quota name &amp;quot;example&amp;quot; drop&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Will count all udp port 5060 packets towards the quota and drop all packets once the quota hits its &amp;quot;over 100 mbytes&amp;quot; threshold.&lt;br /&gt;
&lt;br /&gt;
= Listing stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can list the stateful information of objects individually via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counter filter https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s possible to list all stateful objects of the same type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list quotas&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And list all stateful objects of a type in a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counters table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resetting stateful objects =&lt;br /&gt;
&lt;br /&gt;
Resetting an object will atomically dump and reset its content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes used 217 kbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
% nft list quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other usages are similar to the command list, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset counters&lt;br /&gt;
% nft reset quotas table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At the moment (Jan 2019) resetting quotas does not reset anonymous quotas such as used in rules without names, see [https://bugzilla.netfilter.org/show_bug.cgi?id=1314 bug #1314]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=523</id>
		<title>Stateful objects</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=523"/>
		<updated>2020-07-21T13:22:34Z</updated>

		<summary type="html">&lt;p&gt;Arturo: more bolding&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Linux Kernel 4.10 and nft v0.8 nftables supports stateful objects.&lt;br /&gt;
&lt;br /&gt;
Stateful objects group stateful information of rules, the supported types are: &#039;&#039;&#039;counters&#039;&#039;&#039; and &#039;&#039;&#039;quotas&#039;&#039;&#039;. Stateful objects are attached to tables and have a unique name, defined by the user.&lt;br /&gt;
&lt;br /&gt;
= Creating stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can create a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; with the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table filter&lt;br /&gt;
% nft add counter filter https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a table named &#039;&#039;filter&#039;&#039;, then a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; named &#039;&#039;https-traffic&#039;&#039; and attaches it to &#039;&#039;filter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Creating a &#039;&#039;&#039;quota&#039;&#039;&#039; is similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add quota filter https-quota 25 mbytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A quota named &#039;&#039;https-quota&#039;&#039; is attached to the table &#039;&#039;filter&#039;&#039;, notice that you must specify the quota&#039;s size on creation.&lt;br /&gt;
&lt;br /&gt;
= Referencing stateful objects in rules =&lt;br /&gt;
&lt;br /&gt;
Stateful objects are referenced in rules by their names. They act as both actions and in the case of quotas also matches the simplest way is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain filter output { type filter hook output priority 0 \; }&lt;br /&gt;
% nft add rule filter output tcp dport https counter name https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a chain named &#039;&#039;output&#039;&#039; in the table &#039;&#039;filter&#039;&#039;, then a rule to counter the &#039;&#039;https&#039;&#039; packets generated by your machine and display them in the counter &#039;&#039;https-traffic&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
They can also be used with maps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output counter name tcp dport map { \&lt;br /&gt;
          https : &amp;quot;https-traffic&amp;quot;, \&lt;br /&gt;
          80 : &amp;quot;http-traffic&amp;quot;, \&lt;br /&gt;
          25 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          50 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          107 : &amp;quot;foo-counter&amp;quot; \&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, dynamic maps can be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter ports { type inet_service : quota \; }&lt;br /&gt;
% nft add rule filter output quota name tcp dport map @ports&lt;br /&gt;
% nft add quota filter http-quota over 25 mbytes&lt;br /&gt;
% nft add quota filter ssh-quota 10 kbytes&lt;br /&gt;
% nft add element filter ports { 80 : &amp;quot;http-quota&amp;quot; }&lt;br /&gt;
% nft add element filter ports { 22 : &amp;quot;ssh-quota&amp;quot; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When using quotas, the packet will be counted towards the quota, and if the quota matches (either up-to or over depending on quota type) the remaining actions will take place, otherwise not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
table inet foo {&lt;br /&gt;
   quota example { over 100 mbytes used 0 bytes }&lt;br /&gt;
&lt;br /&gt;
   chain dropafterquota { &lt;br /&gt;
      type filter hook postrouting priority 0; policy accept;&lt;br /&gt;
      udp port 5060 quota name &amp;quot;example&amp;quot; drop&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Will count all udp port 5060 packets towards the quota and drop all packets once the quota hits its &amp;quot;over 100 mbytes&amp;quot; threshold.&lt;br /&gt;
&lt;br /&gt;
= Listing stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can list the stateful information of objects individually via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counter filter https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s possible to list all stateful objects of the same type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list quotas&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And list all stateful objects of a type in a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counters table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resetting stateful objects =&lt;br /&gt;
&lt;br /&gt;
Resetting an object will atomically dump and reset its content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes used 217 kbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
% nft list quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other usages are similar to the command list, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset counters&lt;br /&gt;
% nft reset quotas table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At the moment (Jan 2019) resetting quotas does not reset anonymous quotas such as used in rules without names, see [https://bugzilla.netfilter.org/show_bug.cgi?id=1314 bug #1314]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Counters&amp;diff=522</id>
		<title>Counters</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Counters&amp;diff=522"/>
		<updated>2020-07-21T13:21:55Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add pointer to stateful counters&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Counters are optional in &#039;&#039;nftables&#039;&#039;, thus, you need to explicitly specify them in the rule if you want them.&lt;br /&gt;
&lt;br /&gt;
The following example allows you to account all tcp traffic that you machine receives:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input ip protocol tcp counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An interesting feature of the counter action is that its position in the rule syntax matters. This rule is &#039;&#039;&#039;not&#039;&#039;&#039; equivalent to the previous rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input counter ip protocol tcp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The rule is evaluated from the left to the right, so &#039;&#039;&#039;any kind of packet&#039;&#039;&#039; will update the counters, not only TCP packets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Stateful counters ==&lt;br /&gt;
&lt;br /&gt;
nftables has native support for &#039;&#039;&#039;stateful counters&#039;&#039;&#039;, i.e, counters not attached to a particular rule. Check the [[Stateful_objects | stateful objects]] page for more details.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=521</id>
		<title>Stateful objects</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Stateful_objects&amp;diff=521"/>
		<updated>2020-07-21T13:20:23Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Creating stateful objects */ add some bolding&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Linux Kernel 4.10 and nft v0.8 nftables supports stateful objects.&lt;br /&gt;
&lt;br /&gt;
Stateful objects group stateful information of rules, the supported types are: counters and quotas. Stateful objects are attached to tables and have a unique name, defined by the user.&lt;br /&gt;
&lt;br /&gt;
= Creating stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can create a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; with the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table filter&lt;br /&gt;
% nft add counter filter https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a table named &#039;&#039;filter&#039;&#039;, then a &#039;&#039;&#039;stateful counter&#039;&#039;&#039; named &#039;&#039;https-traffic&#039;&#039; and attaches it to &#039;&#039;filter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Creating a &#039;&#039;&#039;quota&#039;&#039;&#039; is similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add quota filter https-quota 25 mbytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A quota named &#039;&#039;https-quota&#039;&#039; is attached to the table &#039;&#039;filter&#039;&#039;, notice that you must specify the quota&#039;s size on creation.&lt;br /&gt;
&lt;br /&gt;
= Referencing stateful objects in rules =&lt;br /&gt;
&lt;br /&gt;
Stateful objects are referenced in rules by their names. They act as both actions and in the case of quotas also matches the simplest way is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain filter output { type filter hook output priority 0 \; }&lt;br /&gt;
% nft add rule filter output tcp dport https counter name https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These rules create a chain named &#039;&#039;output&#039;&#039; in the table &#039;&#039;filter&#039;&#039;, then a rule to counter the &#039;&#039;https&#039;&#039; packets generated by your machine and display them in the counter &#039;&#039;https-traffic&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
They can also be used with maps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output counter name tcp dport map { \&lt;br /&gt;
          https : &amp;quot;https-traffic&amp;quot;, \&lt;br /&gt;
          80 : &amp;quot;http-traffic&amp;quot;, \&lt;br /&gt;
          25 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          50 : &amp;quot;foo-counter&amp;quot;, \&lt;br /&gt;
          107 : &amp;quot;foo-counter&amp;quot; \&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, dynamic maps can be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter ports { type inet_service : quota \; }&lt;br /&gt;
% nft add rule filter output quota name tcp dport map @ports&lt;br /&gt;
% nft add quota filter http-quota over 25 mbytes&lt;br /&gt;
% nft add quota filter ssh-quota 10 kbytes&lt;br /&gt;
% nft add element filter ports { 80 : &amp;quot;http-quota&amp;quot; }&lt;br /&gt;
% nft add element filter ports { 22 : &amp;quot;ssh-quota&amp;quot; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When using quotas, the packet will be counted towards the quota, and if the quota matches (either up-to or over depending on quota type) the remaining actions will take place, otherwise not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
table inet foo {&lt;br /&gt;
   quota example { over 100 mbytes used 0 bytes }&lt;br /&gt;
&lt;br /&gt;
   chain dropafterquota { &lt;br /&gt;
      type filter hook postrouting priority 0; policy accept;&lt;br /&gt;
      udp port 5060 quota name &amp;quot;example&amp;quot; drop&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Will count all udp port 5060 packets towards the quota and drop all packets once the quota hits its &amp;quot;over 100 mbytes&amp;quot; threshold.&lt;br /&gt;
&lt;br /&gt;
= Listing stateful objects =&lt;br /&gt;
&lt;br /&gt;
You can list the stateful information of objects individually via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counter filter https-traffic&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s possible to list all stateful objects of the same type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list quotas&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And list all stateful objects of a type in a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list counters table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resetting stateful objects =&lt;br /&gt;
&lt;br /&gt;
Resetting an object will atomically dump and reset its content:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes used 217 kbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
% nft list quota filter https-quota&lt;br /&gt;
table ip filter {&lt;br /&gt;
	quota https-quota {&lt;br /&gt;
		25 mbytes&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other usages are similar to the command list, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft reset counters&lt;br /&gt;
% nft reset quotas table filter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At the moment (Jan 2019) resetting quotas does not reset anonymous quotas such as used in rules without names, see [https://bugzilla.netfilter.org/show_bug.cgi?id=1314 bug #1314]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Building_and_installing_nftables_from_sources&amp;diff=501</id>
		<title>Building and installing nftables from sources</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Building_and_installing_nftables_from_sources&amp;diff=501"/>
		<updated>2020-04-14T11:15:13Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Validating your installation */ there is no longer a dmesg message now&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;nftables requires several userspace libraries, the &#039;nft&#039; userspace command line utility and the kernel modules.&lt;br /&gt;
&lt;br /&gt;
If you are using a major linux distribution, you may consider using [[nftables from distributions]].&lt;br /&gt;
&lt;br /&gt;
= Installing userspace libraries =&lt;br /&gt;
&lt;br /&gt;
You have to install the following userspace libraries:&lt;br /&gt;
&lt;br /&gt;
* [http://www.netfilter.org/projects/libmnl libmnl ], this library provides the interfaces to communicate kernel and userspace via Netlink. &#039;&#039;It is very likely that your distribution already provides a package for libmnl that you can use&#039;&#039;. If you decide to use your distributor package, make sure you install the development package as well.&lt;br /&gt;
&lt;br /&gt;
* [http://www.netfilter.org/projects/libnftnl libnftnl], this library provides the low-level API to transform netlink messages to objects.&lt;br /&gt;
&lt;br /&gt;
You also need &#039;&#039;libgmp&#039;&#039; and &#039;&#039;libreadline&#039;&#039;, most distributions already provide packages for these two libraries, so make sure you install the development extensions of this packages to successfully compile &#039;&#039;nftables&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
If you plan to give a test to &#039;&#039;nftables&#039;&#039;, we recommend you to use git snapshots for &#039;&#039;libnftnl&#039;&#039; and &#039;&#039;nft&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Installing userspace libraries from git ==&lt;br /&gt;
&lt;br /&gt;
To install &#039;&#039;libnftnl&#039;&#039;, to can type these magic spells:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ git clone git://git.netfilter.org/libnftnl&lt;br /&gt;
$ cd libnftnl&lt;br /&gt;
$ sh autogen.sh&lt;br /&gt;
$ ./configure&lt;br /&gt;
$ make&lt;br /&gt;
$ sudo make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
If you are working behind proxy than it might possible that you are not able to clone using git protocol so try to clone using &amp;quot;http/https:&amp;quot; instead &amp;quot;git:&amp;quot;&lt;br /&gt;
&amp;lt;br &amp;gt; Reasons:- 1) The git protocol, by default, uses the port 9418. It might possible that your traffic is blocked on that port.&lt;br /&gt;
&amp;lt;br &amp;gt; 2) Also take help and can relate from the [http://stackoverflow.com/a/28494985 solution] &lt;br /&gt;
&lt;br /&gt;
If you have any compilation problem, please report them to the [https://www.netfilter.org/mailinglists.html netfilter developer mailing list] providing as much detailed information as possible.&lt;br /&gt;
&lt;br /&gt;
== Installing userspace libraries from snapshots ==&lt;br /&gt;
&lt;br /&gt;
You can retrieve daily snapshots of this library from the [ftp://ftp.netfilter.org/pub/libnftnl/snapshot/ Netfilter FTP]. Then, to install it you have to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ wget ftp://ftp.netfilter.org/pub/libnftnl/snapshot/libnftnl-20140217.tar.bz2&lt;br /&gt;
$ tar xvjf libnftnl-20140217.tar.bz2&lt;br /&gt;
$ ./configure&lt;br /&gt;
$ make&lt;br /&gt;
$ sudo make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Installing userspace nft command line utility =&lt;br /&gt;
&lt;br /&gt;
This is the command line utility that provides a user interface to configure &#039;&#039;nftables&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Installing from git ==&lt;br /&gt;
&lt;br /&gt;
Just type these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% git clone git://git.netfilter.org/nftables&lt;br /&gt;
% cd nftables&lt;br /&gt;
% sh autogen.sh&lt;br /&gt;
% ./configure&lt;br /&gt;
% make&lt;br /&gt;
% make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should check that &#039;&#039;nft&#039;&#039; is installed in your system by typing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft&lt;br /&gt;
nft: no command specified&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That means &#039;&#039;nft&#039;&#039; has been correctly installed.&lt;br /&gt;
&lt;br /&gt;
= Installing Linux kernel with nftables support =&lt;br /&gt;
&lt;br /&gt;
Prerequisites: nftables is available in Linux kernels since version 3.13 but this is software under development, so we encourage you to run the latest stable kernel.&lt;br /&gt;
&lt;br /&gt;
== Validating your installation ==&lt;br /&gt;
&lt;br /&gt;
You can validate that your installation is working by checking if you can install the &#039;nf_tables&#039; kernel module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% modprobe nf_tables&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can check that&#039;s actually there via &#039;&#039;lsmod&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# lsmod | grep nf_tables&lt;br /&gt;
nf_tables              42349  0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure you also have loaded the family support, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% modprobe nf_tables_ipv4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;lsmod&#039;&#039; command should show something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# lsmod | grep nf_tables&lt;br /&gt;
nf_tables_ipv4         12869  0 &lt;br /&gt;
nf_tables              42349  1 nf_tables_ipv4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other family modules are &#039;&#039;nf_tables_ipv6&#039;&#039;, &#039;&#039;nf_tables_bridge&#039;&#039;, &#039;&#039;nf_tables_arp&#039;&#039; and (since Linux kernel &amp;gt;= 3.14) &#039;&#039;nf_tables_inet&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
These modules provide the corresponding [[Configuring_tables|table]] and the filter [[Configuring_chains|chain]] support for the given family.&lt;br /&gt;
&lt;br /&gt;
You could also check which modules are supported by your current kernel. How to to do this, depends on your distro:&lt;br /&gt;
* on debian, look in /boot/config-XXX-YYY, where XXX is your kernel package version, and YYY is your arch, e.g. /boot/config-4.2.0-1-amd64&lt;br /&gt;
* on Arch, look in /proc/config.gz. As this is compressed, use a command such as zcat or zgrep.&lt;br /&gt;
&lt;br /&gt;
In the debian example below, CONFIG_NFT_REDIR_IPV4 and CONFIG_NFT_REDIR_IPV6 are not set, so you can&#039;t use [http://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT)#Redirect redirect] in the ruleset:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% grep CONFIG_NFT_ /boot/config-4.2.0-1-amd64&lt;br /&gt;
CONFIG_NFT_EXTHDR=m&lt;br /&gt;
CONFIG_NFT_META=m&lt;br /&gt;
CONFIG_NFT_CT=m&lt;br /&gt;
CONFIG_NFT_RBTREE=m&lt;br /&gt;
CONFIG_NFT_HASH=m&lt;br /&gt;
CONFIG_NFT_COUNTER=m&lt;br /&gt;
CONFIG_NFT_LOG=m&lt;br /&gt;
CONFIG_NFT_LIMIT=m&lt;br /&gt;
CONFIG_NFT_MASQ=m&lt;br /&gt;
CONFIG_NFT_REDIR=m&lt;br /&gt;
CONFIG_NFT_NAT=m&lt;br /&gt;
CONFIG_NFT_QUEUE=m&lt;br /&gt;
CONFIG_NFT_REJECT=m&lt;br /&gt;
CONFIG_NFT_REJECT_INET=m&lt;br /&gt;
CONFIG_NFT_COMPAT=m&lt;br /&gt;
CONFIG_NFT_CHAIN_ROUTE_IPV4=m&lt;br /&gt;
CONFIG_NFT_REJECT_IPV4=m&lt;br /&gt;
CONFIG_NFT_CHAIN_NAT_IPV4=m&lt;br /&gt;
CONFIG_NFT_MASQ_IPV4=m&lt;br /&gt;
# CONFIG_NFT_REDIR_IPV4 is not set&lt;br /&gt;
CONFIG_NFT_CHAIN_ROUTE_IPV6=m&lt;br /&gt;
CONFIG_NFT_REJECT_IPV6=m&lt;br /&gt;
CONFIG_NFT_CHAIN_NAT_IPV6=m&lt;br /&gt;
CONFIG_NFT_MASQ_IPV6=m&lt;br /&gt;
# CONFIG_NFT_REDIR_IPV6 is not set&lt;br /&gt;
CONFIG_NFT_BRIDGE_META=m&lt;br /&gt;
CONFIG_NFT_BRIDGE_REJECT=m&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Installing from git ==&lt;br /&gt;
&lt;br /&gt;
This is slower as you will retrieve the Linux kernel git tree for nftables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nftables.git&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After retrieving the git tree, you have to follow the same steps that described in the installation from sources.&lt;br /&gt;
&lt;br /&gt;
But you will get the most recent changes for the &#039;&#039;nftables&#039;&#039; kernel code there.&lt;br /&gt;
&lt;br /&gt;
When configuring the kernel, be sure to enable all the nftables modules (choose &#039;m&#039; or &#039;y&#039;). This is an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ make oldconfig&lt;br /&gt;
&lt;br /&gt;
Netfilter Xtables support (required for ip_tables) (NETFILTER_XTABLES) [M/y/?] m&lt;br /&gt;
Netfilter nf_tables support (NF_TABLES) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables payload module (NFT_PAYLOAD) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables IPv6 exthdr module (NFT_EXTHDR) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables meta module (NFT_META) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables conntrack module (NFT_CT) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables rbtree set module (NFT_RBTREE) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables hash set module (NFT_HASH) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables counter module (NFT_COUNTER) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables log module (NFT_LOG) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables limit module (NFT_LIMIT) [N/m] (NEW) m&lt;br /&gt;
  Netfilter nf_tables nat module (NFT_NAT) [N/m] (NEW) m&lt;br /&gt;
  Netfilter x_tables over nf_tables module (NFT_COMPAT) [N/m/?] (NEW) m&lt;br /&gt;
&lt;br /&gt;
IPv4 nf_tables support (NF_TABLES_IPV4) [N/m] (NEW) m&lt;br /&gt;
  nf_tables IPv4 reject support (NFT_REJECT_IPV4) [N/m] (NEW) m&lt;br /&gt;
  IPv4 nf_tables route chain support (NFT_CHAIN_ROUTE_IPV4) [N/m] (NEW) m&lt;br /&gt;
  IPv4 nf_tables nat chain support (NFT_CHAIN_NAT_IPV4) [N/m] (NEW) m&lt;br /&gt;
&lt;br /&gt;
IPv6 nf_tables support (NF_TABLES_IPV6) [M/n] m&lt;br /&gt;
  IPv6 nf_tables route chain support (NFT_CHAIN_ROUTE_IPV6) [M/n] m&lt;br /&gt;
  IPv6 nf_tables nat chain support (NFT_CHAIN_NAT_IPV6) [M/n] m&lt;br /&gt;
&lt;br /&gt;
Ethernet Bridge nf_tables support (NF_TABLES_BRIDGE) [N/m/y] (NEW) m&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Nftables_families&amp;diff=488</id>
		<title>Nftables families</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Nftables_families&amp;diff=488"/>
		<updated>2019-12-18T09:30:37Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* netdev */ reword&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;nftables &#039;&#039;&#039;families&#039;&#039;&#039; are a new concept introduced with this technology which was previously missing in the iptables world.&lt;br /&gt;
You may already know that the nftables framework is designed to work with all typical address families (IPv4, IPv6, ARP).&lt;br /&gt;
In the past, all the families were handled by different tools: iptables, ip6tables, arptables, ebtables.&lt;br /&gt;
&lt;br /&gt;
Please note that what traffic/packets you see and at which point in the network stack depends on the &#039;&#039;&#039;chain hook&#039;&#039;&#039; you are using.&lt;br /&gt;
You can create tables/chains/sets/rules in any family with the &#039;&#039;&#039;nft&#039;&#039;&#039; command line interface, out of the box, no need for different tools.&lt;br /&gt;
Additional families may be added in the future for extended nftables functionalities.&lt;br /&gt;
&lt;br /&gt;
== ip ==&lt;br /&gt;
&lt;br /&gt;
Tables of this family will see IPv4 traffic/packets.&lt;br /&gt;
The iptables tool was the equivalent in the old x_tables world.&lt;br /&gt;
&lt;br /&gt;
== ip6 ==&lt;br /&gt;
&lt;br /&gt;
Tables of this family will see IPv6 traffic/packets.&lt;br /&gt;
The ip6tables tool was the equivalent in the old x_tables world.&lt;br /&gt;
&lt;br /&gt;
== inet ==&lt;br /&gt;
&lt;br /&gt;
Tables of this family will see both IPv4/IPv6 traffic/packets, designed to improve dual stack support.&lt;br /&gt;
Mixing iptables and ip6tables rules in the same box was the equivalent in the old x_tables world.&lt;br /&gt;
&lt;br /&gt;
Both IPv4/IPv6 packets will traverse the same rules. Rules for IPv4 packets won&#039;t affect IPv6 packets.&lt;br /&gt;
Rules for both L3 protocol will affect both.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# this rule only affects IPv4 packets&lt;br /&gt;
add rule inet filter input ip saddr 1.1.1.1 counter accept &lt;br /&gt;
# this rule only affects IPv6 packets&lt;br /&gt;
add rule inet filter input ip6 daddr fe00::2 counter accept&lt;br /&gt;
# these rules affects both IPv4/IPv6 packets&lt;br /&gt;
add rule inet filter input ct state established,related counter accept&lt;br /&gt;
add rule inet filter input udp dport 53 accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== arp ==&lt;br /&gt;
&lt;br /&gt;
Tables of this family will see ARP-level (i.e, L2) traffic, before any L3 handling is done by the kernel.&lt;br /&gt;
The arptables tool was the equivalent in the old x_tables world.&lt;br /&gt;
&lt;br /&gt;
== bridge ==&lt;br /&gt;
&lt;br /&gt;
Tables of this family will see traffic/packets traversing bridges (i.e. switching). No assumptions are made about L3 protocols.&lt;br /&gt;
The ebtables tool was the equivalent in the old x_tables world.&lt;br /&gt;
Also, some old x_tables modules such as &#039;&#039;physdev&#039;&#039; will eventually be served natively from this family.&lt;br /&gt;
&lt;br /&gt;
Note that there is no nf_conntrack integration for this family. However this may change in the future.&lt;br /&gt;
&lt;br /&gt;
== netdev ==&lt;br /&gt;
&lt;br /&gt;
This family provides the ingress hook, that allows you to classify packets that the driver has just passed up to the networking stack. This means you see &#039;&#039;&#039;all&#039;&#039;&#039; network traffic for your NIC getting in. No assumptions are made about L2 or L3 protocols, therefore you can filter ARP traffic from here.&lt;br /&gt;
&lt;br /&gt;
Note that there is no equivalent in the old iptables world, this is a new feature available since Linux kernel 4.2 for nftables.&lt;br /&gt;
&lt;br /&gt;
This location is ideal to drop packets that result from DDOS attacks given this is very early in the packet path. Dropping packets from here is much more efficient than from the classic prerouting chain, by a factor of 2x.&lt;br /&gt;
&lt;br /&gt;
You can also use this new ingress hook for [[load balancing]], including Direct Server Return (DSR), [https://netdevconf.org/1.2/slides/oct6/08_nftables_Load_Balancing_with_nftables_II_Slides.pdf that has been reported to be 10x faster].&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=487</id>
		<title>Matching packet metainformation</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=487"/>
		<updated>2019-12-17T09:59:16Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* The meta selectors */ mention secpath in ipsec&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The meta selectors allows you to match ([[Setting_packet_metainformation |and in some cases, set]]) packet metainformation.&lt;br /&gt;
&lt;br /&gt;
= The meta selectors =&lt;br /&gt;
&lt;br /&gt;
We have 2 types of meta statement, qualified and unqualified. Qualified ones require you use the &#039;&#039;&#039;meta&#039;&#039;&#039; keyword, and for unqualified ones it can be skipped.&lt;br /&gt;
&lt;br /&gt;
* qualified meta statements:&lt;br /&gt;
** length -- packet lenght&lt;br /&gt;
** protocol -- packet protocol (as in skb-&amp;gt;protocol)&lt;br /&gt;
** nfproto -- netfilter packet protocol family (like ipv4, ipv6, etc..).&lt;br /&gt;
** l4proto -- layer 4 protocol (tcp, udp, etc..)&lt;br /&gt;
** priority -- packet priority, tc handle. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** random -- match against a single/simple random number&lt;br /&gt;
** secmark -- packet secmark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** ibrvproto -- match the bridge protocol&lt;br /&gt;
** ibrpvid -- match the bridge pvid&lt;br /&gt;
&lt;br /&gt;
* unqualified meta statements:&lt;br /&gt;
** mark -- packet mark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** iif -- input interface index&lt;br /&gt;
** iifname -- input interface name&lt;br /&gt;
** iiftype -- input interface type&lt;br /&gt;
** oif -- output interface index&lt;br /&gt;
** oifname -- output interface name&lt;br /&gt;
** oiftype -- output interface type&lt;br /&gt;
** skuid -- socket uid&lt;br /&gt;
** skgid -- socket gid&lt;br /&gt;
** nftrace -- [[Ruleset_debug/tracing|nftrace debugging]] bit. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** rtclassid -- realm&lt;br /&gt;
** ibriport -- input bridge port&lt;br /&gt;
** obriport -- output bridge port&lt;br /&gt;
** ibridgename -- input bridge name&lt;br /&gt;
** obridgename -- output bridge name&lt;br /&gt;
** pkttype -- packet type. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** cpu -- cpu number&lt;br /&gt;
** iifgroup -- input interface group&lt;br /&gt;
** oifgroup -- output interface group&lt;br /&gt;
** cgroup -- cgroup number&lt;br /&gt;
** ipsec -- ipsec (secpath) packet or not&lt;br /&gt;
** time -- packet timestamp&lt;br /&gt;
** day -- packet timestamp&lt;br /&gt;
** hour -- packet timestamp&lt;br /&gt;
&lt;br /&gt;
= Matching packets by interface name =&lt;br /&gt;
&lt;br /&gt;
You can use one of the following selectors to match the interface name:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;iifname&#039;&#039;, to match the input network interface name.&lt;br /&gt;
* &#039;&#039;oifname&#039;&#039;, to match the output network interface name.&lt;br /&gt;
* &#039;&#039;iif&#039;&#039;, to match the interface index of the network interface name. This is faster than &#039;&#039;iifname&#039;&#039; as it only has to compare a 32-bits unsigned integer instead of a string. The interface index is dynamically allocated, so don&#039;t use this for interfaces that are dynamically created and destroyed, eg. &#039;&#039;ppp0&#039;&#039;.&lt;br /&gt;
* &#039;&#039;oif&#039;&#039;, like &#039;&#039;iif&#039;&#039; but it matches the output network interface index.&lt;br /&gt;
&lt;br /&gt;
An example usage of the interface name is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input meta oifname lo accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule accepts all traffic for the loopback pseudodevice &#039;&#039;lo&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Matching packets by packet mark =&lt;br /&gt;
&lt;br /&gt;
You can match packets whose mark is 123 with the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add rule filter output meta mark 123 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Matching packets the socket UID =&lt;br /&gt;
&lt;br /&gt;
You can use your user name to match traffic, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid pablo counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or the 32-bits unsigned integer (UID) in case there is no entry in /etc/passwd for a given user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid 1000 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s just generate some HTTP traffic to test this rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% wget --spider http://www.google.com&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if you check the counters, you can verify that the packets are matching that rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 skuid pablo counter packets 7 bytes 510&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: Beware if you test this with &#039;&#039;ping&#039;&#039;, it is usually installed with suid so that traffic will match the root user (uid=0).&lt;br /&gt;
&lt;br /&gt;
= Matching packet priority =&lt;br /&gt;
&lt;br /&gt;
* Since nftables v0.7 you can match the packet priority, the tc classid:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority abcd:1234&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Packet without set priority can be matched using meta priority none&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority none&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Setting_packet_metainformation&amp;diff=486</id>
		<title>Setting packet metainformation</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Setting_packet_metainformation&amp;diff=486"/>
		<updated>2019-12-17T09:45:40Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add nftrace wiki link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;You can set some [[Matching_packet_metainformation |metainformation]] in a packet. Current supported options are:&lt;br /&gt;
* mark -- packet mark&lt;br /&gt;
* priority -- packet priority&lt;br /&gt;
* nftrace -- [[Ruleset_debug/tracing|nftrace debugging]] bit&lt;br /&gt;
* pkttype -- packet type&lt;br /&gt;
* secmark -- packet secmark&lt;br /&gt;
&lt;br /&gt;
Please note that you require a Linux kernel &amp;gt;= 3.14 to use these features.&lt;br /&gt;
&lt;br /&gt;
== mark ==&lt;br /&gt;
The following example shows how to set the packet mark:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule route output mark set 123&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== mark and conntrack mark ==&lt;br /&gt;
&lt;br /&gt;
You can save/restore conntrack mark like in iptables.&lt;br /&gt;
&lt;br /&gt;
In this example, the nf_tables engine set the packet mark to 1. &lt;br /&gt;
In the last rule, that mark is store in the conntrack entry associated with the flow:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta mark set 1&lt;br /&gt;
% nft add rule filter forward ct mark set mark&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, the conntrack mark is stored in the packet.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta mark set ct mark&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== priority ==&lt;br /&gt;
You can set the priority of a packet.&lt;br /&gt;
&lt;br /&gt;
This example shows a similar operation to what &amp;quot;-j CLASSIFY&amp;quot; does in iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table mangle&lt;br /&gt;
% nft add chain postrouting {type route hook output priority -150\; }&lt;br /&gt;
% nft add rule mangle postrouting tcp sport 80 meta priority set 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: There is a bug in the priority syntax that will be fixed in following versions of nftables.&lt;br /&gt;
&lt;br /&gt;
== nftrace ==&lt;br /&gt;
&lt;br /&gt;
Setting nftrace in a packet will report the journey through the nf_tables stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter forward udp dport 53 meta nftrace set 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== combination of options ==&lt;br /&gt;
&lt;br /&gt;
Given the flexible design of nftables, remember you can perform several actions to a packet in one rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter forward ip saddr 192.168.1.1 meta nftrace set 1 meta priority set 2 meta mark set 123&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=485</id>
		<title>Matching packet metainformation</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=485"/>
		<updated>2019-12-17T09:45:02Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* The meta selectors */ add wiki link to nftrace&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The meta selectors allows you to match ([[Setting_packet_metainformation |and in some cases, set]]) packet metainformation.&lt;br /&gt;
&lt;br /&gt;
= The meta selectors =&lt;br /&gt;
&lt;br /&gt;
We have 2 types of meta statement, qualified and unqualified. Qualified ones require you use the &#039;&#039;&#039;meta&#039;&#039;&#039; keyword, and for unqualified ones it can be skipped.&lt;br /&gt;
&lt;br /&gt;
* qualified meta statements:&lt;br /&gt;
** length -- packet lenght&lt;br /&gt;
** protocol -- packet protocol (as in skb-&amp;gt;protocol)&lt;br /&gt;
** nfproto -- netfilter packet protocol family (like ipv4, ipv6, etc..).&lt;br /&gt;
** l4proto -- layer 4 protocol (tcp, udp, etc..)&lt;br /&gt;
** priority -- packet priority, tc handle. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** random -- match against a single/simple random number&lt;br /&gt;
** secmark -- packet secmark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** ibrvproto -- match the bridge protocol&lt;br /&gt;
** ibrpvid -- match the bridge pvid&lt;br /&gt;
&lt;br /&gt;
* unqualified meta statements:&lt;br /&gt;
** mark -- packet mark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** iif -- input interface index&lt;br /&gt;
** iifname -- input interface name&lt;br /&gt;
** iiftype -- input interface type&lt;br /&gt;
** oif -- output interface index&lt;br /&gt;
** oifname -- output interface name&lt;br /&gt;
** oiftype -- output interface type&lt;br /&gt;
** skuid -- socket uid&lt;br /&gt;
** skgid -- socket gid&lt;br /&gt;
** nftrace -- [[Ruleset_debug/tracing|nftrace debugging]] bit. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** rtclassid -- realm&lt;br /&gt;
** ibriport -- input bridge port&lt;br /&gt;
** obriport -- output bridge port&lt;br /&gt;
** ibridgename -- input bridge name&lt;br /&gt;
** obridgename -- output bridge name&lt;br /&gt;
** pkttype -- packet type. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** cpu -- cpu number&lt;br /&gt;
** iifgroup -- input interface group&lt;br /&gt;
** oifgroup -- output interface group&lt;br /&gt;
** cgroup -- cgroup number&lt;br /&gt;
** ipsec -- ipsec packet or not&lt;br /&gt;
** time -- packet timestamp&lt;br /&gt;
** day -- packet timestamp&lt;br /&gt;
** hour -- packet timestamp&lt;br /&gt;
&lt;br /&gt;
= Matching packets by interface name =&lt;br /&gt;
&lt;br /&gt;
You can use one of the following selectors to match the interface name:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;iifname&#039;&#039;, to match the input network interface name.&lt;br /&gt;
* &#039;&#039;oifname&#039;&#039;, to match the output network interface name.&lt;br /&gt;
* &#039;&#039;iif&#039;&#039;, to match the interface index of the network interface name. This is faster than &#039;&#039;iifname&#039;&#039; as it only has to compare a 32-bits unsigned integer instead of a string. The interface index is dynamically allocated, so don&#039;t use this for interfaces that are dynamically created and destroyed, eg. &#039;&#039;ppp0&#039;&#039;.&lt;br /&gt;
* &#039;&#039;oif&#039;&#039;, like &#039;&#039;iif&#039;&#039; but it matches the output network interface index.&lt;br /&gt;
&lt;br /&gt;
An example usage of the interface name is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input meta oifname lo accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule accepts all traffic for the loopback pseudodevice &#039;&#039;lo&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Matching packets by packet mark =&lt;br /&gt;
&lt;br /&gt;
You can match packets whose mark is 123 with the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add rule filter output meta mark 123 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Matching packets the socket UID =&lt;br /&gt;
&lt;br /&gt;
You can use your user name to match traffic, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid pablo counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or the 32-bits unsigned integer (UID) in case there is no entry in /etc/passwd for a given user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid 1000 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s just generate some HTTP traffic to test this rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% wget --spider http://www.google.com&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if you check the counters, you can verify that the packets are matching that rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 skuid pablo counter packets 7 bytes 510&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: Beware if you test this with &#039;&#039;ping&#039;&#039;, it is usually installed with suid so that traffic will match the root user (uid=0).&lt;br /&gt;
&lt;br /&gt;
= Matching packet priority =&lt;br /&gt;
&lt;br /&gt;
* Since nftables v0.7 you can match the packet priority, the tc classid:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority abcd:1234&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Packet without set priority can be matched using meta priority none&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority none&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Setting_packet_metainformation&amp;diff=484</id>
		<title>Setting packet metainformation</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Setting_packet_metainformation&amp;diff=484"/>
		<updated>2019-12-17T09:43:57Z</updated>

		<summary type="html">&lt;p&gt;Arturo: refresh introductory paragraph&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;You can set some [[Matching_packet_metainformation |metainformation]] in a packet. Current supported options are:&lt;br /&gt;
* mark -- packet mark&lt;br /&gt;
* priority -- packet priority&lt;br /&gt;
* nftrace -- nftrace debugging bit&lt;br /&gt;
* pkttype -- packet type&lt;br /&gt;
* secmark -- packet secmark&lt;br /&gt;
&lt;br /&gt;
Please note that you require a Linux kernel &amp;gt;= 3.14 to use these features.&lt;br /&gt;
&lt;br /&gt;
== mark ==&lt;br /&gt;
The following example shows how to set the packet mark:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule route output mark set 123&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== mark and conntrack mark ==&lt;br /&gt;
&lt;br /&gt;
You can save/restore conntrack mark like in iptables.&lt;br /&gt;
&lt;br /&gt;
In this example, the nf_tables engine set the packet mark to 1. &lt;br /&gt;
In the last rule, that mark is store in the conntrack entry associated with the flow:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta mark set 1&lt;br /&gt;
% nft add rule filter forward ct mark set mark&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, the conntrack mark is stored in the packet.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta mark set ct mark&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== priority ==&lt;br /&gt;
You can set the priority of a packet.&lt;br /&gt;
&lt;br /&gt;
This example shows a similar operation to what &amp;quot;-j CLASSIFY&amp;quot; does in iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table mangle&lt;br /&gt;
% nft add chain postrouting {type route hook output priority -150\; }&lt;br /&gt;
% nft add rule mangle postrouting tcp sport 80 meta priority set 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: There is a bug in the priority syntax that will be fixed in following versions of nftables.&lt;br /&gt;
&lt;br /&gt;
== nftrace ==&lt;br /&gt;
&lt;br /&gt;
Setting nftrace in a packet will report the journey through the nf_tables stack.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter forward udp dport 53 meta nftrace set 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== combination of options ==&lt;br /&gt;
&lt;br /&gt;
Given the flexible design of nftables, remember you can perform several actions to a packet in one rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter forward ip saddr 192.168.1.1 meta nftrace set 1 meta priority set 2 meta mark set 123&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=483</id>
		<title>Matching packet metainformation</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=483"/>
		<updated>2019-12-17T09:41:19Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add a couple more datatypes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The meta selectors allows you to match ([[Setting_packet_metainformation |and in some cases, set]]) packet metainformation.&lt;br /&gt;
&lt;br /&gt;
= The meta selectors =&lt;br /&gt;
&lt;br /&gt;
We have 2 types of meta statement, qualified and unqualified. Qualified ones require you use the &#039;&#039;&#039;meta&#039;&#039;&#039; keyword, and for unqualified ones it can be skipped.&lt;br /&gt;
&lt;br /&gt;
* qualified meta statements:&lt;br /&gt;
** length -- packet lenght&lt;br /&gt;
** protocol -- packet protocol (as in skb-&amp;gt;protocol)&lt;br /&gt;
** nfproto -- netfilter packet protocol family (like ipv4, ipv6, etc..).&lt;br /&gt;
** l4proto -- layer 4 protocol (tcp, udp, etc..)&lt;br /&gt;
** priority -- packet priority, tc handle. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** random -- match against a single/simple random number&lt;br /&gt;
** secmark -- packet secmark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** ibrvproto -- match the bridge protocol&lt;br /&gt;
** ibrpvid -- match the bridge pvid&lt;br /&gt;
&lt;br /&gt;
* unqualified meta statements:&lt;br /&gt;
** mark -- packet mark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** iif -- input interface index&lt;br /&gt;
** iifname -- input interface name&lt;br /&gt;
** iiftype -- input interface type&lt;br /&gt;
** oif -- output interface index&lt;br /&gt;
** oifname -- output interface name&lt;br /&gt;
** oiftype -- output interface type&lt;br /&gt;
** skuid -- socket uid&lt;br /&gt;
** skgid -- socket gid&lt;br /&gt;
** nftrace -- nftrace debugging bit. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** rtclassid -- realm&lt;br /&gt;
** ibriport -- input bridge port&lt;br /&gt;
** obriport -- output bridge port&lt;br /&gt;
** ibridgename -- input bridge name&lt;br /&gt;
** obridgename -- output bridge name&lt;br /&gt;
** pkttype -- packet type. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** cpu -- cpu number&lt;br /&gt;
** iifgroup -- input interface group&lt;br /&gt;
** oifgroup -- output interface group&lt;br /&gt;
** cgroup -- cgroup number&lt;br /&gt;
** ipsec -- ipsec packet or not&lt;br /&gt;
** time -- packet timestamp&lt;br /&gt;
** day -- packet timestamp&lt;br /&gt;
** hour -- packet timestamp&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Matching packets by interface name =&lt;br /&gt;
&lt;br /&gt;
You can use one of the following selectors to match the interface name:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;iifname&#039;&#039;, to match the input network interface name.&lt;br /&gt;
* &#039;&#039;oifname&#039;&#039;, to match the output network interface name.&lt;br /&gt;
* &#039;&#039;iif&#039;&#039;, to match the interface index of the network interface name. This is faster than &#039;&#039;iifname&#039;&#039; as it only has to compare a 32-bits unsigned integer instead of a string. The interface index is dynamically allocated, so don&#039;t use this for interfaces that are dynamically created and destroyed, eg. &#039;&#039;ppp0&#039;&#039;.&lt;br /&gt;
* &#039;&#039;oif&#039;&#039;, like &#039;&#039;iif&#039;&#039; but it matches the output network interface index.&lt;br /&gt;
&lt;br /&gt;
An example usage of the interface name is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input meta oifname lo accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule accepts all traffic for the loopback pseudodevice &#039;&#039;lo&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Matching packets by packet mark =&lt;br /&gt;
&lt;br /&gt;
You can match packets whose mark is 123 with the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add rule filter output meta mark 123 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Matching packets the socket UID =&lt;br /&gt;
&lt;br /&gt;
You can use your user name to match traffic, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid pablo counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or the 32-bits unsigned integer (UID) in case there is no entry in /etc/passwd for a given user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid 1000 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s just generate some HTTP traffic to test this rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% wget --spider http://www.google.com&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if you check the counters, you can verify that the packets are matching that rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 skuid pablo counter packets 7 bytes 510&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: Beware if you test this with &#039;&#039;ping&#039;&#039;, it is usually installed with suid so that traffic will match the root user (uid=0).&lt;br /&gt;
&lt;br /&gt;
= Matching packet priority =&lt;br /&gt;
&lt;br /&gt;
* Since nftables v0.7 you can match the packet priority, the tc classid:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority abcd:1234&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Packet without set priority can be matched using meta priority none&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority none&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=482</id>
		<title>Matching packet metainformation</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=482"/>
		<updated>2019-12-17T09:36:42Z</updated>

		<summary type="html">&lt;p&gt;Arturo: refresh layout of the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The meta selectors allows you to match ([[Setting_packet_metainformation |and in some cases, set]]) packet metainformation.&lt;br /&gt;
&lt;br /&gt;
= The meta selectors =&lt;br /&gt;
&lt;br /&gt;
We have 2 types of meta statement, qualified and unqualified. Qualified ones require you use the &#039;&#039;&#039;meta&#039;&#039;&#039; keyword, and for unqualified ones it can be skipped.&lt;br /&gt;
&lt;br /&gt;
* qualified meta statements:&lt;br /&gt;
** length -- packet lenght&lt;br /&gt;
** protocol -- packet protocol&lt;br /&gt;
** priority -- packet priority, tc handle. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** random -- match against a single/simple random number&lt;br /&gt;
** secmark -- packet secmark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
&lt;br /&gt;
* unqualified meta statements:&lt;br /&gt;
** mark -- packet mark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** iif -- input interface index&lt;br /&gt;
** iifname -- input interface name&lt;br /&gt;
** iiftype -- input interface type&lt;br /&gt;
** oif -- output interface index&lt;br /&gt;
** oifname -- output interface name&lt;br /&gt;
** oiftype -- output interface type&lt;br /&gt;
** skuid -- socket uid&lt;br /&gt;
** skgid -- socket gid&lt;br /&gt;
** nftrace -- nftrace debugging bit. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** rtclassid -- realm&lt;br /&gt;
** ibriport -- input bridge port&lt;br /&gt;
** obriport -- output bridge port&lt;br /&gt;
** ibridgename -- input bridge name&lt;br /&gt;
** obridgename -- output bridge name&lt;br /&gt;
** pkttype -- packet type. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** cpu -- cpu number&lt;br /&gt;
** iifgroup -- input interface group&lt;br /&gt;
** oifgroup -- output interface group&lt;br /&gt;
** cgroup -- cgroup number&lt;br /&gt;
** ipsec -- ipsec packet or not&lt;br /&gt;
** time -- packet timestamp&lt;br /&gt;
** day -- packet timestamp&lt;br /&gt;
** hour -- packet timestamp&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Matching packets by interface name =&lt;br /&gt;
&lt;br /&gt;
You can use one of the following selectors to match the interface name:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;iifname&#039;&#039;, to match the input network interface name.&lt;br /&gt;
* &#039;&#039;oifname&#039;&#039;, to match the output network interface name.&lt;br /&gt;
* &#039;&#039;iif&#039;&#039;, to match the interface index of the network interface name. This is faster than &#039;&#039;iifname&#039;&#039; as it only has to compare a 32-bits unsigned integer instead of a string. The interface index is dynamically allocated, so don&#039;t use this for interfaces that are dynamically created and destroyed, eg. &#039;&#039;ppp0&#039;&#039;.&lt;br /&gt;
* &#039;&#039;oif&#039;&#039;, like &#039;&#039;iif&#039;&#039; but it matches the output network interface index.&lt;br /&gt;
&lt;br /&gt;
An example usage of the interface name is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input meta oifname lo accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule accepts all traffic for the loopback pseudodevice &#039;&#039;lo&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Matching packets by packet mark =&lt;br /&gt;
&lt;br /&gt;
You can match packets whose mark is 123 with the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add rule filter output meta mark 123 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Matching packets the socket UID =&lt;br /&gt;
&lt;br /&gt;
You can use your user name to match traffic, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid pablo counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or the 32-bits unsigned integer (UID) in case there is no entry in /etc/passwd for a given user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid 1000 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s just generate some HTTP traffic to test this rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% wget --spider http://www.google.com&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if you check the counters, you can verify that the packets are matching that rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 skuid pablo counter packets 7 bytes 510&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: Beware if you test this with &#039;&#039;ping&#039;&#039;, it is usually installed with suid so that traffic will match the root user (uid=0).&lt;br /&gt;
&lt;br /&gt;
= Matching packet priority =&lt;br /&gt;
&lt;br /&gt;
* Since nftables v0.7 you can match the packet priority, the tc classid:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority abcd:1234&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Packet without set priority can be matched using meta priority none&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority none&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=481</id>
		<title>Matching packet metainformation</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Matching_packet_metainformation&amp;diff=481"/>
		<updated>2019-12-17T09:27:20Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* The meta selectors */ refresh selectors, mention unqualified/qualified ones&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;nftables&#039;&#039; comes with the packet metainformation selectors that you can use to match information that is stored in the network packet. &lt;br /&gt;
&lt;br /&gt;
= The meta selectors =&lt;br /&gt;
&lt;br /&gt;
The meta selectors allows you to match ([[Setting_packet_metainformation |and in some cases, set]]) packet metainformation.&lt;br /&gt;
&lt;br /&gt;
We have 2 types of meta statement, qualified and unqualified. Qualified ones require you use the &#039;&#039;&#039;meta&#039;&#039;&#039; keyword, and for unqualified ones it can be skipped.&lt;br /&gt;
&lt;br /&gt;
* qualified meta statements:&lt;br /&gt;
** length -- packet lenght&lt;br /&gt;
** protocol -- packet protocol&lt;br /&gt;
** priority -- packet priority, tc handle. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** random -- match against a single/simple random number&lt;br /&gt;
** secmark -- packet secmark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
&lt;br /&gt;
* unqualified meta statements:&lt;br /&gt;
** mark -- packet mark. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** iif -- input interface index&lt;br /&gt;
** iifname -- input interface name&lt;br /&gt;
** iiftype -- input interface type&lt;br /&gt;
** oif -- output interface index&lt;br /&gt;
** oifname -- output interface name&lt;br /&gt;
** oiftype -- output interface type&lt;br /&gt;
** skuid -- socket uid&lt;br /&gt;
** skgid -- socket gid&lt;br /&gt;
** nftrace -- nftrace debugging bit. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** rtclassid -- realm&lt;br /&gt;
** ibriport -- input bridge port&lt;br /&gt;
** obriport -- output bridge port&lt;br /&gt;
** ibridgename -- input bridge name&lt;br /&gt;
** obridgename -- output bridge name&lt;br /&gt;
** pkttype -- packet type. [[Setting_packet_metainformation |Can be set]].&lt;br /&gt;
** cpu -- cpu number&lt;br /&gt;
** iifgroup -- input interface group&lt;br /&gt;
** oifgroup -- output interface group&lt;br /&gt;
** cgroup -- cgroup number&lt;br /&gt;
** ipsec -- ipsec packet or not&lt;br /&gt;
** time -- packet timestamp&lt;br /&gt;
** day -- packet timestamp&lt;br /&gt;
** hour -- packet timestamp&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Matching packets by interface name ==&lt;br /&gt;
&lt;br /&gt;
You can use one of the following selectors to match the interface name:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;iifname&#039;&#039;, to match the input network interface name.&lt;br /&gt;
* &#039;&#039;oifname&#039;&#039;, to match the output network interface name.&lt;br /&gt;
* &#039;&#039;iif&#039;&#039;, to match the interface index of the network interface name. This is faster than &#039;&#039;iifname&#039;&#039; as it only has to compare a 32-bits unsigned integer instead of a string. The interface index is dynamically allocated, so don&#039;t use this for interfaces that are dynamically created and destroyed, eg. &#039;&#039;ppp0&#039;&#039;.&lt;br /&gt;
* &#039;&#039;oif&#039;&#039;, like &#039;&#039;iif&#039;&#039; but it matches the output network interface index.&lt;br /&gt;
&lt;br /&gt;
An example usage of the interface name is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input meta oifname lo accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule accepts all traffic for the loopback pseudodevice &#039;&#039;lo&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Matching packets by packet mark ==&lt;br /&gt;
&lt;br /&gt;
You can match packets whose mark is 123 with the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add rule filter output meta mark 123 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Matching packets the socket UID ==&lt;br /&gt;
&lt;br /&gt;
You can use your user name to match traffic, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid pablo counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or the 32-bits unsigned integer (UID) in case there is no entry in /etc/passwd for a given user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter output meta skuid 1000 counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s just generate some HTTP traffic to test this rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% wget --spider http://www.google.com&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if you check the counters, you can verify that the packets are matching that rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain output {&lt;br /&gt;
                 type filter hook output priority 0;&lt;br /&gt;
                 skuid pablo counter packets 7 bytes 510&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: Beware if you test this with &#039;&#039;ping&#039;&#039;, it is usually installed with suid so that traffic will match the root user (uid=0).&lt;br /&gt;
&lt;br /&gt;
== Matching packet priority ==&lt;br /&gt;
&lt;br /&gt;
* Since nftables v0.7 you can match the packet priority, the tc classid:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority abcd:1234&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Packet without set priority can be matched using meta priority none&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward meta priority none&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Load_balancing&amp;diff=479</id>
		<title>Load balancing</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Load_balancing&amp;diff=479"/>
		<updated>2019-11-27T14:37:56Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Round Robin */ mod 100&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since nftables v0.7, there is support in place to perform [[Performing Network Address Translation (NAT) | NAT]] load balancing.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget the special NAT chain semantics: Only the first packet evaluates the rule, follow up packets rely on conntrack to apply the NAT information.&lt;br /&gt;
&lt;br /&gt;
== Round Robin ==&lt;br /&gt;
&lt;br /&gt;
This method uses the nftables [[Math operations | number generator]].&lt;br /&gt;
&lt;br /&gt;
The example below is distributing new connections in a round-robin fashion between 192.168.10.100 and 192.168.20.200.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting dnat to numgen inc mod 2 map { \&lt;br /&gt;
               0 : 192.168.10.100, \&lt;br /&gt;
               1 : 192.168.20.200 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also emulate flow distribution with different backend weights using intervals:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting dnat to numgen inc mod 10 map { \&lt;br /&gt;
               0-5 : 192.168.10.100, \&lt;br /&gt;
               6-9 : 192.168.20.200 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The distribution can be based on ports as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting ip protocol tcp dnat to 192.168.1.100 : numgen inc mod 2 map {\&lt;br /&gt;
               0 : 4040 ,\&lt;br /&gt;
               1 : 4050 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Support for random and probability-based distributions also exists:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting numgen random mod 2 vmap { 0 : jump mychain1, 1 : jump mychain2 }&lt;br /&gt;
% nft add rule nat prerouting numgen random mod 100 vmap { 0-49 : jump mychain1, 50-99 : jump mychain2 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Consistent Hash-based Distribution ==&lt;br /&gt;
&lt;br /&gt;
Using the nftables internal [[Math operations | hashing mechanisms]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y dnat to jhash ip saddr . tcp dport mod 2 map { \&lt;br /&gt;
                0 : 192.168.20.100, \&lt;br /&gt;
                1 : 192.168.30.100 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This relies on the Jenkins hash.&lt;br /&gt;
&lt;br /&gt;
== Using stateless NAT ==&lt;br /&gt;
&lt;br /&gt;
You can perform load balancing through stateless NAT approach as well. You can combine this either with the round robin and consistent hash-based distribution approaches.&lt;br /&gt;
&lt;br /&gt;
The example below uses Round Robin flow distribution:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule t c tcp dport 80 ip daddr set numgen inc mod 2 map { 0 : 192.168.1.100, 1 : 192.168.1.101 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is more lightweight that stateful NAT given there is no flow tracking in place. This is indeed [[Mangle packet header fields | mangling packet header fields]].&lt;br /&gt;
&lt;br /&gt;
== Using Direct Server Return (DSR) ==&lt;br /&gt;
&lt;br /&gt;
This example performs a DSR topology for connectionless flows from ingress:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule netdev t c udp dport 53 ether saddr set aa:bb:cc:dd:ff:ee ether daddr set numgen inc mod 2 map { 0 : xx:xx:xx:xx:xx:xx, 1: yy:yy:yy:yy:yy:yy } fwd to eth0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An approach for connection oriented flows can be performed as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule netdev t c tcp dport 80 ether saddr set aa:bb:cc:dd:ff:ee ether daddr set jhash ip saddr . tcp sport mod 2 map { 0 : xx:xx:xx:xx:xx:xx, 1: yy:yy:yy:yy:yy:yy } fwd to eth0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that xx:xx:xx:xx:xx:xx and yy:yy:yy:yy:yy:yy need to be replaced by the real destination MAC address.&lt;br /&gt;
This is [[Mangle packet header fields | mangling packet header fields]] as well.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Load_balancing&amp;diff=477</id>
		<title>Load balancing</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Load_balancing&amp;diff=477"/>
		<updated>2019-11-27T09:58:23Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Round Robin */ add example using random and probability&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since nftables v0.7, there is support in place to perform [[Performing Network Address Translation (NAT) | NAT]] load balancing.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget the special NAT chain semantics: Only the first packet evaluates the rule, follow up packets rely on conntrack to apply the NAT information.&lt;br /&gt;
&lt;br /&gt;
== Round Robin ==&lt;br /&gt;
&lt;br /&gt;
This method uses the nftables [[Math operations | number generator]].&lt;br /&gt;
&lt;br /&gt;
The example below is distributing new connections in a round-robin fashion between 192.168.10.100 and 192.168.20.200.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting dnat to numgen inc mod 2 map { \&lt;br /&gt;
               0 : 192.168.10.100, \&lt;br /&gt;
               1 : 192.168.20.200 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also emulate flow distribution with different backend weights using intervals:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting dnat to numgen inc mod 10 map { \&lt;br /&gt;
               0-5 : 192.168.10.100, \&lt;br /&gt;
               6-9 : 192.168.20.200 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The distribution can be based on ports as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting ip protocol tcp dnat to 192.168.1.100 : numgen inc mod 2 map {\&lt;br /&gt;
               0 : 4040 ,\&lt;br /&gt;
               1 : 4050 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Support for random and probability-based distributions also exists:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting numgen random mod 2 vmap { 0 : jump mychain1, 1 : jump mychain2 }&lt;br /&gt;
% nft add rule nat prerouting numgen random mod 99 vmap { 0-49 : jump mychain1, 50-99 : jump mychain2 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Consistent Hash-based Distribution ==&lt;br /&gt;
&lt;br /&gt;
Using the nftables internal [[Math operations | hashing mechanisms]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y dnat to jhash ip saddr . tcp dport mod 2 map { \&lt;br /&gt;
                0 : 192.168.20.100, \&lt;br /&gt;
                1 : 192.168.30.100 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This relies on the Jenkins hash.&lt;br /&gt;
&lt;br /&gt;
== Using stateless NAT ==&lt;br /&gt;
&lt;br /&gt;
You can perform load balancing through stateless NAT approach as well. You can combine this either with the round robin and consistent hash-based distribution approaches.&lt;br /&gt;
&lt;br /&gt;
The example below uses Round Robin flow distribution:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule t c tcp dport 80 ip daddr set numgen inc mod 2 map { 0 : 192.168.1.100, 1 : 192.168.1.101 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is more lightweight that stateful NAT given there is no flow tracking in place. This is indeed [[Mangle packet header fields | mangling packet header fields]].&lt;br /&gt;
&lt;br /&gt;
== Using Direct Server Return (DSR) ==&lt;br /&gt;
&lt;br /&gt;
This example performs a DSR topology for connectionless flows from ingress:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule netdev t c udp dport 53 ether saddr set aa:bb:cc:dd:ff:ee ether daddr set numgen inc mod 2 map { 0 : xx:xx:xx:xx:xx:xx, 1: yy:yy:yy:yy:yy:yy } fwd to eth0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An approach for connection oriented flows can be performed as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule netdev t c tcp dport 80 ether saddr set aa:bb:cc:dd:ff:ee ether daddr set jhash ip saddr . tcp sport mod 2 map { 0 : xx:xx:xx:xx:xx:xx, 1: yy:yy:yy:yy:yy:yy } fwd to eth0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that xx:xx:xx:xx:xx:xx and yy:yy:yy:yy:yy:yy need to be replaced by the real destination MAC address.&lt;br /&gt;
This is [[Mangle packet header fields | mangling packet header fields]] as well.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Verdict_Maps_(vmaps)&amp;diff=475</id>
		<title>Verdict Maps (vmaps)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Verdict_Maps_(vmaps)&amp;diff=475"/>
		<updated>2019-11-04T14:06:34Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Literal dictionaries */ drop unrelated example line&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;dictionaries&#039;&#039;, also known as &#039;&#039;verdict maps&#039;&#039;, are one of the most interesting features available in &#039;&#039;nftables&#039;&#039;. Basically, they allow you to attach an action to an element. Dictionaries internally use the generic set infrastructure.&lt;br /&gt;
&lt;br /&gt;
= Literal dictionaries =&lt;br /&gt;
&lt;br /&gt;
The following example shows how to create a tree of chains that whose traversal depends on the layer 4 protocol type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip protocol vmap { tcp : jump tcp-chain, udp : jump udp-chain , icmp : jump icmp-chain }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example above assumes that you&#039;ve already created the &#039;&#039;tcp-chain&#039;&#039;, &#039;&#039;udp-chain&#039;&#039; and &#039;&#039;icmp-chain&#039;&#039; [[Configuring chains|custom chains]]. Then, by attaching simple rules to account the traffic, ie.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter icmp-chain counter&lt;br /&gt;
% nft add rule filter tcp-chain counter&lt;br /&gt;
% nft add rule filter udp-chain counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can check that the classification is already happening:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list table filter&lt;br /&gt;
table ip filter {&lt;br /&gt;
        chain input {&lt;br /&gt;
                 type filter hook input priority 0;&lt;br /&gt;
                 ip protocol vmap { udp : jump udp-chain, tcp : jump tcp-chain, icmp : jump icmp-chain}&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain tcp-chain {&lt;br /&gt;
                 counter packets 4 bytes 520&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain udp-chain {&lt;br /&gt;
                 counter packets 4 bytes 678&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        chain icmp-chain {&lt;br /&gt;
                 counter packets 4 bytes 336&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you probably already noticed, one of the the good things of nftables is that you can use &#039;&#039;dictionaries&#039;&#039; to construct performance rule-sets. This rule-set arrangement allows you to reduce the amount of linear list inspections to classify your packets.&lt;br /&gt;
&lt;br /&gt;
= Dictionary declarations =&lt;br /&gt;
&lt;br /&gt;
You can also declarate dictionaries and populate its content dynamically, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter mydict { type ipv4_addr : verdict\; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add elements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element filter mydict { 192.168.0.10 : drop, 192.168.0.11 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can bind this set to a rule using the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input ip saddr vmap @mydict&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case you want to build your own dictionary, but you don&#039;t know what is the datatype name. Remember that you can inquire &#039;&#039;nft&#039;&#039; to know the datatype name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft describe tcp dport&lt;br /&gt;
payload expression, datatype inet_service (internet network service) (basetype integer), 16 bits&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the &#039;&#039;inet_service&#039;&#039; string after datatype.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=474</id>
		<title>Sets</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Sets&amp;diff=474"/>
		<updated>2019-11-04T11:41:11Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Named sets specifications */ add ifname&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;nftables&#039;&#039; comes with a built-in generic set infrastructure that allows you to use &#039;&#039;&#039;any&#039;&#039;&#039; supported selector to build sets. This infrastructure makes possible the representation of [[dictionaries]] and [[maps]].&lt;br /&gt;
&lt;br /&gt;
The set elements are internally represented using performance data structures such as hashtables and red-black trees.&lt;br /&gt;
&lt;br /&gt;
= Anonymous sets =&lt;br /&gt;
&lt;br /&gt;
Anonymous sets are those that are:&lt;br /&gt;
&lt;br /&gt;
* Bound to a rule, if the rule is removed, that set is released too.&lt;br /&gt;
* They have no specific name, the kernel internally allocates an identifier.&lt;br /&gt;
* They cannot be updated. So you cannot add and delete elements from it once it is bound to a rule.&lt;br /&gt;
&lt;br /&gt;
The following example shows how to create a simple set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter output tcp dport { 22, 23 } counter&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule above catches all traffic going to TCP ports 22 and 23, in case of matching the counters are updated.&lt;br /&gt;
&lt;br /&gt;
Eric Leblond in his [https://home.regit.org/2014/01/why-you-will-love-nftables/ Why you will love nftables] article shows a very simple example to compare iptables with nftables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -A INPUT -p tcp -m multiport --dports 23,80,443 -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT&lt;br /&gt;
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which can be expressed in &#039;&#039;nftables&#039;&#039; with a couple of rules that provide a set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip6 filter input tcp dport {telnet, http, https} accept&lt;br /&gt;
% nft add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Named sets =&lt;br /&gt;
&lt;br /&gt;
You can create the named sets with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter blackhole { type ipv4_addr\;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;blackhole&#039;&#039; is the name of the set in this case. The &#039;&#039;type&#039;&#039; option indicates the data type that this set stores, which is an IPv4 address in this case. Current maximum name length is 16 characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element ip filter blackhole { 192.168.3.4 }&lt;br /&gt;
% nft add element ip filter blackhole { 192.168.1.4, 192.168.1.5 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can use it from the rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip saddr @blackhole drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Named sets can be updated anytime, so you can add and delete element from them.&lt;br /&gt;
&lt;br /&gt;
= Named sets specifications =&lt;br /&gt;
&lt;br /&gt;
Sets specifications are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;type&#039;&#039;&#039;, is obligatory and determines the data type of the set elements. Supported data types currently are:&lt;br /&gt;
** &#039;&#039;ipv4_addr&#039;&#039;: IPv4 address&lt;br /&gt;
** &#039;&#039;ipv6_addr&#039;&#039;: IPv6 address.&lt;br /&gt;
** &#039;&#039;ether_addr&#039;&#039;: Ethernet address.&lt;br /&gt;
** &#039;&#039;inet_proto&#039;&#039;: Inet protocol type.&lt;br /&gt;
** &#039;&#039;inet_service&#039;&#039;: Internet service (read tcp port for example)&lt;br /&gt;
** &#039;&#039;mark&#039;&#039;: Mark type.&lt;br /&gt;
** &#039;&#039;ifname&#039;&#039;: Network interface name (eth0, eth1..)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;timeout&#039;&#039;&#039;, it determines how long an element stays in the set. The time string respects the format: &#039;&#039;&amp;quot;v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;dv&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;hv&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;mv&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;s&amp;quot;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft add set ip filter ports {type inet_service \; timeout 3h45s \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These commands create a table named &#039;&#039;filter&#039;&#039; and add a set named &#039;&#039;ports&#039;&#039; to it, where elements are deleted after 3 hours and 45 seconds of being added.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;flags&#039;&#039;&#039;, the available flags are:&lt;br /&gt;
** &#039;&#039;constant&#039;&#039; - set content may not change while bound&lt;br /&gt;
** &#039;&#039;interval&#039;&#039; - set contains intervals&lt;br /&gt;
** &#039;&#039;timeout&#039;&#039; - elements can be added with a timeout&lt;br /&gt;
&lt;br /&gt;
Multiple flags should be separated by comma:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter flags_set {type ipv4_addr\; flags constant, interval\;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;gc-interval&#039;&#039;&#039;, stands for garbage collection interval, can only be used if &#039;&#039;timeout&#039;&#039; or &#039;&#039;flags timeout&#039;&#039; are active. The interval follows the same format of &#039;&#039;timeouts&#039;&#039; time string &#039;&#039;&amp;quot;v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;dv&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;hv&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;mv&amp;lt;sub&amp;gt;4&amp;lt;/sub&amp;gt;s&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;elements&#039;&#039;&#039;, initialize the set with some elements in it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter daddrs {type ipv4_addr \; flags timeout \; elements={192.168.1.1 timeout 10s, 192.168.1.2 timeout 30s} \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command creates a set name &#039;&#039;daddrs&#039;&#039; with elements &#039;&#039;192.168.1.1&#039;&#039;, which stays in it for 10s, and &#039;&#039;192.168.1.2&#039;&#039;, which stays for 30s.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;size&#039;&#039;&#039;, limits the maximum number of elements of the set. To create a set with maximum 2 elements type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set ip filter saddrs {type ipv4_addr \; size 2 \;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;policy&#039;&#039;&#039;, determines set selection policy. Available values are:&lt;br /&gt;
** &#039;&#039;performance&#039;&#039; [default]&lt;br /&gt;
** &#039;&#039;memory&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Listing named sets =&lt;br /&gt;
&lt;br /&gt;
You can list the content of a named set via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list set ip filter myset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Meters&amp;diff=473</id>
		<title>Meters</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Meters&amp;diff=473"/>
		<updated>2019-10-30T10:56:50Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Meters */ refresh paragraph&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Meters ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dynamic sets/maps&#039;&#039;&#039; or meters are a way to use maps with stateful objects. They used to be known as &#039;&#039;flow tables&#039;&#039; before nft v0.8.1 and Linux kernel 4.3.&lt;br /&gt;
&lt;br /&gt;
Among other things, they provide a native replacement for the &#039;&#039;hashlimit&#039;&#039; match in iptables. However, meters are a lot more flexible since you can use any selector, one or many through [[concatenations]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that the &#039;&#039;meter&#039;&#039; keyword is obsolete, the dynamic set and map syntax is now preferred for consistency.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Using meters ==&lt;br /&gt;
&lt;br /&gt;
The following commands create a table named &#039;&#039;my_filter_table&#039;&#039;, a chain named &#039;&#039;my_input_chain&#039;&#039; which hooks incoming traffic and a rule that uses a meter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table my_filter_table&lt;br /&gt;
% nft add chain my_filter_table my_input_chain {type filter hook input priority 0\;}&lt;br /&gt;
% nft add set my_filter_table my_ssh_meter { type ipv4_addr\; flags dynamic \;}&lt;br /&gt;
% nft add rule my_filter_table my_input_chain tcp dport 22 ct state new add @my_ssh_meter { ip saddr limit rate 10/second } accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we create a rule to match &#039;&#039;new&#039;&#039; TCP &#039;&#039;ssh&#039;&#039; (port 22) connections, which uses a dynamic set named &#039;&#039;my_ssh_meter&#039;&#039; to limit the traffic rate to 10 connections per second for each source IP address. The available time units on limits are: &#039;&#039;second&#039;&#039;, &#039;&#039;minute&#039;&#039;, &#039;&#039;hour&#039;&#039;, &#039;&#039;day&#039;&#039; and &#039;&#039;week&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You can also use [[concatenations]] to build selectors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add set my_filter_table my_ssh_meter { type ipv4_addr . inet_service\; flags timeout, dynamic \;}&lt;br /&gt;
% nft add rule my_filter_table my_input_chain tcp dport 22 ct state new add @my_ssh_meter { ip saddr . tcp dport timeout 60s limit rate 10/second } accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule counts incoming connections (packets with state &#039;&#039;new&#039;&#039;) based on the tuple &#039;&#039;(IP source address, TCP destination port)&#039;&#039;, the counters are dropped after 60 seconds without update.&lt;br /&gt;
&lt;br /&gt;
== Listing meters ==&lt;br /&gt;
&lt;br /&gt;
To list the content matched by the meter use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list map my_filter_table my_ssh_meter&lt;br /&gt;
table ip my_filter_table {&lt;br /&gt;
	map my_ssh_meter {&lt;br /&gt;
		type ipv4_addr . inet_service&lt;br /&gt;
                size 65535&lt;br /&gt;
		flags dynamic,timeout&lt;br /&gt;
		elements = { 64.62.190.36 . 55000 expires 38s : counter packets 2 bytes 220, 83.98.201.47 . 35460 expires 39s : counter packets 10 bytes 5988, 172.217.7.142 . 43254 expires 46s : counter packets 1 bytes 98}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Doing connlimit with nft ==&lt;br /&gt;
&lt;br /&gt;
Since 4.18, there is a new &#039;&#039;ct count&#039;&#039; selector that allows you to count the number of existing connections. This extension uses the information available in the Connection Tracking System table, therefore, the counting of connection is based on the existing entries in the table.&lt;br /&gt;
&lt;br /&gt;
The following example shows how to do &#039;&#039;connlimit&#039;&#039; from nftables:&lt;br /&gt;
&lt;br /&gt;
 table ip my_filter_table {&lt;br /&gt;
        set my_connlimit {&lt;br /&gt;
                type ipv4_addr&lt;br /&gt;
                size 65535&lt;br /&gt;
                flags dynamic&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        chain my_output_chain {&lt;br /&gt;
                type filter hook output priority filter; policy accept;&lt;br /&gt;
                ct state new add @my_connlimit { ip daddr ct count over 20 } counter packets 0 bytes 0 drop&lt;br /&gt;
        }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The example above dynamically populates the set &#039;&#039;connlimit&#039;&#039; from the packet path. For the first packet of each connection (ie. packets matching &#039;&#039;ct state new&#039;&#039;), this adds an entry into &#039;&#039;connlimit&#039;&#039; set, this entry uses the IPv4 destination address as a key. If the number of connections goes over 20, then packets are dropped.&lt;br /&gt;
&lt;br /&gt;
Since &#039;&#039;connlimit&#039;&#039; is a set, you can perform any operation on it, such as listing and flushing its content.&lt;br /&gt;
&lt;br /&gt;
== Doing iptables hashlimit with nft ==&lt;br /&gt;
&lt;br /&gt;
Meters replace iptables hashlimit in nft. From iptables v1.6.2 onward, you can use the tool &#039;&#039;&#039;iptables-translate&#039;&#039;&#039; to see how to translate hashlimit rules.&lt;br /&gt;
&lt;br /&gt;
Almost all hashlimit options are available in nft, starting with --hashlimit-mode, it is replaced by the selector in a meter. All modes are available except no mode, a meter demands a selector, an iptables rule without hashlimit-mode isn&#039;t supported in nft. A simple rule translation is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-above 200/sec --hashlimit-mode srcip,dstport --hashlimit-name http1 -j DROP&lt;br /&gt;
nft add rule ip filter INPUT tcp dport 80 meter http1 { tcp dport . ip saddr limit rate over 200/second } counter drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that a meter is named, like hashlimit, and using multiple hashlimit-modes is similar to using a concatenation of selectors. Also, --hashlimit-above is translated to &#039;&#039;limit rate over&#039;&#039;, to simulate --hashlimit-upto just omit or replace &#039;&#039;over&#039;&#039; with &#039;&#039;until&#039;&#039; in the rule.&lt;br /&gt;
&lt;br /&gt;
The options --hashlimit-burst and --hashlimit-htable-expire are translated to &#039;&#039;burst&#039;&#039; and &#039;&#039;timeout&#039;&#039; in a meter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-above 200kb/s --hashlimit-burst 1mb --hashlimit-mode srcip,dstport --hashlimit-name http2 --hashlimit-htable-expire 3000 -j DROP&lt;br /&gt;
nft add rule ip filter INPUT tcp dport 80 meter http2 { tcp dport . ip saddr timeout 3s limit rate over 200 kbytes/second burst 1 mbytes} counter drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule shows how &#039;&#039;timeout&#039;&#039; and &#039;&#039;burst&#039;&#039; are used in a meter, also notice that meters, similarly to hashlimit, accepts limiting rates by bytes frequency instead of packets.&lt;br /&gt;
&lt;br /&gt;
Another hashlimit option is to limit the traffic rate on subnets, of IP source or destination addresses, using the options --hashlimit-srcmask and --hashlimit-dstmask. This feature is available in nft by attaching a subnet mask to a meter selector, attach to &#039;&#039;ip saddr&#039;&#039; for source address and to &#039;&#039;ip daddr&#039;&#039; for destination adress:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-upto 200 --hashlimit-mode srcip --hashlimit-name http3 --hashlimit-srcmask 24 -j DROP&lt;br /&gt;
nft add rule ip filter INPUT tcp dport 80 meter http3 { ip saddr and 255.255.255.0 limit rate 200/second } counter drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This rule will limit packets rate, grouping subnets determined by the first 24 bits of the IP source address, from the incoming packets on port 80.&lt;br /&gt;
&lt;br /&gt;
The remaining options, --hashlimit-htable-max, --hashlimit-htable-size and --hashlimit-htable-gcinterval don&#039;t apply to meters.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Concatenations&amp;diff=472</id>
		<title>Concatenations</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Concatenations&amp;diff=472"/>
		<updated>2019-10-30T10:46:57Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Some ipset types */ refactor examples into the moving from ipset to nftables page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Linux kernel 4.1, nftables supports concatenations.&lt;br /&gt;
&lt;br /&gt;
This new feature allows you to put two or more selectors together to perform very fast lookups by combining them with [[sets]], [[dictionaries]], [[maps]] and [[meters]].&lt;br /&gt;
&lt;br /&gt;
= Literal sets =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip filter input ip saddr . ip daddr . ip protocol { 1.1.1.1 . 2.2.2.2 . tcp, 1.1.1.1 . 3.3.3.3 . udp} counter accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So if the packet&#039;s source IP address AND destination IP address AND level 4 protocol match:&lt;br /&gt;
&lt;br /&gt;
* 1.1.1.1 and 2.2.2.2 and TCP.&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
* 1.1.1.1 and 3.3.3.3 and UDP.&lt;br /&gt;
&lt;br /&gt;
nftables updates the counter for this rule and then accepts the packet.&lt;br /&gt;
&lt;br /&gt;
= Dictionary declarations =&lt;br /&gt;
&lt;br /&gt;
The following example creates the &#039;&#039;whitelist&#039;&#039; dictionary using a concatenation of two selectors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map filter whitelist { type ipv4_addr . inet_service : verdict \; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you create the dictionary, you can use it from a rule that creates the following concatenation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input ip saddr . tcp dport vmap @whitelist&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Thus, the rule above looks up for a verdict based on the source IP address AND the TCP destination port.&lt;br /&gt;
&lt;br /&gt;
Since the dictionary is initially empty, you can dynamically populate this dictionary with elements through:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add element filter whitelist { 1.2.3.4 . 22 : accept}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Literal maps =&lt;br /&gt;
&lt;br /&gt;
The rule below determines the destination IP address that is used to perform DNAT to the packet based on:&lt;br /&gt;
&lt;br /&gt;
* the source IP address&lt;br /&gt;
&lt;br /&gt;
AND&lt;br /&gt;
&lt;br /&gt;
* the destination TCP port&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule ip nat prerouting dnat ip saddr . tcp dport map { 1.1.1.1 . 80 : 192.168.1.100, 2.2.2.2 . 8888 : 192.168.1.101 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
&lt;br /&gt;
Some concrete example concatenations so you get an idea on how powerful this new feature is.&lt;br /&gt;
&lt;br /&gt;
== Network addresses ==&lt;br /&gt;
&lt;br /&gt;
The example below implements a dictionary using network masks as matching element.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . ip daddr and 255.255.255.0 vmap { 10.10.10.0 . 10.10.20.0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this is not an interval, this is masking the ip saddr and ip daddr, then concate both results. This concatenation is used to lookup for a matching of this the result in the map. This syntax may be compacted in future releases to support CIDR notation.&lt;br /&gt;
&lt;br /&gt;
This could be easily implemented using a named map as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add map tablename myMap { type ipv4_addr . ipv4_addr : verdict \; }&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . ip saddr and 255.255.255.0 vmap @myMap&lt;br /&gt;
% nft add element tablename myMap { 10.10.10.0 . 10.10.20.0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interfaces ==&lt;br /&gt;
&lt;br /&gt;
The example below checks both input and output interfaces of a forwarded packet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname iif . oif vmap { eth0 . eth1 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note that using strings (for example iifname and oifname) and other variable sized data types is not supported yet.&lt;br /&gt;
&lt;br /&gt;
== Some ipset types ==&lt;br /&gt;
&lt;br /&gt;
These ipset types can be implemented in nftables using concatenations. Probably more equivalences exists, it just a matter of combining data types.&lt;br /&gt;
Of course, you could implement these as named maps/sets as well.&lt;br /&gt;
&lt;br /&gt;
See examples in the [[Moving_from_ipset_to_nftables | moving from ipset to nftables]] page.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Moving_from_ipset_to_nftables&amp;diff=471</id>
		<title>Moving from ipset to nftables</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Moving_from_ipset_to_nftables&amp;diff=471"/>
		<updated>2019-10-30T10:45:33Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add more examples, migrated from Concatenations page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you are [[Moving from iptables to nftables | moving from iptables to nftables]] and you used [[ipset]], some considerations should be taken into account.&lt;br /&gt;
&lt;br /&gt;
* There are no translation/compat tools right now to help in the task. This may change in the future.&lt;br /&gt;
* ipset uses explicit set types, like &#039;&#039;&#039;hash:net,port,net&#039;&#039;&#039; which you need to translate to nftables native data types (like &#039;&#039;&#039;ipv4_addr . inet_service . ipv4_addr&#039;&#039;&#039;)&lt;br /&gt;
* nftables support mappings and dictionaries, so you could take actions directly from matching elements in the set.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Here is an example. This is a basic ipset/iptables setup:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
user@debian:~ $ sudo ipset save&lt;br /&gt;
create myset hash:ip,port,ip family inet hashsize 1024 maxelem 65536&lt;br /&gt;
add myset 172.16.0.1,tcp:80,10.0.0.1&lt;br /&gt;
&lt;br /&gt;
user@debian:~ $ sudo iptables-save&lt;br /&gt;
# Generated by iptables-save v1.8.3 on Wed Oct 30 11:26:41 2019&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT ACCEPT [3:212]&lt;br /&gt;
:FORWARD ACCEPT [0:0]&lt;br /&gt;
:OUTPUT ACCEPT [4:250]&lt;br /&gt;
-A INPUT -m set --match-set myset src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That would translate into nftables as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
user@debian:~ $ sudo nft list ruleset&lt;br /&gt;
table inet filter {&lt;br /&gt;
	map myset {&lt;br /&gt;
		type ipv4_addr . inet_service . ipv4_addr : verdict&lt;br /&gt;
		elements = { 172.16.0.1 . 80 . 10.0.0.1 : accept }&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	chain input {&lt;br /&gt;
		type filter hook input priority filter; policy accept;&lt;br /&gt;
		meta nfproto ipv4 ip saddr . tcp dport . ip daddr vmap @myset&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that nftables is capable of storing verdict information per set element, which can drastically reduce the amount of rules required in the ruleset compared to iptables/ipset.&lt;br /&gt;
&lt;br /&gt;
We recommend reading information about [[Concatenations | concatenations]]. Some additional ipset datatype equivalents:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;hash:net,net&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . ip daddr and 255.255.255.0 vmap { 10.10.10.0 . 10.10.20.0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;hash:net,port,net&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . tcp dport . ip daddr and 255.255.255.0 vmap { 10.10.10.0 . 80 . 10.10.20.0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;hash:net,iface&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule tablename chainname ip saddr and 255.255.255.0 . iif vmap { 10.10.10.0 . eth0 : accept }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This syntax may be compacted in the future to support CIDR notation.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Concatenations]]&lt;br /&gt;
* [[Sets]]&lt;br /&gt;
* [[Dictionaries]]&lt;br /&gt;
* [[Maps]]&lt;br /&gt;
* [[Legacy xtables tools]]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Moving_from_ipset_to_nftables&amp;diff=470</id>
		<title>Moving from ipset to nftables</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Moving_from_ipset_to_nftables&amp;diff=470"/>
		<updated>2019-10-30T10:40:58Z</updated>

		<summary type="html">&lt;p&gt;Arturo: add example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you are [[Moving from iptables to nftables | moving from iptables to nftables]] and you used [[ipset]], some considerations should be taken into account.&lt;br /&gt;
&lt;br /&gt;
* There are no translation/compat tools right now to help in the task. This may change in the future.&lt;br /&gt;
* ipset uses explicit set types, like &#039;&#039;&#039;hash:net,port,net&#039;&#039;&#039; which you need to translate to nftables native data types (like &#039;&#039;&#039;ipv4_addr . inet_service . ipv4_addr&#039;&#039;&#039;)&lt;br /&gt;
* nftables support mappings and dictionaries, so you could take actions directly from matching elements in the set.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Here is an example. This is a basic ipset/iptables setup:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
user@debian:~ $ sudo ipset save&lt;br /&gt;
create myset hash:ip,port,ip family inet hashsize 1024 maxelem 65536&lt;br /&gt;
add myset 172.16.0.1,tcp:80,10.0.0.1&lt;br /&gt;
&lt;br /&gt;
user@debian:~ $ sudo iptables-save&lt;br /&gt;
# Generated by iptables-save v1.8.3 on Wed Oct 30 11:26:41 2019&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT ACCEPT [3:212]&lt;br /&gt;
:FORWARD ACCEPT [0:0]&lt;br /&gt;
:OUTPUT ACCEPT [4:250]&lt;br /&gt;
-A INPUT -m set --match-set myset src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That would translate into nftables as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
user@debian:~ $ sudo nft list ruleset&lt;br /&gt;
table inet filter {&lt;br /&gt;
	map myset {&lt;br /&gt;
		type ipv4_addr . inet_service . ipv4_addr : verdict&lt;br /&gt;
		elements = { 172.16.0.1 . 80 . 10.0.0.1 : accept }&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	chain input {&lt;br /&gt;
		type filter hook input priority filter; policy accept;&lt;br /&gt;
		meta nfproto ipv4 ip saddr . tcp dport . ip daddr vmap @myset&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that nftables is capable of storing verdict information per set element, which can drastically reduce the amount of rules required in the ruleset compared to iptables/ipset.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Concatenations]]&lt;br /&gt;
* [[Sets]]&lt;br /&gt;
* [[Dictionaries]]&lt;br /&gt;
* [[Maps]]&lt;br /&gt;
* [[Legacy xtables tools]]&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=450</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=450"/>
		<updated>2019-08-28T22:34:57Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* Adding non-base chains */ make more explicit that chain name can be arbitrary and clarify the example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, you attach your [[Simple rule management|rules]] to chains. However, contrary to the &#039;&#039;iptables&#039;&#039; modus operandi, the &#039;&#039;nftables&#039;&#039; infrastructure comes with no predefined chains, so you need to register your base chains in first place before you can add any rule. This allows very flexible configurations.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
The syntax to add base chains is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain [&amp;lt;family&amp;gt;] &amp;lt;table-name&amp;gt; &amp;lt;chain-name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; priority &amp;lt;value&amp;gt; \; [policy &amp;lt;policy&amp;gt;] } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], ie. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The following example show how you can add new base chains to the &#039;&#039;foo&#039;&#039; table through the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain ip foo input { type filter hook input priority 0 \; } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: You have to escape the semicolon if you are running this command from &#039;&#039;bash&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, ie. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain ip foo output { type filter hook output priority 0 \; } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a non-base chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain ip foo output { type filter hook output priority 0 \; policy accept\; } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain netdev foo dev0filter { type filter hook ingress device eth0 priority 0 \; } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is obviously used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip and ip6 table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). The first packet that belongs to a flow always hits this chain, follow up packets not. Therefore, never use this chain for filtering. This is supported by the ip and ip6 table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible hooks that you can use when you configure your chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: the routing decision for those packets didn&#039;t happen yet, so you don&#039;t know if they are addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: It happens after the routing decision, you can see packets that are directed to the local system and processes running in system.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: It also happens after the routing decision, you can see packet that are not directed to the local machine.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: to catch packets that are originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: After the routing decision for packets leaving the local system.&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only available at the &#039;&#039;netdev&#039;&#039; family): Since Linux kernel 4.2, you can filter traffic way before prerouting, after the packet is passed up from the NIC driver. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
The priority can be used to order the chains or to put them before or after some Netfilter internal operations. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with the priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations. &lt;br /&gt;
&lt;br /&gt;
For reference, here&#039;s the list of different priority used in iptables:&lt;br /&gt;
&lt;br /&gt;
* NF_IP_PRI_CONNTRACK_DEFRAG (-400): priority of defragmentation&lt;br /&gt;
* NF_IP_PRI_RAW (-300): traditional priority of the raw table placed before connection tracking operation&lt;br /&gt;
* NF_IP_PRI_SELINUX_FIRST (-225): SELinux operations&lt;br /&gt;
* NF_IP_PRI_CONNTRACK (-200): Connection tracking operations&lt;br /&gt;
* NF_IP_PRI_MANGLE (-150): mangle operation&lt;br /&gt;
* NF_IP_PRI_NAT_DST (-100): destination NAT&lt;br /&gt;
* NF_IP_PRI_FILTER (0): filtering operation, the filter table&lt;br /&gt;
* NF_IP_PRI_SECURITY (50): Place of security table where secmark can be set for example&lt;br /&gt;
* NF_IP_PRI_NAT_SRC (100): source NAT&lt;br /&gt;
* NF_IP_PRI_SELINUX_LAST (225): SELinux at packet exit&lt;br /&gt;
* NF_IP_PRI_CONNTRACK_HELPER (300): connection tracking at exit&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: if a packet gets accepted and there is another base chain in the same hook which is ordered with a later priority, the packet will be evaluated &#039;&#039;&#039;again&#039;&#039;&#039;.&lt;br /&gt;
That is, packets will traverse chains in a given hook, until it is dropped or no more base chains exist. Drops take instant effect, no further rules or chains are evaluated.&lt;br /&gt;
&lt;br /&gt;
Example ruleset of this behavior:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table inet filter {&lt;br /&gt;
        # this chain is evaluated first due to priority&lt;br /&gt;
        chain ssh {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                # ssh packet accepted&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # this chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # the same ssh packet is dropped here by means of default policy&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If priority of the &#039;input chain&#039; above would be changed to -1, all packets would&lt;br /&gt;
be dropped.&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding non-base chains =&lt;br /&gt;
&lt;br /&gt;
You can also create non-base chains as in &#039;&#039;iptables&#039;&#039; via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain ip &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this chain does &#039;&#039;&#039;not&#039;&#039;&#039; see any traffic as it is not attached to any hook, but it can be very useful to arrange your rule-set in a tree of chains by using the [[jumping to chain|jump to chain]] action.&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete the chains that you don&#039;t need, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will tell you that such chain is in used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip foo input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chain =&lt;br /&gt;
&lt;br /&gt;
You can also flush the content of a chain. If you want to flush all the rule in the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;foo&#039;&#039; table, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft flush chain foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft add chain ip filter input { type filter hook input priority 0 \; }&lt;br /&gt;
% nft add chain ip filter output { type filter hook output priority 0 \; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=444</id>
		<title>Portal:DeveloperDocs/nftables internals</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=444"/>
		<updated>2019-08-02T12:25:29Z</updated>

		<summary type="html">&lt;p&gt;Arturo: /* The kernel subsystem */ mentions briefly expressions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information for Netfilter developers on how &#039;&#039;&#039;nftables internals&#039;&#039;&#039; work.&lt;br /&gt;
&lt;br /&gt;
= The kernel subsystem =&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;nf_tables&#039;&#039;&#039; kernel subsystem contains 2 key components:&lt;br /&gt;
&lt;br /&gt;
* the netlink API (i.e, control plane API)&lt;br /&gt;
* the nf_tables core (i.e, the data plane engine)&lt;br /&gt;
&lt;br /&gt;
Other components, such as external modules, are also in place and are intermixed with both the API and the core.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the nf_tables subsystem is implementing a virtual machine of low-level expressions that operates on network packets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables netlink API ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_api.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_api.c [git src]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables core ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_core.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_core.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_core.c [git src]]&lt;br /&gt;
&lt;br /&gt;
You can see there one of the most important functions in the core: &#039;&#039;&#039;nft_do_chain()&#039;&#039;&#039;. In a nut shell, this is the function that evaluates network packets against the ruleset.&lt;br /&gt;
&lt;br /&gt;
The logic in this function is rather simple:&lt;br /&gt;
* for each rule in the chain&lt;br /&gt;
** for each low level expression in the rule&lt;br /&gt;
*** evaluate the packet against the expression&lt;br /&gt;
** evaluate expression return code (break, continue, drop, accept, jump, goto, etc)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== expressions ==&lt;br /&gt;
&lt;br /&gt;
There are many low expressions that allows us to operate over network packets in different ways. You can think on these low level expressions as assembly-like instructions.&lt;br /&gt;
&lt;br /&gt;
* nft_immediate: loads an immediate value into a register.&lt;br /&gt;
* nft_cmp: compare a given data with data from a given register.&lt;br /&gt;
* nft_payload: set/get arbitrary data from packet headers.&lt;br /&gt;
* nft_bitwise: perform bit-wise math operations over data in a given register.&lt;br /&gt;
* nft_byteorder: perform byte order operations over data in a given register.&lt;br /&gt;
* nft_counter: a basic counter for packet/bytes that gets incremented everything is evaluated for a packet.&lt;br /&gt;
* nft_meta: set/get packet meta information, such as related interfaces, timestamps, etc.&lt;br /&gt;
* nft_lookup: search for data from a given register (key) into a dataset. If the set is a map/dictionary, returns the value for that key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= The userspace components =&lt;br /&gt;
&lt;br /&gt;
There are several important components in the userpsace part of nftables:&lt;br /&gt;
* &#039;&#039;&#039;libmnl&#039;&#039;&#039;: generic low level library used to communicate with the kernel using netlink sockets.&lt;br /&gt;
* &#039;&#039;&#039;libnftnl&#039;&#039;&#039;: low level library that is capable of interacting with the nf_tables subsystem netlink API in the kernel. Is responsible for creating/parsing the nf_tables netlink messages. Uses libmnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;libnftables&#039;&#039;&#039;: high level library that implements the logic to translate from high level statements to netlink objects and the other way around. Uses libnftnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;nft&#039;&#039;&#039;: the command line interface binary. This is what most end users actually use in their systems. It reads user input and calls libnftables under the hood.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the userspace compiles high level statements (rules, etc) into the netlink bytecode that the kernel API understands&lt;br /&gt;
When inspecting the ruleset (i.e, listing it) what it does is the opposite, reconstruct the low level netlink bytecode into high level statements.&lt;br /&gt;
&lt;br /&gt;
== libnftnl ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== libnftables ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= nft: from userspace to the kernel =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= nft: from the kernel to the usespace =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=443</id>
		<title>Portal:DeveloperDocs/nftables internals</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Portal:DeveloperDocs/nftables_internals&amp;diff=443"/>
		<updated>2019-08-02T12:15:28Z</updated>

		<summary type="html">&lt;p&gt;Arturo: create page with basic content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains information for Netfilter developers on how &#039;&#039;&#039;nftables internals&#039;&#039;&#039; work.&lt;br /&gt;
&lt;br /&gt;
= The kernel subsystem =&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;nf_tables&#039;&#039;&#039; kernel subsystem contains 2 key components:&lt;br /&gt;
&lt;br /&gt;
* the netlink API (i.e, control plane API)&lt;br /&gt;
* the nf_tables core (i.e, the data plane engine)&lt;br /&gt;
&lt;br /&gt;
Other components, such as external modules, are also in place and are intermixed with both the API and the core.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the nf_tables subsystem is implementing a virtual machine of low-level expressions that operates on network packets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables netlink API ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_api.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_api.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_api.c [git src]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== nf_tables core ==&lt;br /&gt;
&lt;br /&gt;
The source code is mostly in &#039;&#039;&#039;net/netfilter/nf_tables_core.c&#039;&#039;&#039; [https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_tables_core.c [elixir src]] [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_tables_core.c [git src]]&lt;br /&gt;
&lt;br /&gt;
You can see there one of the most important functions in the core: &#039;&#039;&#039;nft_do_chain()&#039;&#039;&#039;. In a nut shell, this is the function that evaluates network packets against the ruleset.&lt;br /&gt;
&lt;br /&gt;
The logic in this function is rather simple:&lt;br /&gt;
* for each rule in the chain&lt;br /&gt;
** for each low level expression in the rule&lt;br /&gt;
*** evaluate the packet against the expression&lt;br /&gt;
** evaluate expression return code (break, continue, drop, accept, jump, goto, etc)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= The userspace components =&lt;br /&gt;
&lt;br /&gt;
There are several important components in the userpsace part of nftables:&lt;br /&gt;
* &#039;&#039;&#039;libmnl&#039;&#039;&#039;: generic low level library used to communicate with the kernel using netlink sockets.&lt;br /&gt;
* &#039;&#039;&#039;libnftnl&#039;&#039;&#039;: low level library that is capable of interacting with the nf_tables subsystem netlink API in the kernel. Is responsible for creating/parsing the nf_tables netlink messages. Uses libmnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;libnftables&#039;&#039;&#039;: high level library that implements the logic to translate from high level statements to netlink objects and the other way around. Uses libnftnl under the hood.&lt;br /&gt;
* &#039;&#039;&#039;nft&#039;&#039;&#039;: the command line interface binary. This is what most end users actually use in their systems. It reads user input and calls libnftables under the hood.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, the userspace compiles high level statements (rules, etc) into the netlink bytecode that the kernel API understands&lt;br /&gt;
When inspecting the ruleset (i.e, listing it) what it does is the opposite, reconstruct the low level netlink bytecode into high level statements.&lt;br /&gt;
&lt;br /&gt;
== libnftnl ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
== libnftables ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= nft: from userspace to the kernel =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;br /&gt;
&lt;br /&gt;
= nft: from the kernel to the usespace =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO:&#039;&#039;&#039; add info.&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Using_configuration_management_systems&amp;diff=442</id>
		<title>Using configuration management systems</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Using_configuration_management_systems&amp;diff=442"/>
		<updated>2019-07-30T15:41:33Z</updated>

		<summary type="html">&lt;p&gt;Arturo: introduce ansible section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page shows a basic example on how to integrate nftables [[Scripting | scripting]] capabilities with configuration management systems (like puppet, ansible, chef, salt and others).&lt;br /&gt;
&lt;br /&gt;
The basic approach is to have a central point where we deploy nftables, with a ruleset layout that allows other files to be deployed and loaded atomically by nftables.&lt;br /&gt;
Other components (modules, or profiles, or whatever) then deploy specific rules or other configuration as required.&lt;br /&gt;
&lt;br /&gt;
= puppet =&lt;br /&gt;
&lt;br /&gt;
For the sake of the example this page uses puppet as reference, but the same concepts and mechanism could be applied to others.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; if you copy-paste this example make sure you adapt it to your environment. This code below is an example and hasn&#039;t been tested at all.&lt;br /&gt;
&lt;br /&gt;
== a base puppet module ==&lt;br /&gt;
&lt;br /&gt;
A file like named this: &#039;&#039;&#039;modules/nftables/manifest/init.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
class nftables(&lt;br /&gt;
) {&lt;br /&gt;
    # install the package&lt;br /&gt;
    package { &#039;nftables&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;present&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # create a directory to hold the nftables config&lt;br /&gt;
    file { &#039;/etc/nftables/&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;directory&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # deploy the basic configuration file, i.e, the basic nftables ruleset skeleton&lt;br /&gt;
    file { &#039;/etc/nftables/ruleset.nft&#039;:&lt;br /&gt;
        ensure  =&amp;gt; &#039;present&#039;,&lt;br /&gt;
        source  =&amp;gt; &#039;puppet:///modules/nftables/nftables.nft&#039;,&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    # ensure nftables systemd service is running (at boot time, etc)&lt;br /&gt;
    service { &#039;nftables&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;running&#039;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We are installing this file (a file like: &#039;&#039;&#039;modules/nftables/files/nftables.nft&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
#!/usr/sbin/nft -f&lt;br /&gt;
&lt;br /&gt;
flush ruleset&lt;br /&gt;
&lt;br /&gt;
# create the basic ruleset skeleton&lt;br /&gt;
add table inet filter&lt;br /&gt;
add set inet filter allowed_ports { type inet_service ; }&lt;br /&gt;
add chain inet filter input { type filter hook input priority filter ; policy drop ; }&lt;br /&gt;
add rule inet filter input iif lo counter accept&lt;br /&gt;
add rule inet filter input ct state established,related counter accept&lt;br /&gt;
add rule inet filter input tcp dport @allowed_ports accept&lt;br /&gt;
add rule inet filter input counter&lt;br /&gt;
&lt;br /&gt;
# include all the other files that may be deployed by puppet&lt;br /&gt;
include &amp;quot;/etc/nftables/*puppet.nft&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== a module to introduce nftables config ==&lt;br /&gt;
&lt;br /&gt;
This module is responsible for injecting into the system the new nftables config.&lt;br /&gt;
A file named like : &#039;&#039;&#039;modules/nftables/manifest/rule.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
define nftables::rule(&lt;br /&gt;
    String $rule,&lt;br /&gt;
) {&lt;br /&gt;
   require ::nftables&lt;br /&gt;
&lt;br /&gt;
   file { &amp;quot;/etc/nftables/${name}_puppet.nft&amp;quot;:&lt;br /&gt;
       ensure  =&amp;gt; &#039;present&#039;,&lt;br /&gt;
       content =&amp;gt; $rule,&lt;br /&gt;
       notify  =&amp;gt; Service[&#039;nftables&#039;],&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== other modules adding nftables configuration ==&lt;br /&gt;
&lt;br /&gt;
In this example, we have an apache module that creates some additional rules and configuration for nftables.&lt;br /&gt;
&lt;br /&gt;
This is a file named like this: &#039;&#039;&#039;modules/apache/manifest/config.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
class ::apache::config(&lt;br /&gt;
) {&lt;br /&gt;
    package { &#039;apache&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;present&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    nftables::rule { &#039;apache_port_80&#039;:&lt;br /&gt;
        rule =&amp;gt; &#039;add element inet filter allowed_ports { 80 }&#039;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ansible =&lt;br /&gt;
&lt;br /&gt;
Check some examples on how people are using nftables with ansible:&lt;br /&gt;
&lt;br /&gt;
* https://github.com/ipr-cnrs/nftables&lt;br /&gt;
* https://github.com/Frzk/ansible-role-nftables&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Using_configuration_management_systems&amp;diff=441</id>
		<title>Using configuration management systems</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Using_configuration_management_systems&amp;diff=441"/>
		<updated>2019-07-30T15:40:23Z</updated>

		<summary type="html">&lt;p&gt;Arturo: create puppet section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page shows a basic example on how to integrate nftables [[Scripting | scripting]] capabilities with configuration management systems (like puppet, ansible, chef, salt and others).&lt;br /&gt;
&lt;br /&gt;
The basic approach is to have a central point where we deploy nftables, with a ruleset layout that allows other files to be deployed and loaded atomically by nftables.&lt;br /&gt;
Other components (modules, or profiles, or whatever) then deploy specific rules or other configuration as required.&lt;br /&gt;
&lt;br /&gt;
= puppet =&lt;br /&gt;
&lt;br /&gt;
For the sake of the example this page uses puppet as reference, but the same concepts and mechanism could be applied to others.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; if you copy-paste this example make sure you adapt it to your environment. This code below is an example and hasn&#039;t been tested at all.&lt;br /&gt;
&lt;br /&gt;
== a base puppet module ==&lt;br /&gt;
&lt;br /&gt;
A file like named this: &#039;&#039;&#039;modules/nftables/manifest/init.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
class nftables(&lt;br /&gt;
) {&lt;br /&gt;
    # install the package&lt;br /&gt;
    package { &#039;nftables&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;present&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # create a directory to hold the nftables config&lt;br /&gt;
    file { &#039;/etc/nftables/&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;directory&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # deploy the basic configuration file, i.e, the basic nftables ruleset skeleton&lt;br /&gt;
    file { &#039;/etc/nftables/ruleset.nft&#039;:&lt;br /&gt;
        ensure  =&amp;gt; &#039;present&#039;,&lt;br /&gt;
        source  =&amp;gt; &#039;puppet:///modules/nftables/nftables.nft&#039;,&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    # ensure nftables systemd service is running (at boot time, etc)&lt;br /&gt;
    service { &#039;nftables&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;running&#039;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We are installing this file (a file like: &#039;&#039;&#039;modules/nftables/files/nftables.nft&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
#!/usr/sbin/nft -f&lt;br /&gt;
&lt;br /&gt;
flush ruleset&lt;br /&gt;
&lt;br /&gt;
# create the basic ruleset skeleton&lt;br /&gt;
add table inet filter&lt;br /&gt;
add set inet filter allowed_ports { type inet_service ; }&lt;br /&gt;
add chain inet filter input { type filter hook input priority filter ; policy drop ; }&lt;br /&gt;
add rule inet filter input iif lo counter accept&lt;br /&gt;
add rule inet filter input ct state established,related counter accept&lt;br /&gt;
add rule inet filter input tcp dport @allowed_ports accept&lt;br /&gt;
add rule inet filter input counter&lt;br /&gt;
&lt;br /&gt;
# include all the other files that may be deployed by puppet&lt;br /&gt;
include &amp;quot;/etc/nftables/*puppet.nft&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== a module to introduce nftables config ==&lt;br /&gt;
&lt;br /&gt;
This module is responsible for injecting into the system the new nftables config.&lt;br /&gt;
A file named like : &#039;&#039;&#039;modules/nftables/manifest/rule.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
define nftables::rule(&lt;br /&gt;
    String $rule,&lt;br /&gt;
) {&lt;br /&gt;
   require ::nftables&lt;br /&gt;
&lt;br /&gt;
   file { &amp;quot;/etc/nftables/${name}_puppet.nft&amp;quot;:&lt;br /&gt;
       ensure  =&amp;gt; &#039;present&#039;,&lt;br /&gt;
       content =&amp;gt; $rule,&lt;br /&gt;
       notify  =&amp;gt; Service[&#039;nftables&#039;],&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== other modules adding nftables configuration ==&lt;br /&gt;
&lt;br /&gt;
In this example, we have an apache module that creates some additional rules and configuration for nftables.&lt;br /&gt;
&lt;br /&gt;
This is a file named like this: &#039;&#039;&#039;modules/apache/manifest/config.pp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;puppet&amp;quot;&amp;gt;&lt;br /&gt;
class ::apache::config(&lt;br /&gt;
) {&lt;br /&gt;
    package { &#039;apache&#039;:&lt;br /&gt;
        ensure =&amp;gt; &#039;present&#039;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    nftables::rule { &#039;apache_port_80&#039;:&lt;br /&gt;
        rule =&amp;gt; &#039;add element inet filter allowed_ports { 80 }&#039;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Arturo</name></author>
	</entry>
</feed>