From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 11607 invoked from network); 4 Feb 2021 16:47:42 -0000 Received: from bsd.lv (HELO mandoc.bsd.lv) (66.111.2.12) by inbox.vuxu.org with ESMTPUTF8; 4 Feb 2021 16:47:42 -0000 Received: from fantadrom.bsd.lv (localhost [127.0.0.1]) by mandoc.bsd.lv (OpenSMTPD) with ESMTP id bdf8a733 for ; Thu, 4 Feb 2021 11:47:36 -0500 (EST) Received: from fx.arvanta.net (static-213-198-238-194.adsl.eunet.rs [213.198.238.194]) by mandoc.bsd.lv (OpenSMTPD) with ESMTP id b9899b0f for ; Thu, 4 Feb 2021 11:46:40 -0500 (EST) Received: from arya.arvanta.net (arya.arvanta.net [10.5.1.6]) by fx.arvanta.net (Postfix) with ESMTP id D349E17179 for ; Thu, 4 Feb 2021 17:46:37 +0100 (CET) Date: Thu, 4 Feb 2021 17:46:37 +0100 From: Milan =?utf-8?Q?P=2E_Stani=C4=87?= To: discuss@mandoc.bsd.lv Subject: Re: Segmentation fault on trying to view nft.8 man page on Gentoo Message-ID: References: X-Mailinglist: mandoc-discuss Reply-To: discuss@mandoc.bsd.lv MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable In-Reply-To: Hi, On Thu, 2021-02-04 at 11:15, Aisha Tammy wrote: > Hi, > =A0 It seems that the latest release of mandoc (1.14.5) on Gentoo has tro= uble > viewing the nft.8 man page (attached), it crashes with segmentation fault. > I am able to view it on OpenBSD with man -l nft.8, after copying it over. > (I can provide access to a gentoo virtual machine where this bug is > replicable.) About year ago we had such bug on alpine linux and I reported it here: https://marc.info/?l=3Dmandoc-discuss&m=3D158605350702994&w=3D2=20 Bug is fixed with Ingos patch. > I presume this must be a bug in the release version that has since been > fixed. >=20 > Can we get another release which we can use so that we can avoid this bug? >=20 > Thanks a lot, > Aisha >=20 > '\" t > .\" Title: nft > .\" Author: [see the "AUTHORS" section] > .\" Generator: DocBook XSL Stylesheets v1.79.1 > .\" Date: 01/15/2021 > .\" Manual: \ \& > .\" Source: \ \& > .\" Language: English > .\" > .TH "NFT" "8" "01/15/2021" "\ \&" "\ \&" > .\" ----------------------------------------------------------------- > .\" * Define some portability stuff > .\" ----------------------------------------------------------------- > .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > .\" http://bugs.debian.org/507673 > .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html > .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > .ie \n(.g .ds Aq \(aq > .el .ds Aq ' > .\" ----------------------------------------------------------------- > .\" * set default formatting > .\" ----------------------------------------------------------------- > .\" disable hyphenation > .nh > .\" disable justification (adjust text to left margin only) > .ad l > .\" ----------------------------------------------------------------- > .\" * MAIN CONTENT STARTS HERE * > .\" ----------------------------------------------------------------- > .SH "NAME" > nft \- Administration tool of the nftables framework for packet filtering= and classification > .SH "SYNOPSIS" > .sp > .nf > \fBnft\fR [ \fB\-nNscaeSupyjt\fR ] [ \fB\-I\fR \fIdirectory\fR ] [ \fB\-f= \fR \fIfilename\fR | \fB\-i\fR | \fIcmd\fR \&...] > \fBnft\fR \fB\-h\fR > \fBnft\fR \fB\-v\fR > .fi > .SH "DESCRIPTION" > .sp > nft is the command line tool used to set up, maintain and inspect packet = filtering and classification rules in the Linux kernel, in the nftables fra= mework\&. The Linux kernel subsystem is known as nf_tables, and \(oqnf\(cq = stands for Netfilter\&. > .SH "OPTIONS" > .sp > The command accepts several different options which are documented here i= n groups for better understanding of their meaning\&. You can get informati= on about options by running \fBnft \-\-help\fR\&. > .PP > \fBGeneral options:\fR > .PP > \fB\-h\fR, \fB\-\-help\fR > .RS 4 > Show help message and all options\&. > .RE > .PP > \fB\-v\fR, \fB\-\-version\fR > .RS 4 > Show version\&. > .RE > .PP > \fB\-V\fR > .RS 4 > Show long version information, including compile\-time configuration\&. > .RE > .PP > \fBRuleset input handling options that specify to how to load rulesets:\fR > .PP > \fB\-f\fR, \fB\-\-file \fR\fB\fIfilename\fR\fR > .RS 4 > Read input from > \fIfilename\fR\&. If > \fIfilename\fR > is \-, read from stdin\&. > .RE > .PP > \fB\-i\fR, \fB\-\-interactive\fR > .RS 4 > Read input from an interactive readline CLI\&. You can use quit to exit, = or use the EOF marker, normally this is CTRL\-D\&. > .RE > .PP > \fB\-I\fR, \fB\-\-includepath directory\fR > .RS 4 > Add the directory > \fIdirectory\fR > to the list of directories to be searched for included files\&. This opti= on may be specified multiple times\&. > .RE > .PP > \fB\-c\fR, \fB\-\-check\fR > .RS 4 > Check commands validity without actually applying the changes\&. > .RE > .PP > \fBRuleset list output formatting that modify the output of the list rule= set command:\fR > .PP > \fB\-a\fR, \fB\-\-handle\fR > .RS 4 > Show object handles in output\&. > .RE > .PP > \fB\-s\fR, \fB\-\-stateless\fR > .RS 4 > Omit stateful information of rules and stateful objects\&. > .RE > .PP > \fB\-t\fR, \fB\-\-terse\fR > .RS 4 > Omit contents of sets from output\&. > .RE > .PP > \fB\-S\fR, \fB\-\-service\fR > .RS 4 > Translate ports to service names as defined by /etc/services\&. > .RE > .PP > \fB\-N\fR, \fB\-\-reversedns\fR > .RS 4 > Translate IP address to names via reverse DNS lookup\&. This may slow dow= n your listing since it generates network traffic\&. > .RE > .PP > \fB\-u\fR, \fB\-\-guid\fR > .RS 4 > Translate numeric UID/GID to names as defined by /etc/passwd and /etc/gro= up\&. > .RE > .PP > \fB\-n\fR, \fB\-\-numeric\fR > .RS 4 > Print fully numerical output\&. > .RE > .PP > \fB\-y\fR, \fB\-\-numeric\-priority\fR > .RS 4 > Display base chain priority numerically\&. > .RE > .PP > \fB\-p\fR, \fB\-\-numeric\-protocol\fR > .RS 4 > Display layer 4 protocol numerically\&. > .RE > .PP > \fB\-T\fR, \fB\-\-numeric\-time\fR > .RS 4 > Show time, day and hour values in numeric format\&. > .RE > .PP > \fBCommand output formatting:\fR > .PP > \fB\-e\fR, \fB\-\-echo\fR > .RS 4 > When inserting items into the ruleset using > \fBadd\fR, > \fBinsert\fR > or > \fBreplace\fR > commands, print notifications just like > \fBnft monitor\fR\&. > .RE > .PP > \fB\-j\fR, \fB\-\-json\fR > .RS 4 > Format output in JSON\&. See libnftables\-json(5) for a schema descriptio= n\&. > .RE > .PP > \fB\-d\fR, \fB\-\-debug\fR \fIlevel\fR > .RS 4 > Enable debugging output\&. The debug level can be any of > \fBscanner\fR, > \fBparser\fR, > \fBeval\fR, > \fBnetlink\fR, > \fBmnl\fR, > \fBproto\-ctx\fR, > \fBsegtree\fR, > \fBall\fR\&. You can combine more than one by separating by the > \fI,\fR > symbol, for example > \fI\-d eval,mnl\fR\&. > .RE > .SH "INPUT FILE FORMATS" > .SS "LEXICAL CONVENTIONS" > .sp > Input is parsed line\-wise\&. When the last character of a line, just bef= ore the newline character, is a non\-quoted backslash (\e), the next line i= s treated as a continuation\&. Multiple commands on the same line can be se= parated using a semicolon (;)\&. > .sp > A hash sign (#) begins a comment\&. All following characters on the same = line are ignored\&. > .sp > Identifiers begin with an alphabetic character (a\-z,A\-Z), followed zero= or more alphanumeric characters (a\-z,A\-Z,0\-9) and the characters slash = (/), backslash (\e), underscore (_) and dot (\&.)\&. Identifiers using diff= erent characters or clashing with a keyword need to be enclosed in double q= uotes (")\&. > .SS "INCLUDE FILES" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBinclude\fR \fIfilename\fR > .fi > .if n \{\ > .RE > .\} > .sp > Other files can be included by using the \fBinclude\fR statement\&. The d= irectories to be searched for include files can be specified using the \fB\= -I\fR/\fB\-\-includepath\fR option\&. You can override this behaviour eithe= r by prepending \(oq\&./\(cq to your path to force inclusion of files locat= ed in the current working directory (i\&.e\&. relative path) or / for file = location expressed as an absolute path\&. > .sp > If \fB\-I\fR/\fB\-\-includepath\fR is not specified, then nft relies on t= he default directory that is specified at compile time\&. You can retrieve = this default directory via \fB\-h\fR/\fB\-\-help\fR option\&. > .sp > Include statements support the usual shell wildcard symbols (\e*,?,[])\&.= Having no matches for an include statement is not an error, if wildcard sy= mbols are used in the include statement\&. This allows having potentially e= mpty include directories for statements like \fBinclude "/etc/firewall/rule= s/"\fR\&. The wildcard matches are loaded in alphabetical order\&. Files be= ginning with dot (\&.) are not matched by include statements\&. > .SS "SYMBOLIC VARIABLES" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBdefine\fR \fIvariable\fR \fB=3D\fR \fIexpr\fR > \fB$variable\fR > .fi > .if n \{\ > .RE > .\} > .sp > Symbolic variables can be defined using the \fBdefine\fR statement\&. Var= iable references are expressions and can be used initialize other variables= \&. The scope of a definition is the current block and all blocks contained= within\&. > .PP > \fBUsing symbolic variables\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > define int_if1 =3D eth0 > define int_if2 =3D eth1 > define int_ifs =3D { $int_if1, $int_if2 } >=20 > filter input iif $int_ifs accept > .fi > .if n \{\ > .RE > .\} > .sp > .SH "ADDRESS FAMILIES" > .sp > Address families determine the type of packets which are processed\&. For= each address family, the kernel contains so called hooks at specific stage= s of the packet processing paths, which invoke nftables if rules for these = hooks exist\&. > .TS > tab(:); > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > \fBip\fR > T}:T{ > .sp > IPv4 address family\&. > T} > T{ > .sp > \fBip6\fR > T}:T{ > .sp > IPv6 address family\&. > T} > T{ > .sp > \fBinet\fR > T}:T{ > .sp > Internet (IPv4/IPv6) address family\&. > T} > T{ > .sp > \fBarp\fR > T}:T{ > .sp > ARP address family, handling IPv4 ARP packets\&. > T} > T{ > .sp > \fBbridge\fR > T}:T{ > .sp > Bridge address family, handling packets which traverse a bridge device\&. > T} > T{ > .sp > \fBnetdev\fR > T}:T{ > .sp > Netdev address family, handling packets from ingress\&. > T} > .TE > .sp 1 > .sp > All nftables objects exist in address family specific namespaces, therefo= re all identifiers include an address family\&. If an identifier is specifi= ed without an address family, the \fBip\fR family is used by default\&. > .SS "IPV4/IPV6/INET ADDRESS FAMILIES" > .sp > The IPv4/IPv6/Inet address families handle IPv4, IPv6 or both types of pa= ckets\&. They contain five hooks at different packet processing stages in t= he network stack\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&1.\ \&IPv4/IPv6/Inet address family hooks > .TS > allbox tab(:); > ltB ltB. > T{ > Hook > T}:T{ > Description > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > prerouting > T}:T{ > .sp > All packets entering the system are processed by the prerouting hook\&. I= t is invoked before the routing process and is used for early filtering or = changing packet attributes that affect routing\&. > T} > T{ > .sp > input > T}:T{ > .sp > Packets delivered to the local system are processed by the input hook\&. > T} > T{ > .sp > forward > T}:T{ > .sp > Packets forwarded to a different host are processed by the forward hook\&. > T} > T{ > .sp > output > T}:T{ > .sp > Packets sent by local processes are processed by the output hook\&. > T} > T{ > .sp > postrouting > T}:T{ > .sp > All packets leaving the system are processed by the postrouting hook\&. > T} > T{ > .sp > ingress > T}:T{ > .sp > All packets entering the system are processed by this hook\&. It is invok= ed before layer 3 protocol handlers, hence before the prerouting hook, and = it can be used for filtering and policing\&. Ingress is only available for = Inet family (since Linux kernel 5\&.10)\&. > T} > .TE > .sp 1 > .SS "ARP ADDRESS FAMILY" > .sp > The ARP address family handles ARP packets received and sent by the syste= m\&. It is commonly used to mangle ARP packets for clustering\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&2.\ \&ARP address family hooks > .TS > allbox tab(:); > ltB ltB. > T{ > Hook > T}:T{ > Description > T} > .T& > lt lt > lt lt. > T{ > .sp > input > T}:T{ > .sp > Packets delivered to the local system are processed by the input hook\&. > T} > T{ > .sp > output > T}:T{ > .sp > Packets send by the local system are processed by the output hook\&. > T} > .TE > .sp 1 > .SS "BRIDGE ADDRESS FAMILY" > .sp > The bridge address family handles Ethernet packets traversing bridge devi= ces\&. > .sp > The list of supported hooks is identical to IPv4/IPv6/Inet address famili= es above\&. > .SS "NETDEV ADDRESS FAMILY" > .sp > The Netdev address family handles packets from the device ingress path\&.= This family allows you to filter packets of any ethertype such as ARP, VLA= N 802\&.1q, VLAN 802\&.1ad (Q\-in\-Q) as well as IPv4 and IPv6 packets\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&3.\ \&Netdev address family hooks > .TS > allbox tab(:); > ltB ltB. > T{ > Hook > T}:T{ > Description > T} > .T& > lt lt. > T{ > .sp > ingress > T}:T{ > .sp > All packets entering the system are processed by this hook\&. It is invok= ed after the network taps (ie\&. \fBtcpdump\fR), right after \fBtc\fR ingre= ss and before layer 3 protocol handlers, it can be used for early filtering= and policing\&. > T} > .TE > .sp 1 > .SH "RULESET" > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBlist\fR | \fBflush\fR} \fBruleset\fR [\fIfamily\fR] > .fi > .if n \{\ > .RE > .\} > .sp > The \fBruleset\fR keyword is used to identify the whole set of tables, ch= ains, etc\&. currently in place in kernel\&. The following \fBruleset\fR co= mmands exist: > .TS > tab(:); > lt lt > lt lt. > T{ > .sp > \fBlist\fR > T}:T{ > .sp > Print the ruleset in human\-readable format\&. > T} > T{ > .sp > \fBflush\fR > T}:T{ > .sp > Clear the whole ruleset\&. Note that, unlike iptables, this will remove a= ll tables and whatever they contain, effectively leading to an empty rulese= t \- no packet filtering will happen anymore, so the kernel accepts any val= id packet it receives\&. > T} > .TE > .sp 1 > .sp > It is possible to limit \fBlist\fR and \fBflush\fR to a specific address = family only\&. For a list of valid family names, see the section called \(l= qADDRESS FAMILIES\(rq above\&. > .sp > By design, \fBlist ruleset\fR command output may be used as input to \fBn= ft \-f\fR\&. Effectively, this is the nft\-equivalent of \fBiptables\-save\= fR and \fBiptables\-restore\fR\&. > .SH "TABLES" > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBadd\fR | \fBcreate\fR} \fBtable\fR [\fIfamily\fR] \fItable\fR [\fB{ f= lags\fR \fIflags\fR \fB; }\fR] > {\fBdelete\fR | \fBlist\fR | \fBflush\fR} \fBtable\fR [\fIfamily\fR] \fIt= able\fR > \fBlist tables\fR [\fIfamily\fR] > \fBdelete table\fR [\fIfamily\fR] \fBhandle\fR \fIhandle\fR > .fi > .if n \{\ > .RE > .\} > .sp > Tables are containers for chains, sets and stateful objects\&. They are i= dentified by their address family and their name\&. The address family must= be one of \fBip\fR, \fBip6\fR, \fBinet\fR, \fBarp\fR, \fBbridge\fR, \fBnet= dev\fR\&. The \fBinet\fR address family is a dummy family which is used to = create hybrid IPv4/IPv6 tables\&. The \fBmeta expression nfproto\fR keyword= can be used to test which family (ipv4 or ipv6) context the packet is bein= g processed in\&. When no address family is specified, \fBip\fR is used by = default\&. The only difference between add and create is that the former wi= ll not return an error if the specified table already exists while \fBcreat= e\fR will return an error\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&4.\ \&Table flags > .TS > allbox tab(:); > ltB ltB. > T{ > Flag > T}:T{ > Description > T} > .T& > lt lt. > T{ > .sp > dormant > T}:T{ > .sp > table is not evaluated any more (base chains are unregistered)\&. > T} > .TE > .sp 1 > .PP > \fBAdd, change, delete a table\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # start nft in interactive mode > nft \-\-interactive >=20 > # create a new table\&. > create table inet mytable >=20 > # add a new base chain: get input packets > add chain inet mytable myin { type filter hook input priority 0; } >=20 > # add a single counter to the chain > add rule inet mytable myin counter >=20 > # disable the table temporarily \-\- rules are not evaluated anymore > add table inet mytable { flags dormant; } >=20 > # make table active again: > add table inet mytable > .fi > .if n \{\ > .RE > .\} > .sp > .TS > tab(:); > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > \fBadd\fR > T}:T{ > .sp > Add a new table for the given family with the given name\&. > T} > T{ > .sp > \fBdelete\fR > T}:T{ > .sp > Delete the specified table\&. > T} > T{ > .sp > \fBlist\fR > T}:T{ > .sp > List all chains and rules of the specified table\&. > T} > T{ > .sp > \fBflush\fR > T}:T{ > .sp > Flush all chains and rules of the specified table\&. > T} > .TE > .sp 1 > .SH "CHAINS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBadd\fR | \fBcreate\fR} \fBchain\fR [\fIfamily\fR] \fItable\fR \fIchai= n\fR [\fB{ type\fR \fItype\fR \fBhook\fR \fIhook\fR [\fBdevice\fR \fIdevice= \fR] \fBpriority\fR \fIpriority\fR \fB;\fR [\fBpolicy\fR \fIpolicy\fR \fB;\= fR] \fB}\fR] > {\fBdelete\fR | \fBlist\fR | \fBflush\fR} \fBchain\fR [\fIfamily\fR] \fIt= able\fR \fIchain\fR > \fBlist chains\fR [\fIfamily\fR] > \fBdelete chain\fR [\fIfamily\fR] \fItable\fR \fBhandle\fR \fIhandle\fR > \fBrename chain\fR [\fIfamily\fR] \fItable\fR \fIchain\fR \fInewname\fR > .fi > .if n \{\ > .RE > .\} > .sp > Chains are containers for rules\&. They exist in two kinds, base chains a= nd regular chains\&. A base chain is an entry point for packets from the ne= tworking stack, a regular chain may be used as jump target and is used for = better rule organization\&. > .TS > tab(:); > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > \fBadd\fR > T}:T{ > .sp > Add a new chain in the specified table\&. When a hook and priority value = are specified, the chain is created as a base chain and hooked up to the ne= tworking stack\&. > T} > T{ > .sp > \fBcreate\fR > T}:T{ > .sp > Similar to the \fBadd\fR command, but returns an error if the chain alrea= dy exists\&. > T} > T{ > .sp > \fBdelete\fR > T}:T{ > .sp > Delete the specified chain\&. The chain must not contain any rules or be = used as jump target\&. > T} > T{ > .sp > \fBrename\fR > T}:T{ > .sp > Rename the specified chain\&. > T} > T{ > .sp > \fBlist\fR > T}:T{ > .sp > List all rules of the specified chain\&. > T} > T{ > .sp > \fBflush\fR > T}:T{ > .sp > Flush all rules of the specified chain\&. > T} > .TE > .sp 1 > .sp > For base chains, \fBtype\fR, \fBhook\fR and \fBpriority\fR parameters are= mandatory\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&5.\ \&Supported chain types > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Type > T}:T{ > Families > T}:T{ > Hooks > T}:T{ > Description > T} > .T& > lt lt lt lt > lt lt lt lt > lt lt lt lt. > T{ > .sp > filter > T}:T{ > .sp > all > T}:T{ > .sp > all > T}:T{ > .sp > Standard chain type to use in doubt\&. > T} > T{ > .sp > nat > T}:T{ > .sp > ip, ip6, inet > T}:T{ > .sp > prerouting, input, output, postrouting > T}:T{ > .sp > Chains of this type perform Native Address Translation based on conntrack= entries\&. Only the first packet of a connection actually traverses this c= hain \- its rules usually define details of the created conntrack entry (NA= T statements for instance)\&. > T} > T{ > .sp > route > T}:T{ > .sp > ip, ip6 > T}:T{ > .sp > output > T}:T{ > .sp > If a packet has traversed a chain of this type and is about to be accepte= d, a new route lookup is performed if relevant parts of the IP header have = changed\&. This allows to e\&.g\&. implement policy routing selectors in nf= tables\&. > T} > .TE > .sp 1 > .sp > Apart from the special cases illustrated above (e\&.g\&. \fBnat\fR type n= ot supporting \fBforward\fR hook or \fBroute\fR type only supporting \fBout= put\fR hook), there are three further quirks worth noticing: > .sp > .RS 4 > .ie n \{\ > \h'-04'\(bu\h'+03'\c > .\} > .el \{\ > .sp -1 > .IP \(bu 2.3 > .\} > The netdev family supports merely a single combination, namely > \fBfilter\fR > type and > \fBingress\fR > hook\&. Base chains in this family also require the > \fBdevice\fR > parameter to be present since they exist per incoming interface only\&. > .RE > .sp > .RS 4 > .ie n \{\ > \h'-04'\(bu\h'+03'\c > .\} > .el \{\ > .sp -1 > .IP \(bu 2.3 > .\} > The arp family supports only the > \fBinput\fR > and > \fBoutput\fR > hooks, both in chains of type > \fBfilter\fR\&. > .RE > .sp > .RS 4 > .ie n \{\ > \h'-04'\(bu\h'+03'\c > .\} > .el \{\ > .sp -1 > .IP \(bu 2.3 > .\} > The inet family also supports the > \fBingress\fR > hook (since Linux kernel 5\&.10), to filter IPv4 and IPv6 packet at the s= ame location as the netdev > \fBingress\fR > hook\&. This inet hook allows you to share sets and maps between the usual > \fBprerouting\fR, > \fBinput\fR, > \fBforward\fR, > \fBoutput\fR, > \fBpostrouting\fR > and this > \fBingress\fR > hook\&. > .RE > .sp > The \fBpriority\fR parameter accepts a signed integer value or a standard= priority name which specifies the order in which chains with same \fBhook\= fR value are traversed\&. The ordering is ascending, i\&.e\&. lower priorit= y values have precedence over higher ones\&. > .sp > Standard priority values can be replaced with easily memorizable names\&.= Not all names make sense in every family with every hook (see the compatib= ility matrices below) but their numerical value can still be used for prior= itizing chains\&. > .sp > These names and values are defined and made available based on what prior= ities are used by xtables when registering their default chains\&. > .sp > Most of the families use the same values, but bridge uses different ones = =66rom the others\&. See the following tables that describe the values and = compatibility\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&6.\ \&Standard priority names, family and hook compatibility = matrix > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Value > T}:T{ > Families > T}:T{ > Hooks > T} > .T& > lt lt lt lt > lt lt lt lt > lt lt lt lt > lt lt lt lt > lt lt lt lt > lt lt lt lt. > T{ > .sp > raw > T}:T{ > .sp > \-300 > T}:T{ > .sp > ip, ip6, inet > T}:T{ > .sp > all > T} > T{ > .sp > mangle > T}:T{ > .sp > \-150 > T}:T{ > .sp > ip, ip6, inet > T}:T{ > .sp > all > T} > T{ > .sp > dstnat > T}:T{ > .sp > \-100 > T}:T{ > .sp > ip, ip6, inet > T}:T{ > .sp > prerouting > T} > T{ > .sp > filter > T}:T{ > .sp > 0 > T}:T{ > .sp > ip, ip6, inet, arp, netdev > T}:T{ > .sp > all > T} > T{ > .sp > security > T}:T{ > .sp > 50 > T}:T{ > .sp > ip, ip6, inet > T}:T{ > .sp > all > T} > T{ > .sp > srcnat > T}:T{ > .sp > 100 > T}:T{ > .sp > ip, ip6, inet > T}:T{ > .sp > postrouting > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&7.\ \&Standard priority names and hook compatibility for the = bridge family > .TS > allbox tab(:); > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > Name > T}:T{ > .sp > Value > T}:T{ > .sp > Hooks > T} > T{ > .sp > dstnat > T}:T{ > .sp > \-300 > T}:T{ > .sp > prerouting > T} > T{ > .sp > filter > T}:T{ > .sp > \-200 > T}:T{ > .sp > all > T} > T{ > .sp > out > T}:T{ > .sp > 100 > T}:T{ > .sp > output > T} > T{ > .sp > srcnat > T}:T{ > .sp > 300 > T}:T{ > .sp > postrouting > T} > .TE > .sp 1 > .sp > Basic arithmetic expressions (addition and subtraction) can also be achie= ved with these standard names to ease relative prioritizing, e\&.g\&. \fBma= ngle \- 5\fR stands for \fB\-155\fR\&. Values will also be printed like thi= s until the value is not further than 10 form the standard value\&. > .sp > Base chains also allow to set the chain\(cqs \fBpolicy\fR, i\&.e\&. what = happens to packets not explicitly accepted or refused in contained rules\&.= Supported policy values are \fBaccept\fR (which is the default) or \fBdrop= \fR\&. > .SH "RULES" > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBadd\fR | \fBinsert\fR} \fBrule\fR [\fIfamily\fR] \fItable\fR \fIchain= \fR [\fBhandle\fR \fIhandle\fR | \fBindex\fR \fIindex\fR] \fIstatement\fR \= &... [\fBcomment\fR \fIcomment\fR] > \fBreplace rule\fR [\fIfamily\fR] \fItable\fR \fIchain\fR \fBhandle\fR \f= Ihandle\fR \fIstatement\fR \&... [\fBcomment\fR \fIcomment\fR] > \fBdelete rule\fR [\fIfamily\fR] \fItable\fR \fIchain\fR \fBhandle\fR \fI= handle\fR > .fi > .if n \{\ > .RE > .\} > .sp > Rules are added to chains in the given table\&. If the family is not spec= ified, the ip family is used\&. Rules are constructed from two kinds of com= ponents according to a set of grammatical rules: expressions and statements= \&. > .sp > The add and insert commands support an optional location specifier, which= is either a \fIhandle\fR or the \fIindex\fR (starting at zero) of an exist= ing rule\&. Internally, rule locations are always identified by \fIhandle\f= R and the translation from \fIindex\fR happens in userspace\&. This has two= potential implications in case a concurrent ruleset change happens after t= he translation was done: The effective rule index might change if a rule wa= s inserted or deleted before the referred one\&. If the referred rule was d= eleted, the command is rejected by the kernel just as if an invalid \fIhand= le\fR was given\&. > .sp > A \fIcomment\fR is a single word or a double\-quoted (") multi\-word stri= ng which can be used to make notes regarding the actual rule\&. \fBNote:\fR= If you use bash for adding rules, you have to escape the quotation marks, = e\&.g\&. \e"enable ssh for servers\e"\&. > .TS > tab(:); > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > \fBadd\fR > T}:T{ > .sp > Add a new rule described by the list of statements\&. The rule is appende= d to the given chain unless a location is specified, in which case the rule= is inserted after the specified rule\&. > T} > T{ > .sp > \fBinsert\fR > T}:T{ > .sp > Same as \fBadd\fR except the rule is inserted at the beginning of the cha= in or before the specified rule\&. > T} > T{ > .sp > \fBreplace\fR > T}:T{ > .sp > Similar to \fBadd\fR, but the rule replaces the specified rule\&. > T} > T{ > .sp > \fBdelete\fR > T}:T{ > .sp > Delete the specified rule\&. > T} > .TE > .sp 1 > .PP > \fBadd a rule to ip table output chain\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > nft add rule filter output ip daddr 192\&.168\&.0\&.0/24 accept # \*(Aqip= filter\*(Aq is assumed > # same command, slightly more verbose > nft add rule ip filter output ip daddr 192\&.168\&.0\&.0/24 accept > .fi > .if n \{\ > .RE > .\} > .PP > \fBdelete rule from inet table\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # nft \-a list ruleset > table inet filter { > chain input { > type filter hook input priority 0; policy accept; > ct state established,related accept # handle 4 > ip saddr 10\&.1\&.1\&.1 tcp dport ssh accept # handle 5 > \&.\&.\&. > # delete the rule with handle 5 > # nft delete rule inet filter input handle 5 > .fi > .if n \{\ > .RE > .\} > .sp > .SH "SETS" > .sp > nftables offers two kinds of set concepts\&. Anonymous sets are sets that= have no specific name\&. The set members are enclosed in curly braces, wit= h commas to separate elements when creating the rule the set is used in\&. = Once that rule is removed, the set is removed as well\&. They cannot be upd= ated, i\&.e\&. once an anonymous set is declared it cannot be changed anymo= re except by removing/altering the rule that uses the anonymous set\&. > .PP > \fBUsing anonymous sets to accept particular subnets and ports\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > nft add rule filter input ip saddr { 10\&.0\&.0\&.0/8, 192\&.168\&.0\&.0/= 16 } tcp dport { 22, 443 } accept > .fi > .if n \{\ > .RE > .\} > .sp > Named sets are sets that need to be defined first before they can be refe= renced in rules\&. Unlike anonymous sets, elements can be added to or remov= ed from a named set at any time\&. Sets are referenced from rules using an = @ prefixed to the sets name\&. > .PP > \fBUsing named sets to accept addresses and ports\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > nft add rule filter input ip saddr @allowed_hosts tcp dport @allowed_port= s accept > .fi > .if n \{\ > .RE > .\} > .sp > The sets allowed_hosts and allowed_ports need to be created first\&. The = next section describes nft set syntax in more detail\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBadd set\fR [\fIfamily\fR] \fItable\fR \fIset\fR \fB{ type\fR \fItype\f= R | \fBtypeof\fR \fIexpression\fR \fB;\fR [\fBflags\fR \fIflags\fR \fB;\fR]= [\fBtimeout\fR \fItimeout\fR \fB;\fR] [\fBgc\-interval\fR \fIgc\-interval\= fR \fB;\fR] [\fBelements =3D {\fR \fIelement\fR[\fB,\fR \&...] \fB} ;\fR] [= \fBsize\fR \fIsize\fR \fB;\fR] [\fBpolicy\fR \fIpolicy\fR \fB;\fR] [\fBauto= \-merge ;\fR] \fB}\fR > {\fBdelete\fR | \fBlist\fR | \fBflush\fR} \fBset\fR [\fIfamily\fR] \fItab= le\fR \fIset\fR > \fBlist sets\fR [\fIfamily\fR] > \fBdelete set\fR [\fIfamily\fR] \fItable\fR \fBhandle\fR \fIhandle\fR > {\fBadd\fR | \fBdelete\fR} \fBelement\fR [\fIfamily\fR] \fItable\fR \fIse= t\fR \fB{\fR \fIelement\fR[\fB,\fR \&...] \fB}\fR > .fi > .if n \{\ > .RE > .\} > .sp > Sets are element containers of a user\-defined data type, they are unique= ly identified by a user\-defined name and attached to tables\&. Their behav= iour can be tuned with the flags that can be specified at set creation time= \&. > .TS > tab(:); > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > \fBadd\fR > T}:T{ > .sp > Add a new set in the specified table\&. See the Set specification table b= elow for more information about how to specify a sets properties\&. > T} > T{ > .sp > \fBdelete\fR > T}:T{ > .sp > Delete the specified set\&. > T} > T{ > .sp > \fBlist\fR > T}:T{ > .sp > Display the elements in the specified set\&. > T} > T{ > .sp > \fBflush\fR > T}:T{ > .sp > Remove all elements from the specified set\&. > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&8.\ \&Set specifications > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > type > T}:T{ > .sp > data type of set elements > T}:T{ > .sp > string: ipv4_addr, ipv6_addr, ether_addr, inet_proto, inet_service, mark > T} > T{ > .sp > typeof > T}:T{ > .sp > data type of set element > T}:T{ > .sp > expression to derive the data type from > T} > T{ > .sp > flags > T}:T{ > .sp > set flags > T}:T{ > .sp > string: constant, dynamic, interval, timeout > T} > T{ > .sp > timeout > T}:T{ > .sp > time an element stays in the set, mandatory if set is added to from the p= acket path (ruleset)\&. > T}:T{ > .sp > string, decimal followed by unit\&. Units are: d, h, m, s > T} > T{ > .sp > gc\-interval > T}:T{ > .sp > garbage collection interval, only available when timeout or flag timeout = are active > T}:T{ > .sp > string, decimal followed by unit\&. Units are: d, h, m, s > T} > T{ > .sp > elements > T}:T{ > .sp > elements contained by the set > T}:T{ > .sp > set data type > T} > T{ > .sp > size > T}:T{ > .sp > maximum number of elements in the set, mandatory if set is added to from = the packet path (ruleset)\&. > T}:T{ > .sp > unsigned integer (64 bit) > T} > T{ > .sp > policy > T}:T{ > .sp > set policy > T}:T{ > .sp > string: performance [default], memory > T} > T{ > .sp > auto\-merge > T}:T{ > .sp > automatic merge of adjacent/overlapping set elements (only for interval s= ets) > T}:T{ > .sp > T} > .TE > .sp 1 > .SH "MAPS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBadd map\fR [\fIfamily\fR] \fItable\fR \fImap\fR \fB{ type\fR \fItype\f= R | \fBtypeof\fR \fIexpression\fR [\fBflags\fR \fIflags\fR \fB;\fR] [\fBele= ments =3D {\fR \fIelement\fR[\fB,\fR \&...] \fB} ;\fR] [\fBsize\fR \fIsize\= fR \fB;\fR] [\fBpolicy\fR \fIpolicy\fR \fB;\fR] \fB}\fR > {\fBdelete\fR | \fBlist\fR | \fBflush\fR} \fBmap\fR [\fIfamily\fR] \fItab= le\fR \fImap\fR > \fBlist maps\fR [\fIfamily\fR] > .fi > .if n \{\ > .RE > .\} > .sp > Maps store data based on some specific key used as input\&. They are uniq= uely identified by a user\-defined name and attached to tables\&. > .TS > tab(:); > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > \fBadd\fR > T}:T{ > .sp > Add a new map in the specified table\&. > T} > T{ > .sp > \fBdelete\fR > T}:T{ > .sp > Delete the specified map\&. > T} > T{ > .sp > \fBlist\fR > T}:T{ > .sp > Display the elements in the specified map\&. > T} > T{ > .sp > \fBflush\fR > T}:T{ > .sp > Remove all elements from the specified map\&. > T} > T{ > .sp > \fBadd element\fR > T}:T{ > .sp > Comma\-separated list of elements to add into the specified map\&. > T} > T{ > .sp > \fBdelete element\fR > T}:T{ > .sp > Comma\-separated list of element keys to delete from the specified map\&. > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&9.\ \&Map specifications > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > type > T}:T{ > .sp > data type of map elements > T}:T{ > .sp > string: ipv4_addr, ipv6_addr, ether_addr, inet_proto, inet_service, mark,= counter, quota\&. Counter and quota can\(cqt be used as keys > T} > T{ > .sp > typeof > T}:T{ > .sp > data type of set element > T}:T{ > .sp > expression to derive the data type from > T} > T{ > .sp > flags > T}:T{ > .sp > map flags > T}:T{ > .sp > string: constant, interval > T} > T{ > .sp > elements > T}:T{ > .sp > elements contained by the map > T}:T{ > .sp > map data type > T} > T{ > .sp > size > T}:T{ > .sp > maximum number of elements in the map > T}:T{ > .sp > unsigned integer (64 bit) > T} > T{ > .sp > policy > T}:T{ > .sp > map policy > T}:T{ > .sp > string: performance [default], memory > T} > .TE > .sp 1 > .SH "ELEMENTS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBadd\fR | \fBcreate\fR | \fBdelete\fR | \fBget\fR } \fBelement\fR [\fI= family\fR] \fItable\fR \fIset\fR \fB{\fR \fIELEMENT\fR[\fB,\fR \&...] \fB}\= fR >=20 > \fIELEMENT\fR :=3D \fIkey_expression\fR \fIOPTIONS\fR [\fB:\fR \fIvalue_e= xpression\fR] > \fIOPTIONS\fR :=3D [\fBtimeout\fR \fITIMESPEC\fR] [\fBexpires\fR \fITIMES= PEC\fR] [\fBcomment\fR \fIstring\fR] > \fITIMESPEC\fR :=3D [\fInum\fR\fBd\fR][\fInum\fR\fBh\fR][\fInum\fR\fBm\fR= ][\fInum\fR[\fBs\fR]] > .fi > .if n \{\ > .RE > .\} > .sp > Element\-related commands allow to change contents of named sets and maps= \&. \fIkey_expression\fR is typically a value matching the set type\&. \fIv= alue_expression\fR is not allowed in sets but mandatory when adding to maps= , where it matches the data part in it\(cqs type definition\&. When deletin= g from maps, it may be specified but is optional as \fIkey_expression\fR un= iquely identifies the element\&. > .sp > \fBcreate\fR command is similar to \fBadd\fR with the exception that none= of the listed elements may already exist\&. > .sp > \fBget\fR command is useful to check if an element is contained in a set = which may be non\-trivial in very large and/or interval sets\&. In the latt= er case, the containing interval is returned instead of just the element it= self\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&10.\ \&Element options > .TS > allbox tab(:); > ltB ltB. > T{ > Option > T}:T{ > Description > T} > .T& > lt lt > lt lt > lt lt. > T{ > .sp > timeout > T}:T{ > .sp > timeout value for sets/maps with flag \fBtimeout\fR > T} > T{ > .sp > expires > T}:T{ > .sp > the time until given element expires, useful for ruleset replication only > T} > T{ > .sp > comment > T}:T{ > .sp > per element comment field > T} > .TE > .sp 1 > .SH "FLOWTABLES" > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBadd\fR | \fBcreate\fR} \fBflowtable\fR [\fIfamily\fR] \fItable\fR \fI= flowtable\fR \fB{ hook\fR \fIhook\fR \fBpriority\fR \fIpriority\fR \fB; dev= ices =3D {\fR \fIdevice\fR[\fB,\fR \&...] \fB} ; }\fR > \fBlist flowtables\fR [\fIfamily\fR] > {\fBdelete\fR | \fBlist\fR} \fBflowtable\fR [\fIfamily\fR] \fItable\fR \f= Iflowtable\fR > \fBdelete\fR \fBflowtable\fR [\fIfamily\fR] \fItable\fR \fBhandle\fR \fIh= andle\fR > .fi > .if n \{\ > .RE > .\} > .sp > Flowtables allow you to accelerate packet forwarding in software\&. Flowt= ables entries are represented through a tuple that is composed of the input= interface, source and destination address, source and destination port; an= d layer 3/4 protocols\&. Each entry also caches the destination interface a= nd the gateway address \- to update the destination link\-layer address \- = to forward packets\&. The ttl and hoplimit fields are also decremented\&. H= ence, flowtables provides an alternative path that allow packets to bypass = the classic forwarding path\&. Flowtables reside in the ingress hook that i= s located before the prerouting hook\&. You can select which flows you want= to offload through the flow expression from the forward chain\&. Flowtable= s are identified by their address family and their name\&. The address fami= ly must be one of ip, ip6, or inet\&. The inet address family is a dummy fa= mily which is used to create hybrid IPv4/IPv6 tables\&. When no address fam= ily is specified, ip is used by default\&. > .sp > The \fBpriority\fR can be a signed integer or \fBfilter\fR which stands f= or 0\&. Addition and subtraction can be used to set relative priority, e\&.= g\&. filter + 5 equals to 5\&. > .TS > tab(:); > lt lt > lt lt > lt lt. > T{ > .sp > \fBadd\fR > T}:T{ > .sp > Add a new flowtable for the given family with the given name\&. > T} > T{ > .sp > \fBdelete\fR > T}:T{ > .sp > Delete the specified flowtable\&. > T} > T{ > .sp > \fBlist\fR > T}:T{ > .sp > List all flowtables\&. > T} > .TE > .sp 1 > .SH "STATEFUL OBJECTS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBadd\fR | \fBdelete\fR | \fBlist\fR | \fBreset\fR} \fItype\fR [\fIfami= ly\fR] \fItable\fR \fIobject\fR > \fBdelete\fR \fItype\fR [\fIfamily\fR] \fItable\fR \fBhandle\fR \fIhandle= \fR > \fBlist counters\fR [\fIfamily\fR] > \fBlist quotas\fR [\fIfamily\fR] > .fi > .if n \{\ > .RE > .\} > .sp > Stateful objects are attached to tables and are identified by an unique n= ame\&. They group stateful information from rules, to reference them in rul= es the keywords "type name" are used e\&.g\&. "counter name"\&. > .TS > tab(:); > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > \fBadd\fR > T}:T{ > .sp > Add a new stateful object in the specified table\&. > T} > T{ > .sp > \fBdelete\fR > T}:T{ > .sp > Delete the specified object\&. > T} > T{ > .sp > \fBlist\fR > T}:T{ > .sp > Display stateful information the object holds\&. > T} > T{ > .sp > \fBreset\fR > T}:T{ > .sp > List\-and\-reset stateful object\&. > T} > .TE > .sp 1 > .SS "CT HELPER" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBct helper\fR \fIhelper\fR \fB{ type\fR \fItype\fR \fBprotocol\fR \fIpr= otocol\fR \fB;\fR [\fBl3proto\fR \fIfamily\fR \fB;\fR] \fB}\fR > .fi > .if n \{\ > .RE > .\} > .sp > Ct helper is used to define connection tracking helpers that can then be = used in combination with the \fBct helper set\fR statement\&. \fItype\fR an= d \fIprotocol\fR are mandatory, l3proto is derived from the table family by= default, i\&.e\&. in the inet table the kernel will try to load both the i= pv4 and ipv6 helper backends, if they are supported by the kernel\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&11.\ \&conntrack helper specifications > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > type > T}:T{ > .sp > name of helper type > T}:T{ > .sp > quoted string (e\&.g\&. "ftp") > T} > T{ > .sp > protocol > T}:T{ > .sp > layer 4 protocol of the helper > T}:T{ > .sp > string (e\&.g\&. ip) > T} > T{ > .sp > l3proto > T}:T{ > .sp > layer 3 protocol of the helper > T}:T{ > .sp > address family (e\&.g\&. ip) > T} > .TE > .sp 1 > .PP > \fBdefining and assigning ftp helper\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > Unlike iptables, helper assignment needs to be performed after the conntr= ack > lookup has completed, for example with the default 0 hook priority\&. >=20 > table inet myhelpers { > ct helper ftp\-standard { > type "ftp" protocol tcp > } > chain prerouting { > type filter hook prerouting priority 0; > tcp dport 21 ct helper set "ftp\-standard" > } > } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "CT TIMEOUT" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBct timeout\fR \fIname\fR \fB{ protocol\fR \fIprotocol\fR \fB; policy = =3D {\fR \fIstate\fR\fB:\fR \fIvalue\fR [\fB,\fR \&...] \fB} ;\fR [\fBl3pro= to\fR \fIfamily\fR \fB;\fR] \fB}\fR > .fi > .if n \{\ > .RE > .\} > .sp > Ct timeout is used to update connection tracking timeout values\&.Timeout= policies are assigned with the \fBct timeout set\fR statement\&. \fIprotoc= ol\fR and \fIpolicy\fR are mandatory, l3proto is derived from the table fam= ily by default\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&12.\ \&conntrack timeout specifications > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > protocol > T}:T{ > .sp > layer 4 protocol of the timeout object > T}:T{ > .sp > string (e\&.g\&. ip) > T} > T{ > .sp > state > T}:T{ > .sp > connection state name > T}:T{ > .sp > string (e\&.g\&. "established") > T} > T{ > .sp > value > T}:T{ > .sp > timeout value for connection state > T}:T{ > .sp > unsigned integer > T} > T{ > .sp > l3proto > T}:T{ > .sp > layer 3 protocol of the timeout object > T}:T{ > .sp > address family (e\&.g\&. ip) > T} > .TE > .sp 1 > .PP > \fBdefining and assigning ct timeout policy\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > table ip filter { > ct timeout customtimeout { > protocol tcp; > l3proto ip > policy =3D { established: 120, close: 20 } > } >=20 > chain output { > type filter hook output priority filter; policy accept; > ct timeout set "customtimeout" > } > } > .fi > .if n \{\ > .RE > .\} > .PP > \fBtesting the updated timeout policy\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > % conntrack \-E >=20 > It should display: >=20 > [UPDATE] tcp 6 120 ESTABLISHED src=3D172\&.16\&.19\&.128 dst=3D172\&= =2E16\&.19\&.1 > sport=3D22 dport=3D41360 [UNREPLIED] src=3D172\&.16\&.19\&.1 dst=3D172\&.= 16\&.19\&.128 > sport=3D41360 dport=3D22 > .fi > .if n \{\ > .RE > .\} > .sp > .SS "CT EXPECTATION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBct expectation\fR \fIname\fR \fB{ protocol\fR \fIprotocol\fR \fB; dpor= t\fR \fIdport\fR \fB; timeout\fR \fItimeout\fR \fB; size\fR \fIsize\fR \fB;= [*l3proto\fR \fIfamily\fR \fB;\fR] \fB}\fR > .fi > .if n \{\ > .RE > .\} > .sp > Ct expectation is used to create connection expectations\&. Expectations = are assigned with the \fBct expectation set\fR statement\&. \fIprotocol\fR,= \fIdport\fR, \fItimeout\fR and \fIsize\fR are mandatory, l3proto is derive= d from the table family by default\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&13.\ \&conntrack expectation specifications > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > protocol > T}:T{ > .sp > layer 4 protocol of the expectation object > T}:T{ > .sp > string (e\&.g\&. ip) > T} > T{ > .sp > dport > T}:T{ > .sp > destination port of expected connection > T}:T{ > .sp > unsigned integer > T} > T{ > .sp > timeout > T}:T{ > .sp > timeout value for expectation > T}:T{ > .sp > unsigned integer > T} > T{ > .sp > size > T}:T{ > .sp > size value for expectation > T}:T{ > .sp > unsigned integer > T} > T{ > .sp > l3proto > T}:T{ > .sp > layer 3 protocol of the expectation object > T}:T{ > .sp > address family (e\&.g\&. ip) > T} > .TE > .sp 1 > .PP > \fBdefining and assigning ct expectation policy\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > table ip filter { > ct expectation expect { > protocol udp > dport 9876 > timeout 2m > size 8 > l3proto ip > } >=20 > chain input { > type filter hook input priority filter; policy accept; > ct expectation set "expect" > } > } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "COUNTER" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBcounter\fR [\fIpackets bytes\fR] > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&14.\ \&Counter specifications > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt. > T{ > .sp > packets > T}:T{ > .sp > initial count of packets > T}:T{ > .sp > unsigned integer (64 bit) > T} > T{ > .sp > bytes > T}:T{ > .sp > initial count of bytes > T}:T{ > .sp > unsigned integer (64 bit) > T} > .TE > .sp 1 > .SS "QUOTA" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBquota\fR [\fBover\fR | \fBuntil\fR] [\fIused\fR] > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&15.\ \&Quota specifications > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt. > T{ > .sp > quota > T}:T{ > .sp > quota limit, used as the quota name > T}:T{ > .sp > Two arguments, unsigned integer (64 bit) and string: bytes, kbytes, mbyte= s\&. "over" and "until" go before these arguments > T} > T{ > .sp > used > T}:T{ > .sp > initial value of used quota > T}:T{ > .sp > Two arguments, unsigned integer (64 bit) and string: bytes, kbytes, mbytes > T} > .TE > .sp 1 > .SH "EXPRESSIONS" > .sp > Expressions represent values, either constants like network addresses, po= rt numbers, etc\&., or data gathered from the packet during ruleset evaluat= ion\&. Expressions can be combined using binary, logical, relational and ot= her types of expressions to form complex or relational (match) expressions\= &. They are also used as arguments to certain types of operations, like NAT= , packet marking etc\&. > .sp > Each expression has a data type, which determines the size, parsing and r= epresentation of symbolic values and type compatibility with other expressi= ons\&. > .SS "DESCRIBE COMMAND" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBdescribe\fR \fIexpression\fR | \fIdata type\fR > .fi > .if n \{\ > .RE > .\} > .sp > The \fBdescribe\fR command shows information about the type of an express= ion and its data type\&. A data type may also be given, in which nft will d= isplay more information about the type\&. > .PP > \fBThe describe command\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > $ nft describe tcp flags > payload expression, datatype tcp_flag (TCP flag) (basetype bitmask, integ= er), 8 bits >=20 > predefined symbolic constants: > fin 0x01 > syn 0x02 > rst 0x04 > psh 0x08 > ack 0x10 > urg 0x20 > ecn 0x40 > cwr 0x80 > .fi > .if n \{\ > .RE > .\} > .sp > .SH "DATA TYPES" > .sp > Data types determine the size, parsing and representation of symbolic val= ues and type compatibility of expressions\&. A number of global data types = exist, in addition some expression types define further data types specific= to the expression type\&. Most data types have a fixed size, some however = may have a dynamic size, f\&.i\&. the string type\&. Some types also have p= redefined symbolic constants\&. Those can be listed using the nft \fBdescri= be\fR command: > .sp > .if n \{\ > .RS 4 > .\} > .nf > $ nft describe ct_state > datatype ct_state (conntrack state) (basetype bitmask, integer), 32 bits >=20 > pre\-defined symbolic constants (in hexadecimal): > invalid 0x00000001 > new \&.\&.\&. > .fi > .if n \{\ > .RE > .\} > .sp > Types may be derived from lower order types, f\&.i\&. the IPv4 address ty= pe is derived from the integer type, meaning an IPv4 address can also be sp= ecified as an integer value\&. > .sp > In certain contexts (set and map definitions), it is necessary to explici= tly specify a data type\&. Each type has a name which is used for this\&. > .SS "INTEGER TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > Integer > T}:T{ > .sp > integer > T}:T{ > .sp > variable > T}:T{ > .sp > \- > T} > .TE > .sp 1 > .sp > The integer type is used for numeric values\&. It may be specified as a d= ecimal, hexadecimal or octal number\&. The integer type does not have a fix= ed size, its size is determined by the expression for which it is used\&. > .SS "BITMASK TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > Bitmask > T}:T{ > .sp > bitmask > T}:T{ > .sp > variable > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The bitmask type (\fBbitmask\fR) is used for bitmasks\&. > .SS "STRING TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > String > T}:T{ > .sp > string > T}:T{ > .sp > variable > T}:T{ > .sp > \- > T} > .TE > .sp 1 > .sp > The string type is used for character strings\&. A string begins with an = alphabetic character (a\-zA\-Z) followed by zero or more alphanumeric chara= cters or the characters /, \-, _ and \&.\&. In addition, anything enclosed = in double quotes (") is recognized as a string\&. > .PP > \fBString specification\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # Interface name > filter input iifname eth0 >=20 > # Weird interface name > filter input iifname "(eth0)" > .fi > .if n \{\ > .RE > .\} > .sp > .SS "LINK LAYER ADDRESS TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > Link layer address > T}:T{ > .sp > lladdr > T}:T{ > .sp > variable > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The link layer address type is used for link layer addresses\&. Link laye= r addresses are specified as a variable amount of groups of two hexadecimal= digits separated using colons (:)\&. > .PP > \fBLink layer address specification\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # Ethernet destination MAC address > filter input ether daddr 20:c9:d0:43:12:d9 > .fi > .if n \{\ > .RE > .\} > .sp > .SS "IPV4 ADDRESS TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > IPV4 address > T}:T{ > .sp > ipv4_addr > T}:T{ > .sp > 32 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The IPv4 address type is used for IPv4 addresses\&. Addresses are specifi= ed in either dotted decimal, dotted hexadecimal, dotted octal, decimal, hex= adecimal, octal notation or as a host name\&. A host name will be resolved = using the standard system resolver\&. > .PP > \fBIPv4 address specification\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # dotted decimal notation > filter output ip daddr 127\&.0\&.0\&.1 >=20 > # host name > filter output ip daddr localhost > .fi > .if n \{\ > .RE > .\} > .sp > .SS "IPV6 ADDRESS TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > IPv6 address > T}:T{ > .sp > ipv6_addr > T}:T{ > .sp > 128 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The IPv6 address type is used for IPv6 addresses\&. Addresses are specifi= ed as a host name or as hexadecimal halfwords separated by colons\&. Addres= ses might be enclosed in square brackets ("[]") to differentiate them from = port numbers\&. > .PP > \fBIPv6 address specification\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # abbreviated loopback address > filter output ip6 daddr ::1 > .fi > .if n \{\ > .RE > .\} > .PP > \fBIPv6 address specification with bracket notation\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # without [] the port number (22) would be parsed as part of the > # ipv6 address > ip6 nat prerouting tcp dport 2222 dnat to [1ce::d0]:22 > .fi > .if n \{\ > .RE > .\} > .sp > .SS "BOOLEAN TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > Boolean > T}:T{ > .sp > boolean > T}:T{ > .sp > 1 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The boolean type is a syntactical helper type in userspace\&. Its use is = in the right\-hand side of a (typically implicit) relational expression to = change the expression on the left\-hand side into a boolean check (usually = for existence)\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&16.\ \&The following keywords will automatically resolve into= a boolean type with given value > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt. > T{ > .sp > exists > T}:T{ > .sp > 1 > T} > T{ > .sp > missing > T}:T{ > .sp > 0 > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&17.\ \&expressions support a boolean comparison > .TS > allbox tab(:); > ltB ltB. > T{ > Expression > T}:T{ > Behaviour > T} > .T& > lt lt > lt lt > lt lt. > T{ > .sp > fib > T}:T{ > .sp > Check route existence\&. > T} > T{ > .sp > exthdr > T}:T{ > .sp > Check IPv6 extension header existence\&. > T} > T{ > .sp > tcp option > T}:T{ > .sp > Check TCP option header existence\&. > T} > .TE > .sp 1 > .PP > \fBBoolean specification\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # match if route exists > filter input fib daddr \&. iif oif exists >=20 > # match only non\-fragmented packets in IPv6 traffic > filter input exthdr frag missing >=20 > # match if TCP timestamp option is present > filter input tcp option timestamp exists > .fi > .if n \{\ > .RE > .\} > .sp > .SS "ICMP TYPE TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > ICMP Type > T}:T{ > .sp > icmp_type > T}:T{ > .sp > 8 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The ICMP Type type is used to conveniently specify the ICMP header\(cqs t= ype field\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&18.\ \&Keywords may be used when specifying the ICMP type > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > echo\-reply > T}:T{ > .sp > 0 > T} > T{ > .sp > destination\-unreachable > T}:T{ > .sp > 3 > T} > T{ > .sp > source\-quench > T}:T{ > .sp > 4 > T} > T{ > .sp > redirect > T}:T{ > .sp > 5 > T} > T{ > .sp > echo\-request > T}:T{ > .sp > 8 > T} > T{ > .sp > router\-advertisement > T}:T{ > .sp > 9 > T} > T{ > .sp > router\-solicitation > T}:T{ > .sp > 10 > T} > T{ > .sp > time\-exceeded > T}:T{ > .sp > 11 > T} > T{ > .sp > parameter\-problem > T}:T{ > .sp > 12 > T} > T{ > .sp > timestamp\-request > T}:T{ > .sp > 13 > T} > T{ > .sp > timestamp\-reply > T}:T{ > .sp > 14 > T} > T{ > .sp > info\-request > T}:T{ > .sp > 15 > T} > T{ > .sp > info\-reply > T}:T{ > .sp > 16 > T} > T{ > .sp > address\-mask\-request > T}:T{ > .sp > 17 > T} > T{ > .sp > address\-mask\-reply > T}:T{ > .sp > 18 > T} > .TE > .sp 1 > .PP > \fBICMP Type specification\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # match ping packets > filter output icmp type { echo\-request, echo\-reply } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "ICMP CODE TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > ICMP Code > T}:T{ > .sp > icmp_code > T}:T{ > .sp > 8 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The ICMP Code type is used to conveniently specify the ICMP header\(cqs c= ode field\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&19.\ \&Keywords may be used when specifying the ICMP code > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > net\-unreachable > T}:T{ > .sp > 0 > T} > T{ > .sp > host\-unreachable > T}:T{ > .sp > 1 > T} > T{ > .sp > prot\-unreachable > T}:T{ > .sp > 2 > T} > T{ > .sp > port\-unreachable > T}:T{ > .sp > 3 > T} > T{ > .sp > frag\-needed > T}:T{ > .sp > 4 > T} > T{ > .sp > net\-prohibited > T}:T{ > .sp > 9 > T} > T{ > .sp > host\-prohibited > T}:T{ > .sp > 10 > T} > T{ > .sp > admin\-prohibited > T}:T{ > .sp > 13 > T} > .TE > .sp 1 > .SS "ICMPV6 TYPE TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > ICMPv6 Type > T}:T{ > .sp > icmpx_code > T}:T{ > .sp > 8 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The ICMPv6 Type type is used to conveniently specify the ICMPv6 header\(c= qs type field\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&20.\ \&keywords may be used when specifying the ICMPv6 type: > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > destination\-unreachable > T}:T{ > .sp > 1 > T} > T{ > .sp > packet\-too\-big > T}:T{ > .sp > 2 > T} > T{ > .sp > time\-exceeded > T}:T{ > .sp > 3 > T} > T{ > .sp > parameter\-problem > T}:T{ > .sp > 4 > T} > T{ > .sp > echo\-request > T}:T{ > .sp > 128 > T} > T{ > .sp > echo\-reply > T}:T{ > .sp > 129 > T} > T{ > .sp > mld\-listener\-query > T}:T{ > .sp > 130 > T} > T{ > .sp > mld\-listener\-report > T}:T{ > .sp > 131 > T} > T{ > .sp > mld\-listener\-done > T}:T{ > .sp > 132 > T} > T{ > .sp > mld\-listener\-reduction > T}:T{ > .sp > 132 > T} > T{ > .sp > nd\-router\-solicit > T}:T{ > .sp > 133 > T} > T{ > .sp > nd\-router\-advert > T}:T{ > .sp > 134 > T} > T{ > .sp > nd\-neighbor\-solicit > T}:T{ > .sp > 135 > T} > T{ > .sp > nd\-neighbor\-advert > T}:T{ > .sp > 136 > T} > T{ > .sp > nd\-redirect > T}:T{ > .sp > 137 > T} > T{ > .sp > router\-renumbering > T}:T{ > .sp > 138 > T} > T{ > .sp > ind\-neighbor\-solicit > T}:T{ > .sp > 141 > T} > T{ > .sp > ind\-neighbor\-advert > T}:T{ > .sp > 142 > T} > T{ > .sp > mld2\-listener\-report > T}:T{ > .sp > 143 > T} > .TE > .sp 1 > .PP > \fBICMPv6 Type specification\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # match ICMPv6 ping packets > filter output icmpv6 type { echo\-request, echo\-reply } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "ICMPV6 CODE TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > ICMPv6 Code > T}:T{ > .sp > icmpv6_code > T}:T{ > .sp > 8 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The ICMPv6 Code type is used to conveniently specify the ICMPv6 header\(c= qs code field\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&21.\ \&keywords may be used when specifying the ICMPv6 code > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > no\-route > T}:T{ > .sp > 0 > T} > T{ > .sp > admin\-prohibited > T}:T{ > .sp > 1 > T} > T{ > .sp > addr\-unreachable > T}:T{ > .sp > 3 > T} > T{ > .sp > port\-unreachable > T}:T{ > .sp > 4 > T} > T{ > .sp > policy\-fail > T}:T{ > .sp > 5 > T} > T{ > .sp > reject\-route > T}:T{ > .sp > 6 > T} > .TE > .sp 1 > .SS "ICMPVX CODE TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > ICMPvX Code > T}:T{ > .sp > icmpv6_type > T}:T{ > .sp > 8 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The ICMPvX Code type abstraction is a set of values which overlap between= ICMP and ICMPv6 Code types to be used from the inet family\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&22.\ \&keywords may be used when specifying the ICMPvX code > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > no\-route > T}:T{ > .sp > 0 > T} > T{ > .sp > port\-unreachable > T}:T{ > .sp > 1 > T} > T{ > .sp > host\-unreachable > T}:T{ > .sp > 2 > T} > T{ > .sp > admin\-prohibited > T}:T{ > .sp > 3 > T} > .TE > .sp 1 > .SS "CONNTRACK TYPES" > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&23.\ \&overview of types used in ct expression and statement > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt > lt lt lt lt > lt lt lt lt > lt lt lt lt > lt lt lt lt. > T{ > .sp > conntrack state > T}:T{ > .sp > ct_state > T}:T{ > .sp > 4 byte > T}:T{ > .sp > bitmask > T} > T{ > .sp > conntrack direction > T}:T{ > .sp > ct_dir > T}:T{ > .sp > 8 bit > T}:T{ > .sp > integer > T} > T{ > .sp > conntrack status > T}:T{ > .sp > ct_status > T}:T{ > .sp > 4 byte > T}:T{ > .sp > bitmask > T} > T{ > .sp > conntrack event bits > T}:T{ > .sp > ct_event > T}:T{ > .sp > 4 byte > T}:T{ > .sp > bitmask > T} > T{ > .sp > conntrack label > T}:T{ > .sp > ct_label > T}:T{ > .sp > 128 bit > T}:T{ > .sp > bitmask > T} > .TE > .sp 1 > .sp > For each of the types above, keywords are available for convenience: > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&24.\ \&conntrack state (ct_state) > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > invalid > T}:T{ > .sp > 1 > T} > T{ > .sp > established > T}:T{ > .sp > 2 > T} > T{ > .sp > related > T}:T{ > .sp > 4 > T} > T{ > .sp > new > T}:T{ > .sp > 8 > T} > T{ > .sp > untracked > T}:T{ > .sp > 64 > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&25.\ \&conntrack direction (ct_dir) > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt. > T{ > .sp > original > T}:T{ > .sp > 0 > T} > T{ > .sp > reply > T}:T{ > .sp > 1 > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&26.\ \&conntrack status (ct_status) > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > expected > T}:T{ > .sp > 1 > T} > T{ > .sp > seen\-reply > T}:T{ > .sp > 2 > T} > T{ > .sp > assured > T}:T{ > .sp > 4 > T} > T{ > .sp > confirmed > T}:T{ > .sp > 8 > T} > T{ > .sp > snat > T}:T{ > .sp > 16 > T} > T{ > .sp > dnat > T}:T{ > .sp > 32 > T} > T{ > .sp > dying > T}:T{ > .sp > 512 > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&27.\ \&conntrack event bits (ct_event) > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > new > T}:T{ > .sp > 1 > T} > T{ > .sp > related > T}:T{ > .sp > 2 > T} > T{ > .sp > destroy > T}:T{ > .sp > 4 > T} > T{ > .sp > reply > T}:T{ > .sp > 8 > T} > T{ > .sp > assured > T}:T{ > .sp > 16 > T} > T{ > .sp > protoinfo > T}:T{ > .sp > 32 > T} > T{ > .sp > helper > T}:T{ > .sp > 64 > T} > T{ > .sp > mark > T}:T{ > .sp > 128 > T} > T{ > .sp > seqadj > T}:T{ > .sp > 256 > T} > T{ > .sp > secmark > T}:T{ > .sp > 512 > T} > T{ > .sp > label > T}:T{ > .sp > 1024 > T} > .TE > .sp 1 > .sp > Possible keywords for conntrack label type (ct_label) are read at runtime= from /etc/connlabel\&.conf\&. > .SS "DCCP PKTTYPE TYPE" > .TS > allbox tab(:); > ltB ltB ltB ltB. > T{ > Name > T}:T{ > Keyword > T}:T{ > Size > T}:T{ > Base type > T} > .T& > lt lt lt lt. > T{ > .sp > DCCP packet type > T}:T{ > .sp > dccp_pkttype > T}:T{ > .sp > 4 bit > T}:T{ > .sp > integer > T} > .TE > .sp 1 > .sp > The DCCP packet type abstracts the different legal values of the respecti= ve four bit field in the DCCP header, as stated by RFC4340\&. Note that pos= sible values 10\-15 are considered reserved and therefore not allowed to be= used\&. In iptables\*(Aq \fBdccp\fR match, these values are aliased \fIINV= ALID\fR\&. With nftables, one may simply match on the numeric value range, = i\&.e\&. \fB10\-15\fR\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&28.\ \&keywords may be used when specifying the DCCP packet t= ype > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Value > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > request > T}:T{ > .sp > 0 > T} > T{ > .sp > response > T}:T{ > .sp > 1 > T} > T{ > .sp > data > T}:T{ > .sp > 2 > T} > T{ > .sp > ack > T}:T{ > .sp > 3 > T} > T{ > .sp > dataack > T}:T{ > .sp > 4 > T} > T{ > .sp > closereq > T}:T{ > .sp > 5 > T} > T{ > .sp > close > T}:T{ > .sp > 6 > T} > T{ > .sp > reset > T}:T{ > .sp > 7 > T} > T{ > .sp > sync > T}:T{ > .sp > 8 > T} > T{ > .sp > syncack > T}:T{ > .sp > 9 > T} > .TE > .sp 1 > .SH "PRIMARY EXPRESSIONS" > .sp > The lowest order expression is a primary expression, representing either = a constant or a single datum from a packet\(cqs payload, meta data or a sta= teful module\&. > .SS "META EXPRESSIONS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBmeta\fR {\fBlength\fR | \fBnfproto\fR | \fBl4proto\fR | \fBprotocol\fR= | \fBpriority\fR} > [\fBmeta\fR] {\fBmark\fR | \fBiif\fR | \fBiifname\fR | \fBiiftype\fR | \f= Boif\fR | \fBoifname\fR | \fBoiftype\fR | \fBskuid\fR | \fBskgid\fR | \fBnf= trace\fR | \fBrtclassid\fR | \fBibrname\fR | \fBobrname\fR | \fBpkttype\fR = | \fBcpu\fR | \fBiifgroup\fR | \fBoifgroup\fR | \fBcgroup\fR | \fBrandom\fR= | \fBipsec\fR | \fBiifkind\fR | \fBoifkind\fR | \fBtime\fR | \fBhour\fR | = \fBday\fR } > .fi > .if n \{\ > .RE > .\} > .sp > A meta expression refers to meta data associated with a packet\&. > .sp > There are two types of meta expressions: unqualified and qualified meta e= xpressions\&. Qualified meta expressions require the meta keyword before th= e meta key, unqualified meta expressions can be specified by using the meta= key directly or as qualified meta expressions\&. Meta l4proto is useful to= match a particular transport protocol that is part of either an IPv4 or IP= v6 packet\&. It will also skip any IPv6 extension headers present in an IPv= 6 packet\&. > .sp > meta iif, oif, iifname and oifname are used to match the interface a pack= et arrived on or is about to be sent out on\&. > .sp > iif and oif are used to match on the interface index, whereas iifname and= oifname are used to match on the interface name\&. This is not the same \(= em assuming the rule > .sp > .if n \{\ > .RS 4 > .\} > .nf > filter input meta iif "foo" > .fi > .if n \{\ > .RE > .\} > .sp > Then this rule can only be added if the interface "foo" exists\&. Also, t= he rule will continue to match even if the interface "foo" is renamed to "b= ar"\&. > .sp > This is because internally the interface index is used\&. In case of dyna= mically created interfaces, such as tun/tap or dialup interfaces (ppp for e= xample), it might be better to use iifname or oifname instead\&. > .sp > In these cases, the name is used so the interface doesn\(cqt have to exis= t to add such a rule, it will stop matching if the interface gets renamed a= nd it will match again in case interface gets deleted and later a new inter= face with the same name is created\&. > .sp > Like with iptables, wildcard matching on interface name prefixes is avail= able for \fBiifname\fR and \fBoifname\fR matches by appending an asterisk (= *) character\&. Note however that unlike iptables, nftables does not accept= interface names consisting of the wildcard character only \- users are sup= posed to just skip those always matching expressions\&. In order to match o= n literal asterisk character, one may escape it using backslash (\e)\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&29.\ \&Meta expression types > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > length > T}:T{ > .sp > Length of the packet in bytes > T}:T{ > .sp > integer (32\-bit) > T} > T{ > .sp > nfproto > T}:T{ > .sp > real hook protocol family, useful only in inet table > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > l4proto > T}:T{ > .sp > layer 4 protocol, skips ipv6 extension headers > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > protocol > T}:T{ > .sp > EtherType protocol value > T}:T{ > .sp > ether_type > T} > T{ > .sp > priority > T}:T{ > .sp > TC packet priority > T}:T{ > .sp > tc_handle > T} > T{ > .sp > mark > T}:T{ > .sp > Packet mark > T}:T{ > .sp > mark > T} > T{ > .sp > iif > T}:T{ > .sp > Input interface index > T}:T{ > .sp > iface_index > T} > T{ > .sp > iifname > T}:T{ > .sp > Input interface name > T}:T{ > .sp > ifname > T} > T{ > .sp > iiftype > T}:T{ > .sp > Input interface type > T}:T{ > .sp > iface_type > T} > T{ > .sp > oif > T}:T{ > .sp > Output interface index > T}:T{ > .sp > iface_index > T} > T{ > .sp > oifname > T}:T{ > .sp > Output interface name > T}:T{ > .sp > ifname > T} > T{ > .sp > oiftype > T}:T{ > .sp > Output interface hardware type > T}:T{ > .sp > iface_type > T} > T{ > .sp > sdif > T}:T{ > .sp > Slave device input interface index > T}:T{ > .sp > iface_index > T} > T{ > .sp > sdifname > T}:T{ > .sp > Slave device interface name > T}:T{ > .sp > ifname > T} > T{ > .sp > skuid > T}:T{ > .sp > UID associated with originating socket > T}:T{ > .sp > uid > T} > T{ > .sp > skgid > T}:T{ > .sp > GID associated with originating socket > T}:T{ > .sp > gid > T} > T{ > .sp > rtclassid > T}:T{ > .sp > Routing realm > T}:T{ > .sp > realm > T} > T{ > .sp > ibrname > T}:T{ > .sp > Input bridge interface name > T}:T{ > .sp > ifname > T} > T{ > .sp > obrname > T}:T{ > .sp > Output bridge interface name > T}:T{ > .sp > ifname > T} > T{ > .sp > pkttype > T}:T{ > .sp > packet type > T}:T{ > .sp > pkt_type > T} > T{ > .sp > cpu > T}:T{ > .sp > cpu number processing the packet > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > iifgroup > T}:T{ > .sp > incoming device group > T}:T{ > .sp > devgroup > T} > T{ > .sp > oifgroup > T}:T{ > .sp > outgoing device group > T}:T{ > .sp > devgroup > T} > T{ > .sp > cgroup > T}:T{ > .sp > control group id > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > random > T}:T{ > .sp > pseudo\-random number > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > ipsec > T}:T{ > .sp > true if packet was ipsec encrypted > T}:T{ > .sp > boolean (1 bit) > T} > T{ > .sp > iifkind > T}:T{ > .sp > Input interface kind > T}:T{ > .sp > T} > T{ > .sp > oifkind > T}:T{ > .sp > Output interface kind > T}:T{ > .sp > T} > T{ > .sp > time > T}:T{ > .sp > Absolute time of packet reception > T}:T{ > .sp > Integer (32 bit) or string > T} > T{ > .sp > day > T}:T{ > .sp > Day of week > T}:T{ > .sp > Integer (8 bit) or string > T} > T{ > .sp > hour > T}:T{ > .sp > Hour of day > T}:T{ > .sp > String > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&30.\ \&Meta expression specific types > .TS > allbox tab(:); > ltB ltB. > T{ > Type > T}:T{ > Description > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > iface_index > T}:T{ > .sp > Interface index (32 bit number)\&. Can be specified numerically or as nam= e of an existing interface\&. > T} > T{ > .sp > ifname > T}:T{ > .sp > Interface name (16 byte string)\&. Does not have to exist\&. > T} > T{ > .sp > iface_type > T}:T{ > .sp > Interface type (16 bit number)\&. > T} > T{ > .sp > uid > T}:T{ > .sp > User ID (32 bit number)\&. Can be specified numerically or as user name\&. > T} > T{ > .sp > gid > T}:T{ > .sp > Group ID (32 bit number)\&. Can be specified numerically or as group name= \&. > T} > T{ > .sp > realm > T}:T{ > .sp > Routing Realm (32 bit number)\&. Can be specified numerically or as symbo= lic name defined in /etc/iproute2/rt_realms\&. > T} > T{ > .sp > devgroup_type > T}:T{ > .sp > Device group (32 bit number)\&. Can be specified numerically or as symbol= ic name defined in /etc/iproute2/group\&. > T} > T{ > .sp > pkt_type > T}:T{ > .sp > Packet type: \fBhost\fR (addressed to local host), \fBbroadcast\fR (to al= l), \fBmulticast\fR (to group), \fBother\fR (addressed to another host)\&. > T} > T{ > .sp > ifkind > T}:T{ > .sp > Interface kind (16 byte string)\&. See TYPES in ip\-link(8) for a list\&. > T} > T{ > .sp > time > T}:T{ > .sp > Either an integer or a date in ISO format\&. For example: "2019\-06\-06 1= 7:00"\&. Hour and seconds are optional and can be omitted if desired\&. If = omitted, midnight will be assumed\&. The following three would be equivalen= t: "2019\-06\-06", "2019\-06\-06 00:00" and "2019\-06\-06 00:00:00"\&. When= an integer is given, it is assumed to be a UNIX timestamp\&. > T} > T{ > .sp > day > T}:T{ > .sp > Either a day of week ("Monday", "Tuesday", etc\&.), or an integer between= 0 and 6\&. Strings are matched case\-insensitively, and a full match is no= t expected (e\&.g\&. "Mon" would match "Monday")\&. When an integer is give= n, 0 is Sunday and 6 is Saturday\&. > T} > T{ > .sp > hour > T}:T{ > .sp > A string representing an hour in 24\-hour format\&. Seconds can optionall= y be specified\&. For example, 17:00 and 17:00:00 would be equivalent\&. > T} > .TE > .sp 1 > .PP > \fBUsing meta expressions\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # qualified meta expression > filter output meta oif eth0 > filter forward meta iifkind { "tun", "veth" } >=20 > # unqualified meta expression > filter output oif eth0 >=20 > # incoming packet was subject to ipsec processing > raw prerouting meta ipsec exists accept > .fi > .if n \{\ > .RE > .\} > .sp > .SS "SOCKET EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBsocket\fR {\fBtransparent\fR | \fBmark\fR | \fBwildcard\fR} > .fi > .if n \{\ > .RE > .\} > .sp > Socket expression can be used to search for an existing open TCP/UDP sock= et and its attributes that can be associated with a packet\&. It looks for = an established or non\-zero bound listening socket (possibly with a non\-lo= cal address)\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&31.\ \&Available socket attributes > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Name > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > transparent > T}:T{ > .sp > Value of the IP_TRANSPARENT socket option in the found socket\&. It can b= e 0 or 1\&. > T}:T{ > .sp > boolean (1 bit) > T} > T{ > .sp > mark > T}:T{ > .sp > Value of the socket mark (SOL_SOCKET, SO_MARK)\&. > T}:T{ > .sp > mark > T} > T{ > .sp > wildcard > T}:T{ > .sp > Indicates whether the socket is wildcard\-bound (e\&.g\&. 0\&.0\&.0\&.0 o= r ::0)\&. > T}:T{ > .sp > boolean (1 bit) > T} > .TE > .sp 1 > .PP > \fBUsing socket expression\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # Mark packets that correspond to a transparent socket\&. "socket wildcar= d 0" > # means that zero\-bound listener sockets are NOT matched (which is usual= ly > # exactly what you want)\&. > table inet x { > chain y { > type filter hook prerouting priority \-150; policy accept; > socket transparent 1 socket wildcard 0 mark set 0x00000001 accept > } > } >=20 > # Trace packets that corresponds to a socket with a mark value of 15 > table inet x { > chain y { > type filter hook prerouting priority \-150; policy accept; > socket mark 0x0000000f nftrace set 1 > } > } >=20 > # Set packet mark to socket mark > table inet x { > chain y { > type filter hook prerouting priority \-150; policy accept; > tcp dport 8080 mark set socket mark > } > } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "OSF EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBosf\fR [\fBttl\fR {\fBloose\fR | \fBskip\fR}] {\fBname\fR | \fBversion= \fR} > .fi > .if n \{\ > .RE > .\} > .sp > The osf expression does passive operating system fingerprinting\&. This e= xpression compares some data (Window Size, MSS, options and their order, DF= , and others) from packets with the SYN bit set\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&32.\ \&Available osf attributes > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Name > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > ttl > T}:T{ > .sp > Do TTL checks on the packet to determine the operating system\&. > T}:T{ > .sp > string > T} > T{ > .sp > version > T}:T{ > .sp > Do OS version checks on the packet\&. > T}:T{ > .sp > T} > T{ > .sp > name > T}:T{ > .sp > Name of the OS signature to match\&. All signatures can be found at pf\&.= os file\&. Use "unknown" for OS signatures that the expression could not de= tect\&. > T}:T{ > .sp > string > T} > .TE > .sp 1 > .PP > \fBAvailable ttl values\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > If no TTL attribute is passed, make a true IP header and fingerprint TTL = true comparison\&. This generally works for LANs\&. >=20 > * loose: Check if the IP header\*(Aqs TTL is less than the fingerprint on= e\&. Works for globally\-routable addresses\&. > * skip: Do not compare the TTL at all\&. > .fi > .if n \{\ > .RE > .\} > .PP > \fBUsing osf expression\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # Accept packets that match the "Linux" OS genre signature without compar= ing TTL\&. > table inet x { > chain y { > type filter hook input priority 0; policy accept; > osf ttl skip name "Linux" > } > } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "FIB EXPRESSIONS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBfib\fR {\fBsaddr\fR | \fBdaddr\fR | \fBmark\fR | \fBiif\fR | \fBoif\fR= } [\fB\&.\fR \&...] {\fBoif\fR | \fBoifname\fR | \fBtype\fR} > .fi > .if n \{\ > .RE > .\} > .sp > A fib expression queries the fib (forwarding information base) to obtain = information such as the output interface index a particular address would u= se\&. The input is a tuple of elements that is used as input to the fib loo= kup functions\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&33.\ \&fib expression specific types > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > oif > T}:T{ > .sp > Output interface index > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > oifname > T}:T{ > .sp > Output interface name > T}:T{ > .sp > string > T} > T{ > .sp > type > T}:T{ > .sp > Address type > T}:T{ > .sp > fib_addrtype > T} > .TE > .sp 1 > .sp > Use \fBnft\fR \fBdescribe\fR \fBfib_addrtype\fR to get a list of all addr= ess types\&. > .PP > \fBUsing fib expressions\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # drop packets without a reverse path > filter prerouting fib saddr \&. iif oif missing drop >=20 > In this example, \*(Aqsaddr \&. iif\*(Aq looks up routing information bas= ed on the source address and the input interface\&. > oif picks the output interface index from the routing information\&. > If no route was found for the source address/input interface combination,= the output interface index is zero\&. > In case the input interface is specified as part of the input key, the ou= tput interface index is always the same as the input interface index or zer= o\&. > If only \*(Aqsaddr oif\*(Aq is given, then oif can be any interface index= or zero\&. >=20 > # drop packets to address not configured on incoming interface > filter prerouting fib daddr \&. iif type !=3D { local, broadcast, multica= st } drop >=20 > # perform lookup in a specific \*(Aqblackhole\*(Aq table (0xdead, needs i= p appropriate ip rule) > filter prerouting meta mark set 0xdead fib daddr \&. mark type vmap { bla= ckhole : drop, prohibit : jump prohibited, unreachable : drop } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "ROUTING EXPRESSIONS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBrt\fR [\fBip\fR | \fBip6\fR] {\fBclassid\fR | \fBnexthop\fR | \fBmtu\f= R | \fBipsec\fR} > .fi > .if n \{\ > .RE > .\} > .sp > A routing expression refers to routing data associated with a packet\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&34.\ \&Routing expression types > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > classid > T}:T{ > .sp > Routing realm > T}:T{ > .sp > realm > T} > T{ > .sp > nexthop > T}:T{ > .sp > Routing nexthop > T}:T{ > .sp > ipv4_addr/ipv6_addr > T} > T{ > .sp > mtu > T}:T{ > .sp > TCP maximum segment size of route > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > ipsec > T}:T{ > .sp > route via ipsec tunnel or transport > T}:T{ > .sp > boolean > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&35.\ \&Routing expression specific types > .TS > allbox tab(:); > ltB ltB. > T{ > Type > T}:T{ > Description > T} > .T& > lt lt. > T{ > .sp > realm > T}:T{ > .sp > Routing Realm (32 bit number)\&. Can be specified numerically or as symbo= lic name defined in /etc/iproute2/rt_realms\&. > T} > .TE > .sp 1 > .PP > \fBUsing routing expressions\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # IP family independent rt expression > filter output rt classid 10 >=20 > # IP family dependent rt expressions > ip filter output rt nexthop 192\&.168\&.0\&.1 > ip6 filter output rt nexthop fd00::1 > inet filter output rt ip nexthop 192\&.168\&.0\&.1 > inet filter output rt ip6 nexthop fd00::1 >=20 > # outgoing packet will be encapsulated/encrypted by ipsec > filter output rt ipsec exists > .fi > .if n \{\ > .RE > .\} > .sp > .SS "IPSEC EXPRESSIONS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBipsec\fR {\fBin\fR | \fBout\fR} [ \fBspnum\fR \fINUM\fR ] {\fBreqid\f= R | \fBspi\fR} > \fBipsec\fR {\fBin\fR | \fBout\fR} [ \fBspnum\fR \fINUM\fR ] {\fBip\fR |= \fBip6\fR} {\fBsaddr\fR | \fBdaddr\fR} > .fi > .if n \{\ > .RE > .\} > .sp > An ipsec expression refers to ipsec data associated with a packet\&. > .sp > The \fIin\fR or \fIout\fR keyword needs to be used to specify if the expr= ession should examine inbound or outbound policies\&. The \fIin\fR keyword = can be used in the prerouting, input and forward hooks\&. The \fIout\fR key= word applies to forward, output and postrouting hooks\&. The optional keywo= rd spnum can be used to match a specific state in a chain, it defaults to 0= \&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&36.\ \&Ipsec expression types > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > reqid > T}:T{ > .sp > Request ID > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > spi > T}:T{ > .sp > Security Parameter Index > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > saddr > T}:T{ > .sp > Source address of the tunnel > T}:T{ > .sp > ipv4_addr/ipv6_addr > T} > T{ > .sp > daddr > T}:T{ > .sp > Destination address of the tunnel > T}:T{ > .sp > ipv4_addr/ipv6_addr > T} > .TE > .sp 1 > .SS "NUMGEN EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBnumgen\fR {\fBinc\fR | \fBrandom\fR} \fBmod\fR \fINUM\fR [ \fBoffset\f= R \fINUM\fR ] > .fi > .if n \{\ > .RE > .\} > .sp > Create a number generator\&. The \fBinc\fR or \fBrandom\fR keywords contr= ol its operation mode: In \fBinc\fR mode, the last returned value is simply= incremented\&. In \fBrandom\fR mode, a new random number is returned\&. Th= e value after \fBmod\fR keyword specifies an upper boundary (read: modulus)= which is not reached by returned numbers\&. The optional \fBoffset\fR allo= ws to increment the returned value by a fixed offset\&. > .sp > A typical use\-case for \fBnumgen\fR is load\-balancing: > .PP > \fBUsing numgen expression\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # round\-robin between 192\&.168\&.10\&.100 and 192\&.168\&.20\&.200: > add rule nat prerouting dnat to numgen inc mod 2 map \e > { 0 : 192\&.168\&.10\&.100, 1 : 192\&.168\&.20\&.200 } >=20 > # probability\-based with odd bias using intervals: > add rule nat prerouting dnat to numgen random mod 10 map \e > { 0\-2 : 192\&.168\&.10\&.100, 3\-9 : 192\&.168\&.20\&.200 } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "HASH EXPRESSIONS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBjhash\fR {\fBip saddr\fR | \fBip6 daddr\fR | \fBtcp dport\fR | \fBudp = sport\fR | \fBether saddr\fR} [\fB\&.\fR \&...] \fBmod\fR \fINUM\fR [ \fBse= ed\fR \fINUM\fR ] [ \fBoffset\fR \fINUM\fR ] > \fBsymhash\fR \fBmod\fR \fINUM\fR [ \fBoffset\fR \fINUM\fR ] > .fi > .if n \{\ > .RE > .\} > .sp > Use a hashing function to generate a number\&. The functions available ar= e \fBjhash\fR, known as Jenkins Hash, and \fBsymhash\fR, for Symmetric Hash= \&. The \fBjhash\fR requires an expression to determine the parameters of t= he packet header to apply the hashing, concatenations are possible as well\= &. The value after \fBmod\fR keyword specifies an upper boundary (read: mod= ulus) which is not reached by returned numbers\&. The optional \fBseed\fR i= s used to specify an init value used as seed in the hashing function\&. The= optional \fBoffset\fR allows to increment the returned value by a fixed of= fset\&. > .sp > A typical use\-case for \fBjhash\fR and \fBsymhash\fR is load\-balancing: > .PP > \fBUsing hash expressions\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # load balance based on source ip between 2 ip addresses: > add rule nat prerouting dnat to jhash ip saddr mod 2 map \e > { 0 : 192\&.168\&.10\&.100, 1 : 192\&.168\&.20\&.200 } >=20 > # symmetric load balancing between 2 ip addresses: > add rule nat prerouting dnat to symhash mod 2 map \e > { 0 : 192\&.168\&.10\&.100, 1 : 192\&.168\&.20\&.200 } > .fi > .if n \{\ > .RE > .\} > .sp > .SH "PAYLOAD EXPRESSIONS" > .sp > Payload expressions refer to data from the packet\(cqs payload\&. > .SS "ETHERNET HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBether\fR {\fBdaddr\fR | \fBsaddr\fR | \fBtype\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&37.\ \&Ethernet header expression types > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > daddr > T}:T{ > .sp > Destination MAC address > T}:T{ > .sp > ether_addr > T} > T{ > .sp > saddr > T}:T{ > .sp > Source MAC address > T}:T{ > .sp > ether_addr > T} > T{ > .sp > type > T}:T{ > .sp > EtherType > T}:T{ > .sp > ether_type > T} > .TE > .sp 1 > .SS "VLAN HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBvlan\fR {\fBid\fR | \fBcfi\fR | \fBpcp\fR | \fBtype\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&38.\ \&VLAN header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > id > T}:T{ > .sp > VLAN ID (VID) > T}:T{ > .sp > integer (12 bit) > T} > T{ > .sp > cfi > T}:T{ > .sp > Canonical Format Indicator > T}:T{ > .sp > integer (1 bit) > T} > T{ > .sp > pcp > T}:T{ > .sp > Priority code point > T}:T{ > .sp > integer (3 bit) > T} > T{ > .sp > type > T}:T{ > .sp > EtherType > T}:T{ > .sp > ether_type > T} > .TE > .sp 1 > .SS "ARP HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBarp\fR {\fBhtype\fR | \fBptype\fR | \fBhlen\fR | \fBplen\fR | \fBopera= tion\fR | \fBsaddr\fR { \fBip\fR | \fBether\fR } | \fBdaddr\fR { \fBip\fR |= \fBether\fR } > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&39.\ \&ARP header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > htype > T}:T{ > .sp > ARP hardware type > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > ptype > T}:T{ > .sp > EtherType > T}:T{ > .sp > ether_type > T} > T{ > .sp > hlen > T}:T{ > .sp > Hardware address len > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > plen > T}:T{ > .sp > Protocol address len > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > operation > T}:T{ > .sp > Operation > T}:T{ > .sp > arp_op > T} > T{ > .sp > saddr ether > T}:T{ > .sp > Ethernet sender address > T}:T{ > .sp > ether_addr > T} > T{ > .sp > daddr ether > T}:T{ > .sp > Ethernet target address > T}:T{ > .sp > ether_addr > T} > T{ > .sp > saddr ip > T}:T{ > .sp > IPv4 sender address > T}:T{ > .sp > ipv4_addr > T} > T{ > .sp > daddr ip > T}:T{ > .sp > IPv4 target address > T}:T{ > .sp > ipv4_addr > T} > .TE > .sp 1 > .SS "IPV4 HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBip\fR {\fBversion\fR | \fBhdrlength\fR | \fBdscp\fR | \fBecn\fR | \fBl= ength\fR | \fBid\fR | \fBfrag\-off\fR | \fBttl\fR | \fBprotocol\fR | \fBche= cksum\fR | \fBsaddr\fR | \fBdaddr\fR } > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&40.\ \&IPv4 header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > version > T}:T{ > .sp > IP header version (4) > T}:T{ > .sp > integer (4 bit) > T} > T{ > .sp > hdrlength > T}:T{ > .sp > IP header length including options > T}:T{ > .sp > integer (4 bit) FIXME scaling > T} > T{ > .sp > dscp > T}:T{ > .sp > Differentiated Services Code Point > T}:T{ > .sp > dscp > T} > T{ > .sp > ecn > T}:T{ > .sp > Explicit Congestion Notification > T}:T{ > .sp > ecn > T} > T{ > .sp > length > T}:T{ > .sp > Total packet length > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > id > T}:T{ > .sp > IP ID > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > frag\-off > T}:T{ > .sp > Fragment offset > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > ttl > T}:T{ > .sp > Time to live > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > protocol > T}:T{ > .sp > Upper layer protocol > T}:T{ > .sp > inet_proto > T} > T{ > .sp > checksum > T}:T{ > .sp > IP header checksum > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > saddr > T}:T{ > .sp > Source address > T}:T{ > .sp > ipv4_addr > T} > T{ > .sp > daddr > T}:T{ > .sp > Destination address > T}:T{ > .sp > ipv4_addr > T} > .TE > .sp 1 > .SS "ICMP HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBicmp\fR {\fBtype\fR | \fBcode\fR | \fBchecksum\fR | \fBid\fR | \fBsequ= ence\fR | \fBgateway\fR | \fBmtu\fR} > .fi > .if n \{\ > .RE > .\} > .sp > This expression refers to ICMP header fields\&. When using it in \fBinet\= fR, \fBbridge\fR or \fBnetdev\fR families, it will cause an implicit depend= ency on IPv4 to be created\&. To match on unusual cases like ICMP over IPv6= , one has to add an explicit \fBmeta protocol ip6\fR match to the rule\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&41.\ \&ICMP header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > type > T}:T{ > .sp > ICMP type field > T}:T{ > .sp > icmp_type > T} > T{ > .sp > code > T}:T{ > .sp > ICMP code field > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > checksum > T}:T{ > .sp > ICMP checksum field > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > id > T}:T{ > .sp > ID of echo request/response > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > sequence > T}:T{ > .sp > sequence number of echo request/response > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > gateway > T}:T{ > .sp > gateway of redirects > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > mtu > T}:T{ > .sp > MTU of path MTU discovery > T}:T{ > .sp > integer (16 bit) > T} > .TE > .sp 1 > .SS "IGMP HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBigmp\fR {\fBtype\fR | \fBmrt\fR | \fBchecksum\fR | \fBgroup\fR} > .fi > .if n \{\ > .RE > .\} > .sp > This expression refers to IGMP header fields\&. When using it in \fBinet\= fR, \fBbridge\fR or \fBnetdev\fR families, it will cause an implicit depend= ency on IPv4 to be created\&. To match on unusual cases like IGMP over IPv6= , one has to add an explicit \fBmeta protocol ip6\fR match to the rule\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&42.\ \&IGMP header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > type > T}:T{ > .sp > IGMP type field > T}:T{ > .sp > igmp_type > T} > T{ > .sp > mrt > T}:T{ > .sp > IGMP maximum response time field > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > checksum > T}:T{ > .sp > IGMP checksum field > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > group > T}:T{ > .sp > Group address > T}:T{ > .sp > integer (32 bit) > T} > .TE > .sp 1 > .SS "IPV6 HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBip6\fR {\fBversion\fR | \fBdscp\fR | \fBecn\fR | \fBflowlabel\fR | \fB= length\fR | \fBnexthdr\fR | \fBhoplimit\fR | \fBsaddr\fR | \fBdaddr\fR} > .fi > .if n \{\ > .RE > .\} > .sp > This expression refers to the ipv6 header fields\&. Caution when using \f= Bip6 nexthdr\fR, the value only refers to the next header, i\&.e\&. \fBip6 = nexthdr tcp\fR will only match if the ipv6 packet does not contain any exte= nsion headers\&. Packets that are fragmented or e\&.g\&. contain a routing = extension headers will not be matched\&. Please use \fBmeta l4proto\fR if y= ou wish to match the real transport header and ignore any additional extens= ion headers instead\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&43.\ \&IPv6 header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > version > T}:T{ > .sp > IP header version (6) > T}:T{ > .sp > integer (4 bit) > T} > T{ > .sp > dscp > T}:T{ > .sp > Differentiated Services Code Point > T}:T{ > .sp > dscp > T} > T{ > .sp > ecn > T}:T{ > .sp > Explicit Congestion Notification > T}:T{ > .sp > ecn > T} > T{ > .sp > flowlabel > T}:T{ > .sp > Flow label > T}:T{ > .sp > integer (20 bit) > T} > T{ > .sp > length > T}:T{ > .sp > Payload length > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > nexthdr > T}:T{ > .sp > Nexthdr protocol > T}:T{ > .sp > inet_proto > T} > T{ > .sp > hoplimit > T}:T{ > .sp > Hop limit > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > saddr > T}:T{ > .sp > Source address > T}:T{ > .sp > ipv6_addr > T} > T{ > .sp > daddr > T}:T{ > .sp > Destination address > T}:T{ > .sp > ipv6_addr > T} > .TE > .sp 1 > .PP > \fBUsing ip6 header expressions\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # matching if first extension header indicates a fragment > ip6 nexthdr ipv6\-frag > .fi > .if n \{\ > .RE > .\} > .sp > .SS "ICMPV6 HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBicmpv6\fR {\fBtype\fR | \fBcode\fR | \fBchecksum\fR | \fBparameter\-pr= oblem\fR | \fBpacket\-too\-big\fR | \fBid\fR | \fBsequence\fR | \fBmax\-del= ay\fR} > .fi > .if n \{\ > .RE > .\} > .sp > This expression refers to ICMPv6 header fields\&. When using it in \fBine= t\fR, \fBbridge\fR or \fBnetdev\fR families, it will cause an implicit depe= ndency on IPv6 to be created\&. To match on unusual cases like ICMPv6 over = IPv4, one has to add an explicit \fBmeta protocol ip\fR match to the rule\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&44.\ \&ICMPv6 header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > type > T}:T{ > .sp > ICMPv6 type field > T}:T{ > .sp > icmpv6_type > T} > T{ > .sp > code > T}:T{ > .sp > ICMPv6 code field > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > checksum > T}:T{ > .sp > ICMPv6 checksum field > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > parameter\-problem > T}:T{ > .sp > pointer to problem > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > packet\-too\-big > T}:T{ > .sp > oversized MTU > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > id > T}:T{ > .sp > ID of echo request/response > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > sequence > T}:T{ > .sp > sequence number of echo request/response > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > max\-delay > T}:T{ > .sp > maximum response delay of MLD queries > T}:T{ > .sp > integer (16 bit) > T} > .TE > .sp 1 > .SS "TCP HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBtcp\fR {\fBsport\fR | \fBdport\fR | \fBsequence\fR | \fBackseq\fR | \f= Bdoff\fR | \fBreserved\fR | \fBflags\fR | \fBwindow\fR | \fBchecksum\fR | \= fBurgptr\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&45.\ \&TCP header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > sport > T}:T{ > .sp > Source port > T}:T{ > .sp > inet_service > T} > T{ > .sp > dport > T}:T{ > .sp > Destination port > T}:T{ > .sp > inet_service > T} > T{ > .sp > sequence > T}:T{ > .sp > Sequence number > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > ackseq > T}:T{ > .sp > Acknowledgement number > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > doff > T}:T{ > .sp > Data offset > T}:T{ > .sp > integer (4 bit) FIXME scaling > T} > T{ > .sp > reserved > T}:T{ > .sp > Reserved area > T}:T{ > .sp > integer (4 bit) > T} > T{ > .sp > flags > T}:T{ > .sp > TCP flags > T}:T{ > .sp > tcp_flag > T} > T{ > .sp > window > T}:T{ > .sp > Window > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > checksum > T}:T{ > .sp > Checksum > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > urgptr > T}:T{ > .sp > Urgent pointer > T}:T{ > .sp > integer (16 bit) > T} > .TE > .sp 1 > .SS "UDP HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBudp\fR {\fBsport\fR | \fBdport\fR | \fBlength\fR | \fBchecksum\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&46.\ \&UDP header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > sport > T}:T{ > .sp > Source port > T}:T{ > .sp > inet_service > T} > T{ > .sp > dport > T}:T{ > .sp > Destination port > T}:T{ > .sp > inet_service > T} > T{ > .sp > length > T}:T{ > .sp > Total packet length > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > checksum > T}:T{ > .sp > Checksum > T}:T{ > .sp > integer (16 bit) > T} > .TE > .sp 1 > .SS "UDP\-LITE HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBudplite\fR {\fBsport\fR | \fBdport\fR | \fBchecksum\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&47.\ \&UDP\-Lite header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > sport > T}:T{ > .sp > Source port > T}:T{ > .sp > inet_service > T} > T{ > .sp > dport > T}:T{ > .sp > Destination port > T}:T{ > .sp > inet_service > T} > T{ > .sp > checksum > T}:T{ > .sp > Checksum > T}:T{ > .sp > integer (16 bit) > T} > .TE > .sp 1 > .SS "SCTP HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBsctp\fR {\fBsport\fR | \fBdport\fR | \fBvtag\fR | \fBchecksum\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&48.\ \&SCTP header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > sport > T}:T{ > .sp > Source port > T}:T{ > .sp > inet_service > T} > T{ > .sp > dport > T}:T{ > .sp > Destination port > T}:T{ > .sp > inet_service > T} > T{ > .sp > vtag > T}:T{ > .sp > Verification Tag > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > checksum > T}:T{ > .sp > Checksum > T}:T{ > .sp > integer (32 bit) > T} > .TE > .sp 1 > .SS "DCCP HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBdccp\fR {\fBsport\fR | \fBdport\fR | \fBtype\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&49.\ \&DCCP header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > sport > T}:T{ > .sp > Source port > T}:T{ > .sp > inet_service > T} > T{ > .sp > dport > T}:T{ > .sp > Destination port > T}:T{ > .sp > inet_service > T} > T{ > .sp > type > T}:T{ > .sp > Packet type > T}:T{ > .sp > dccp_pkttype > T} > .TE > .sp 1 > .SS "AUTHENTICATION HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBah\fR {\fBnexthdr\fR | \fBhdrlength\fR | \fBreserved\fR | \fBspi\fR | = \fBsequence\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&50.\ \&AH header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > nexthdr > T}:T{ > .sp > Next header protocol > T}:T{ > .sp > inet_proto > T} > T{ > .sp > hdrlength > T}:T{ > .sp > AH Header length > T}:T{ > .sp > integer (8 bit) > T} > T{ > .sp > reserved > T}:T{ > .sp > Reserved area > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > spi > T}:T{ > .sp > Security Parameter Index > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > sequence > T}:T{ > .sp > Sequence number > T}:T{ > .sp > integer (32 bit) > T} > .TE > .sp 1 > .SS "ENCRYPTED SECURITY PAYLOAD HEADER EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBesp\fR {\fBspi\fR | \fBsequence\fR} > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&51.\ \&ESP header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt. > T{ > .sp > spi > T}:T{ > .sp > Security Parameter Index > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > sequence > T}:T{ > .sp > Sequence number > T}:T{ > .sp > integer (32 bit) > T} > .TE > .sp 1 > .SS "IPCOMP HEADER EXPRESSION" > .sp > \fBcomp\fR {\fBnexthdr\fR | \fBflags\fR | \fBcpi\fR} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&52.\ \&IPComp header expression > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > nexthdr > T}:T{ > .sp > Next header protocol > T}:T{ > .sp > inet_proto > T} > T{ > .sp > flags > T}:T{ > .sp > Flags > T}:T{ > .sp > bitmask > T} > T{ > .sp > cpi > T}:T{ > .sp > compression Parameter Index > T}:T{ > .sp > integer (16 bit) > T} > .TE > .sp 1 > .SS "RAW PAYLOAD EXPRESSION" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fB@\fR\fIbase\fR\fB,\fR\fIoffset\fR\fB,\fR\fIlength\fR > .fi > .if n \{\ > .RE > .\} > .sp > The raw payload expression instructs to load \fIlength\fR bits starting a= t \fIoffset\fR bits\&. Bit 0 refers to the very first bit \(em in the C pro= gramming language, this corresponds to the topmost bit, i\&.e\&. 0x80 in ca= se of an octet\&. They are useful to match headers that do not have a human= \-readable template expression yet\&. Note that nft will not add dependenci= es for Raw payload expressions\&. If you e\&.g\&. want to match protocol fi= elds of a transport header with protocol number 5, you need to manually exc= lude packets that have a different transport header, for instance by using = \fBmeta l4proto 5\fR before the raw expression\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&53.\ \&Supported payload protocol bases > .TS > allbox tab(:); > ltB ltB. > T{ > Base > T}:T{ > Description > T} > .T& > lt lt > lt lt > lt lt. > T{ > .sp > ll > T}:T{ > .sp > Link layer, for example the Ethernet header > T} > T{ > .sp > nh > T}:T{ > .sp > Network header, for example IPv4 or IPv6 > T} > T{ > .sp > th > T}:T{ > .sp > Transport Header, for example TCP > T} > .TE > .sp 1 > .PP > \fBMatching destination port of both UDP and TCP\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > inet filter input meta l4proto {tcp, udp} @th,16,16 { 53, 80 } > .fi > .if n \{\ > .RE > .\} > .sp > The above can also be written as > .sp > .if n \{\ > .RS 4 > .\} > .nf > inet filter input meta l4proto {tcp, udp} th dport { 53, 80 } > .fi > .if n \{\ > .RE > .\} > .sp > it is more convenient, but like the raw expression notation no dependenci= es are created or checked\&. It is the users responsibility to restrict mat= ching to those header types that have a notion of ports\&. Otherwise, rules= using raw expressions will errnously match unrelated packets, e\&.g\&. mis= \-interpreting ESP packets SPI field as a port\&. > .PP > \fBRewrite arp packet target hardware address if target protocol address = matches a given address\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > input meta iifname enp2s0 arp ptype 0x0800 arp htype 1 arp hlen 6 arp ple= n 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566 accept > .fi > .if n \{\ > .RE > .\} > .sp > .SS "EXTENSION HEADER EXPRESSIONS" > .sp > Extension header expressions refer to data from variable\-sized protocol = headers, such as IPv6 extension headers, TCP options and IPv4 options\&. > .sp > nftables currently supports matching (finding) a given ipv6 extension hea= der, TCP option or IPv4 option\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBhbh\fR {\fBnexthdr\fR | \fBhdrlength\fR} > \fBfrag\fR {\fBnexthdr\fR | \fBfrag\-off\fR | \fBmore\-fragments\fR | \fB= id\fR} > \fBrt\fR {\fBnexthdr\fR | \fBhdrlength\fR | \fBtype\fR | \fBseg\-left\fR} > \fBdst\fR {\fBnexthdr\fR | \fBhdrlength\fR} > \fBmh\fR {\fBnexthdr\fR | \fBhdrlength\fR | \fBchecksum\fR | \fBtype\fR} > \fBsrh\fR {\fBflags\fR | \fBtag\fR | \fBsid\fR | \fBseg\-left\fR} > \fBtcp option\fR {\fBeol\fR | \fBnop\fR | \fBmaxseg\fR | \fBwindow\fR | \= fBsack\-perm\fR | \fBsack\fR | \fBsack0\fR | \fBsack1\fR | \fBsack2\fR | \f= Bsack3\fR | \fBtimestamp\fR} \fItcp_option_field\fR > \fBip option\fR { lsrr | ra | rr | ssrr } \fIip_option_field\fR > .fi > .if n \{\ > .RE > .\} > .sp > The following syntaxes are valid only in a relational expression with boo= lean type on right\-hand side for checking header existence only: > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBexthdr\fR {\fBhbh\fR | \fBfrag\fR | \fBrt\fR | \fBdst\fR | \fBmh\fR} > \fBtcp option\fR {\fBeol\fR | \fBnop\fR | \fBmaxseg\fR | \fBwindow\fR | \= fBsack\-perm\fR | \fBsack\fR | \fBsack0\fR | \fBsack1\fR | \fBsack2\fR | \f= Bsack3\fR | \fBtimestamp\fR} > \fBip option\fR { lsrr | ra | rr | ssrr } > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&54.\ \&IPv6 extension headers > .TS > allbox tab(:); > ltB ltB. > T{ > Keyword > T}:T{ > Description > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > hbh > T}:T{ > .sp > Hop by Hop > T} > T{ > .sp > rt > T}:T{ > .sp > Routing Header > T} > T{ > .sp > frag > T}:T{ > .sp > Fragmentation header > T} > T{ > .sp > dst > T}:T{ > .sp > dst options > T} > T{ > .sp > mh > T}:T{ > .sp > Mobility Header > T} > T{ > .sp > srh > T}:T{ > .sp > Segment Routing Header > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&55.\ \&TCP Options > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > TCP option fields > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > eol > T}:T{ > .sp > End if option list > T}:T{ > .sp > kind > T} > T{ > .sp > nop > T}:T{ > .sp > 1 Byte TCP Nop padding option > T}:T{ > .sp > kind > T} > T{ > .sp > maxseg > T}:T{ > .sp > TCP Maximum Segment Size > T}:T{ > .sp > kind, length, size > T} > T{ > .sp > window > T}:T{ > .sp > TCP Window Scaling > T}:T{ > .sp > kind, length, count > T} > T{ > .sp > sack\-perm > T}:T{ > .sp > TCP SACK permitted > T}:T{ > .sp > kind, length > T} > T{ > .sp > sack > T}:T{ > .sp > TCP Selective Acknowledgement (alias of block 0) > T}:T{ > .sp > kind, length, left, right > T} > T{ > .sp > sack0 > T}:T{ > .sp > TCP Selective Acknowledgement (block 0) > T}:T{ > .sp > kind, length, left, right > T} > T{ > .sp > sack1 > T}:T{ > .sp > TCP Selective Acknowledgement (block 1) > T}:T{ > .sp > kind, length, left, right > T} > T{ > .sp > sack2 > T}:T{ > .sp > TCP Selective Acknowledgement (block 2) > T}:T{ > .sp > kind, length, left, right > T} > T{ > .sp > sack3 > T}:T{ > .sp > TCP Selective Acknowledgement (block 3) > T}:T{ > .sp > kind, length, left, right > T} > T{ > .sp > timestamp > T}:T{ > .sp > TCP Timestamps > T}:T{ > .sp > kind, length, tsval, tsecr > T} > .TE > .sp 1 > .sp > TCP option matching also supports raw expression syntax to access arbitra= ry options: > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBtcp option\fR > .fi > .if n \{\ > .RE > .\} > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBtcp option\fR \fB@\fR\fInumber\fR\fB,\fR\fIoffset\fR\fB,\fR\fIlength\fR > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&56.\ \&IP Options > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > IP option fields > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > lsrr > T}:T{ > .sp > Loose Source Route > T}:T{ > .sp > type, length, ptr, addr > T} > T{ > .sp > ra > T}:T{ > .sp > Router Alert > T}:T{ > .sp > type, length, value > T} > T{ > .sp > rr > T}:T{ > .sp > Record Route > T}:T{ > .sp > type, length, ptr, addr > T} > T{ > .sp > ssrr > T}:T{ > .sp > Strict Source Route > T}:T{ > .sp > type, length, ptr, addr > T} > .TE > .sp 1 > .PP > \fBfinding TCP options\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > filter input tcp option sack\-perm kind 1 counter > .fi > .if n \{\ > .RE > .\} > .PP > \fBmatching IPv6 exthdr\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > ip6 filter input frag more\-fragments 1 counter > .fi > .if n \{\ > .RE > .\} > .PP > \fBfinding IP option\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > filter input ip option lsrr exists counter > .fi > .if n \{\ > .RE > .\} > .sp > .SS "CONNTRACK EXPRESSIONS" > .sp > Conntrack expressions refer to meta data of the connection tracking entry= associated with a packet\&. > .sp > There are three types of conntrack expressions\&. Some conntrack expressi= ons require the flow direction before the conntrack key, others must be use= d directly because they are direction agnostic\&. The \fBpackets\fR, \fBbyt= es\fR and \fBavgpkt\fR keywords can be used with or without a direction\&. = If the direction is omitted, the sum of the original and the reply directio= n is returned\&. The same is true for the \fBzone\fR, if a direction is giv= en, the zone is only matched if the zone id is tied to the given direction\= &. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBct\fR {\fBstate\fR | \fBdirection\fR | \fBstatus\fR | \fBmark\fR | \fB= expiration\fR | \fBhelper\fR | \fBlabel\fR} > \fBct\fR [\fBoriginal\fR | \fBreply\fR] {\fBl3proto\fR | \fBprotocol\fR |= \fBbytes\fR | \fBpackets\fR | \fBavgpkt\fR | \fBzone\fR | \fBid\fR} > \fBct\fR {\fBoriginal\fR | \fBreply\fR} {\fBproto\-src\fR | \fBproto\-dst= \fR} > \fBct\fR {\fBoriginal\fR | \fBreply\fR} {\fBip\fR | \fBip6\fR} {\fBsaddr\= fR | \fBdaddr\fR} > .fi > .if n \{\ > .RE > .\} > .sp > The conntrack\-specific types in this table are described in the sub\-sec= tion CONNTRACK TYPES above\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&57.\ \&Conntrack expressions > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > state > T}:T{ > .sp > State of the connection > T}:T{ > .sp > ct_state > T} > T{ > .sp > direction > T}:T{ > .sp > Direction of the packet relative to the connection > T}:T{ > .sp > ct_dir > T} > T{ > .sp > status > T}:T{ > .sp > Status of the connection > T}:T{ > .sp > ct_status > T} > T{ > .sp > mark > T}:T{ > .sp > Connection mark > T}:T{ > .sp > mark > T} > T{ > .sp > expiration > T}:T{ > .sp > Connection expiration time > T}:T{ > .sp > time > T} > T{ > .sp > helper > T}:T{ > .sp > Helper associated with the connection > T}:T{ > .sp > string > T} > T{ > .sp > label > T}:T{ > .sp > Connection tracking label bit or symbolic name defined in connlabel\&.con= f in the nftables include path > T}:T{ > .sp > ct_label > T} > T{ > .sp > l3proto > T}:T{ > .sp > Layer 3 protocol of the connection > T}:T{ > .sp > nf_proto > T} > T{ > .sp > saddr > T}:T{ > .sp > Source address of the connection for the given direction > T}:T{ > .sp > ipv4_addr/ipv6_addr > T} > T{ > .sp > daddr > T}:T{ > .sp > Destination address of the connection for the given direction > T}:T{ > .sp > ipv4_addr/ipv6_addr > T} > T{ > .sp > protocol > T}:T{ > .sp > Layer 4 protocol of the connection for the given direction > T}:T{ > .sp > inet_proto > T} > T{ > .sp > proto\-src > T}:T{ > .sp > Layer 4 protocol source for the given direction > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > proto\-dst > T}:T{ > .sp > Layer 4 protocol destination for the given direction > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > packets > T}:T{ > .sp > packet count seen in the given direction or sum of original and reply > T}:T{ > .sp > integer (64 bit) > T} > T{ > .sp > bytes > T}:T{ > .sp > byte count seen, see description for \fBpackets\fR keyword > T}:T{ > .sp > integer (64 bit) > T} > T{ > .sp > avgpkt > T}:T{ > .sp > average bytes per packet, see description for \fBpackets\fR keyword > T}:T{ > .sp > integer (64 bit) > T} > T{ > .sp > zone > T}:T{ > .sp > conntrack zone > T}:T{ > .sp > integer (16 bit) > T} > T{ > .sp > count > T}:T{ > .sp > number of current connections > T}:T{ > .sp > integer (32 bit) > T} > T{ > .sp > id > T}:T{ > .sp > Connection id > T}:T{ > .sp > ct_id > T} > .TE > .sp 1 > .PP > \fBrestrict the number of parallel connections to a server\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > nft add set filter ssh_flood \*(Aq{ type ipv4_addr; flags dynamic; }\*(Aq > nft add rule filter input tcp dport 22 add @ssh_flood \*(Aq{ ip saddr ct = count over 2 }\*(Aq reject > .fi > .if n \{\ > .RE > .\} > .sp > .SH "STATEMENTS" > .sp > Statements represent actions to be performed\&. They can alter control fl= ow (return, jump to a different chain, accept or drop the packet) or can pe= rform actions, such as logging, rejecting a packet, etc\&. > .sp > Statements exist in two kinds\&. Terminal statements unconditionally term= inate evaluation of the current rule, non\-terminal statements either only = conditionally or never terminate evaluation of the current rule, in other w= ords, they are passive from the ruleset evaluation perspective\&. There can= be an arbitrary amount of non\-terminal statements in a rule, but only a s= ingle terminal statement as the final statement\&. > .SS "VERDICT STATEMENT" > .sp > The verdict statement alters control flow in the ruleset and issues polic= y decisions for packets\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBaccept\fR | \fBdrop\fR | \fBqueue\fR | \fBcontinue\fR | \fBreturn\fR} > {\fBjump\fR | \fBgoto\fR} \fIchain\fR > .fi > .if n \{\ > .RE > .\} > .sp > \fBaccept\fR and \fBdrop\fR are absolute verdicts \(em they terminate rul= eset evaluation immediately\&. > .TS > tab(:); > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > \fBaccept\fR > T}:T{ > .sp > Terminate ruleset evaluation and accept the packet\&. The packet can stil= l be dropped later by another hook, for instance accept in the forward hook= still allows to drop the packet later in the postrouting hook, or another = forward base chain that has a higher priority number and is evaluated after= wards in the processing pipeline\&. > T} > T{ > .sp > \fBdrop\fR > T}:T{ > .sp > Terminate ruleset evaluation and drop the packet\&. The drop occurs insta= ntly, no further chains or hooks are evaluated\&. It is not possible to acc= ept the packet in a later chain again, as those are not evaluated anymore f= or the packet\&. > T} > T{ > .sp > \fBqueue\fR > T}:T{ > .sp > Terminate ruleset evaluation and queue the packet to userspace\&. Userspa= ce must provide a drop or accept verdict\&. In case of accept, processing r= esumes with the next base chain hook, not the rule following the queue verd= ict\&. > T} > T{ > .sp > \fBcontinue\fR > T}:T{ > .sp > Continue ruleset evaluation with the next rule\&. This is the default beh= aviour in case a rule issues no verdict\&. > T} > T{ > .sp > \fBreturn\fR > T}:T{ > .sp > Return from the current chain and continue evaluation at the next rule in= the last chain\&. If issued in a base chain, it is equivalent to the base = chain policy\&. > T} > T{ > .sp > \fBjump\fR \fIchain\fR > T}:T{ > .sp > Continue evaluation at the first rule in \fIchain\fR\&. The current posit= ion in the ruleset is pushed to a call stack and evaluation will continue t= here when the new chain is entirely evaluated or a \fBreturn\fR verdict is = issued\&. In case an absolute verdict is issued by a rule in the chain, rul= eset evaluation terminates immediately and the specific action is taken\&. > T} > T{ > .sp > \fBgoto\fR \fIchain\fR > T}:T{ > .sp > Similar to \fBjump\fR, but the current position is not pushed to the call= stack, meaning that after the new chain evaluation will continue at the la= st chain instead of the one containing the goto statement\&. > T} > .TE > .sp 1 > .PP > \fBUsing verdict statements\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # process packets from eth0 and the internal network in from_lan > # chain, drop all packets from eth0 with different source addresses\&. >=20 > filter input iif eth0 ip saddr 192\&.168\&.0\&.0/24 jump from_lan > filter input iif eth0 drop > .fi > .if n \{\ > .RE > .\} > .sp > .SS "PAYLOAD STATEMENT" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fIpayload_expression\fR \fBset\fR \fIvalue\fR > .fi > .if n \{\ > .RE > .\} > .sp > The payload statement alters packet content\&. It can be used for example= to set ip DSCP (diffserv) header field or ipv6 flow labels\&. > .PP > \fBroute some packets instead of bridging\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # redirect tcp:http from 192\&.160\&.0\&.0/16 to local machine for routin= g instead of bridging > # assumes 00:11:22:33:44:55 is local MAC address\&. > bridge input meta iif eth0 ip saddr 192\&.168\&.0\&.0/16 tcp dport 80 met= a pkttype set unicast ether daddr set 00:11:22:33:44:55 > .fi > .if n \{\ > .RE > .\} > .PP > \fBSet IPv4 DSCP header field\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > ip forward ip dscp set 42 > .fi > .if n \{\ > .RE > .\} > .sp > .SS "EXTENSION HEADER STATEMENT" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fIextension_header_expression\fR \fBset\fR \fIvalue\fR > .fi > .if n \{\ > .RE > .\} > .sp > The extension header statement alters packet content in variable\-sized h= eaders\&. This can currently be used to alter the TCP Maximum segment size = of packets, similar to TCPMSS\&. > .PP > \fBchange tcp mss\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > tcp flags syn tcp option maxseg size set 1360 > # set a size based on route information: > tcp flags syn tcp option maxseg size set rt mtu > .fi > .if n \{\ > .RE > .\} > .sp > .SS "LOG STATEMENT" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBlog\fR [\fBprefix\fR \fIquoted_string\fR] [\fBlevel\fR \fIsyslog\-leve= l\fR] [\fBflags\fR \fIlog\-flags\fR] > \fBlog\fR \fBgroup\fR \fInflog_group\fR [\fBprefix\fR \fIquoted_string\fR= ] [\fBqueue\-threshold\fR \fIvalue\fR] [\fBsnaplen\fR \fIsize\fR] > \fBlog level audit\fR > .fi > .if n \{\ > .RE > .\} > .sp > The log statement enables logging of matching packets\&. When this statem= ent is used from a rule, the Linux kernel will print some information on al= l matching packets, such as header fields, via the kernel log (where it can= be read with dmesg(1) or read in the syslog)\&. > .sp > In the second form of invocation (if \fInflog_group\fR is specified), the= Linux kernel will pass the packet to nfnetlink_log which will multicast th= e packet through a netlink socket to the specified multicast group\&. One o= r more userspace processes may subscribe to the group to receive the packet= s, see libnetfilter_queue documentation for details\&. > .sp > In the third form of invocation (if level audit is specified), the Linux = kernel writes a message into the audit buffer suitably formatted for readin= g with auditd\&. Therefore no further formatting options (such as prefix or= flags) are allowed in this mode\&. > .sp > This is a non\-terminating statement, so the rule evaluation continues af= ter the packet is logged\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&58.\ \&log statement options > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > prefix > T}:T{ > .sp > Log message prefix > T}:T{ > .sp > quoted string > T} > T{ > .sp > level > T}:T{ > .sp > Syslog level of logging > T}:T{ > .sp > string: emerg, alert, crit, err, warn [default], notice, info, debug, aud= it > T} > T{ > .sp > group > T}:T{ > .sp > NFLOG group to send messages to > T}:T{ > .sp > unsigned integer (16 bit) > T} > T{ > .sp > snaplen > T}:T{ > .sp > Length of packet payload to include in netlink message > T}:T{ > .sp > unsigned integer (32 bit) > T} > T{ > .sp > queue\-threshold > T}:T{ > .sp > Number of packets to queue inside the kernel before sending them to users= pace > T}:T{ > .sp > unsigned integer (32 bit) > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&59.\ \&log\-flags > .TS > allbox tab(:); > ltB ltB. > T{ > Flag > T}:T{ > Description > T} > .T& > lt lt > lt lt > lt lt > lt lt > lt lt > lt lt. > T{ > .sp > tcp sequence > T}:T{ > .sp > Log TCP sequence numbers\&. > T} > T{ > .sp > tcp options > T}:T{ > .sp > Log options from the TCP packet header\&. > T} > T{ > .sp > ip options > T}:T{ > .sp > Log options from the IP/IPv6 packet header\&. > T} > T{ > .sp > skuid > T}:T{ > .sp > Log the userid of the process which generated the packet\&. > T} > T{ > .sp > ether > T}:T{ > .sp > Decode MAC addresses and protocol\&. > T} > T{ > .sp > all > T}:T{ > .sp > Enable all log flags listed above\&. > T} > .TE > .sp 1 > .PP > \fBUsing log statement\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # log the UID which generated the packet and ip options > ip filter output log flags skuid flags ip options >=20 > # log the tcp sequence numbers and tcp options from the TCP packet > ip filter output log flags tcp sequence,options >=20 > # enable all supported log flags > ip6 filter output log flags all > .fi > .if n \{\ > .RE > .\} > .sp > .SS "REJECT STATEMENT" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBreject\fR [ \fBwith\fR \fIREJECT_WITH\fR ] >=20 > \fIREJECT_WITH\fR :=3D \fBicmp type\fR \fIicmp_code\fR | > \fBicmpv6 type\fR \fIicmpv6_code\fR | > \fBicmpx type\fR \fIicmpx_code\fR | > \fBtcp reset\fR > .fi > .if n \{\ > .RE > .\} > .sp > A reject statement is used to send back an error packet in response to th= e matched packet otherwise it is equivalent to drop so it is a terminating = statement, ending rule traversal\&. This statement is only valid in base ch= ains using the \fBinput\fR, \fBforward\fR or \fBoutput\fR hooks, and user\-= defined chains which are only called from those chains\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&60.\ \&different ICMP reject variants are meant for use in di= fferent table families > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Variant > T}:T{ > Family > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > icmp > T}:T{ > .sp > ip > T}:T{ > .sp > icmp_code > T} > T{ > .sp > icmpv6 > T}:T{ > .sp > ip6 > T}:T{ > .sp > icmpv6_code > T} > T{ > .sp > icmpx > T}:T{ > .sp > inet > T}:T{ > .sp > icmpx_code > T} > .TE > .sp 1 > .sp > For a description of the different types and a list of supported keywords= refer to DATA TYPES section above\&. The common default reject value is \f= Bport\-unreachable\fR\&. > .sp > Note that in bridge family, reject statement is only allowed in base chai= ns which hook into input or prerouting\&. > .SS "COUNTER STATEMENT" > .sp > A counter statement sets the hit count of packets along with the number o= f bytes\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBcounter\fR \fBpackets\fR \fInumber\fR \fBbytes\fR \fInumber\fR > \fBcounter\fR { \fBpackets\fR \fInumber\fR | \fBbytes\fR \fInumber\fR } > .fi > .if n \{\ > .RE > .\} > .SS "CONNTRACK STATEMENT" > .sp > The conntrack statement can be used to set the conntrack mark and conntra= ck labels\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBct\fR {\fBmark\fR | \fBevent\fR | \fBlabel\fR | \fBzone\fR} \fBset\fR = \fIvalue\fR > .fi > .if n \{\ > .RE > .\} > .sp > The ct statement sets meta data associated with a connection\&. The zone = id has to be assigned before a conntrack lookup takes place, i\&.e\&. this = has to be done in prerouting and possibly output (if locally generated pack= ets need to be placed in a distinct zone), with a hook priority of \-300\&. > .sp > Unlike iptables, where the helper assignment happens in the raw table, th= e helper needs to be assigned after a conntrack entry has been found, i\&.e= \&. it will not work when used with hook priorities equal or before \-200\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&61.\ \&Conntrack statement types > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Value > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > event > T}:T{ > .sp > conntrack event bits > T}:T{ > .sp > bitmask, integer (32 bit) > T} > T{ > .sp > helper > T}:T{ > .sp > name of ct helper object to assign to the connection > T}:T{ > .sp > quoted string > T} > T{ > .sp > mark > T}:T{ > .sp > Connection tracking mark > T}:T{ > .sp > mark > T} > T{ > .sp > label > T}:T{ > .sp > Connection tracking label > T}:T{ > .sp > label > T} > T{ > .sp > zone > T}:T{ > .sp > conntrack zone > T}:T{ > .sp > integer (16 bit) > T} > .TE > .sp 1 > .PP > \fBsave packet nfmark in conntrack\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > ct mark set meta mark > .fi > .if n \{\ > .RE > .\} > .PP > \fBset zone mapped via interface\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > table inet raw { > chain prerouting { > type filter hook prerouting priority \-300; > ct zone set iif map { "eth1" : 1, "veth1" : 2 } > } > chain output { > type filter hook output priority \-300; > ct zone set oif map { "eth1" : 1, "veth1" : 2 } > } > } > .fi > .if n \{\ > .RE > .\} > .PP > \fBrestrict events reported by ctnetlink\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > ct event set new,related,destroy > .fi > .if n \{\ > .RE > .\} > .sp > .SS "NOTRACK STATEMENT" > .sp > The notrack statement allows to disable connection tracking for certain p= ackets\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBnotrack\fR > .fi > .if n \{\ > .RE > .\} > .sp > Note that for this statement to be effective, it has to be applied to pac= kets before a conntrack lookup happens\&. Therefore, it needs to sit in a c= hain with either prerouting or output hook and a hook priority of \-300 or = less\&. > .sp > See SYNPROXY STATEMENT for an example usage\&. > .SS "META STATEMENT" > .sp > A meta statement sets the value of a meta expression\&. The existing meta= fields are: priority, mark, pkttype, nftrace\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBmeta\fR {\fBmark\fR | \fBpriority\fR | \fBpkttype\fR | \fBnftrace\fR} = \fBset\fR \fIvalue\fR > .fi > .if n \{\ > .RE > .\} > .sp > A meta statement sets meta data associated with a packet\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&62.\ \&Meta statement types > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Keyword > T}:T{ > Description > T}:T{ > Value > T} > .T& > lt lt lt > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > priority > T}:T{ > .sp > TC packet priority > T}:T{ > .sp > tc_handle > T} > T{ > .sp > mark > T}:T{ > .sp > Packet mark > T}:T{ > .sp > mark > T} > T{ > .sp > pkttype > T}:T{ > .sp > packet type > T}:T{ > .sp > pkt_type > T} > T{ > .sp > nftrace > T}:T{ > .sp > ruleset packet tracing on/off\&. Use \fBmonitor trace\fR command to watch= traces > T}:T{ > .sp > 0, 1 > T} > .TE > .sp 1 > .SS "LIMIT STATEMENT" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBlimit rate\fR [\fBover\fR] \fIpacket_number\fR \fB/\fR \fITIME_UNIT\fR= [\fBburst\fR \fIpacket_number\fR \fBpackets\fR] > \fBlimit rate\fR [\fBover\fR] \fIbyte_number\fR \fIBYTE_UNIT\fR \fB/\fR \= fITIME_UNIT\fR [\fBburst\fR \fIbyte_number\fR \fIBYTE_UNIT\fR] >=20 > \fITIME_UNIT\fR :=3D \fBsecond\fR | \fBminute\fR | \fBhour\fR | \fBday\fR > \fIBYTE_UNIT\fR :=3D \fBbytes\fR | \fBkbytes\fR | \fBmbytes\fR > .fi > .if n \{\ > .RE > .\} > .sp > A limit statement matches at a limited rate using a token bucket filter\&= =2E A rule using this statement will match until this limit is reached\&. I= t can be used in combination with the log statement to give limited logging= \&. The optional \fBover\fR keyword makes it match over the specified rate\= &. Default \fBburst\fR is 5\&. if you specify \fBburst\fR, it must be non\-= zero value\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&63.\ \&limit statement values > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Value > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt. > T{ > .sp > packet_number > T}:T{ > .sp > Number of packets > T}:T{ > .sp > unsigned integer (32 bit) > T} > T{ > .sp > byte_number > T}:T{ > .sp > Number of bytes > T}:T{ > .sp > unsigned integer (32 bit) > T} > .TE > .sp 1 > .SS "NAT STATEMENTS" > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBsnat to\fR \fIaddress\fR [\fB:\fR\fIport\fR] [\fIPRF_FLAGS\fR] > \fBsnat to\fR \fIaddress\fR \fB\-\fR \fIaddress\fR [\fB:\fR\fIport\fR \fB= \-\fR \fIport\fR] [\fIPRF_FLAGS\fR] > \fBsnat\fR { \fBip\fR | \fBip6\fR } \fBto\fR \fIaddress\fR \fB\-\fR \fIad= dress\fR [\fB:\fR\fIport\fR \fB\-\fR \fIport\fR] [\fIPR_FLAGS\fR] > \fBdnat to\fR \fIaddress\fR [\fB:\fR\fIport\fR] [\fIPRF_FLAGS\fR] > \fBdnat to\fR \fIaddress\fR [\fB:\fR\fIport\fR \fB\-\fR \fIport\fR] [\fIP= R_FLAGS\fR] > \fBdnat\fR { \fBip\fR | \fBip6\fR } \fBto\fR \fIaddress\fR [\fB:\fR\fIpor= t\fR \fB\-\fR \fIport\fR] [\fIPR_FLAGS\fR] > \fBmasquerade to\fR [\fB:\fR\fIport\fR] [\fIPRF_FLAGS\fR] > \fBmasquerade to\fR [\fB:\fR\fIport\fR \fB\-\fR \fIport\fR] [\fIPRF_FLAGS= \fR] > \fBredirect to\fR [\fB:\fR\fIport\fR] [\fIPRF_FLAGS\fR] > \fBredirect to\fR [\fB:\fR\fIport\fR \fB\-\fR \fIport\fR] [\fIPRF_FLAGS\f= R] >=20 > \fIPRF_FLAGS\fR :=3D \fIPRF_FLAG\fR [\fB,\fR \fIPRF_FLAGS\fR] > \fIPR_FLAGS\fR :=3D \fIPR_FLAG\fR [\fB,\fR \fIPR_FLAGS\fR] > \fIPRF_FLAG\fR :=3D \fIPR_FLAG\fR | \fBfully\-random\fR > \fIPR_FLAG\fR :=3D \fBpersistent\fR | \fBrandom\fR > .fi > .if n \{\ > .RE > .\} > .sp > The nat statements are only valid from nat chain types\&. > .sp > The \fBsnat\fR and \fBmasquerade\fR statements specify that the source ad= dress of the packet should be modified\&. While \fBsnat\fR is only valid in= the postrouting and input chains, \fBmasquerade\fR makes sense only in pos= trouting\&. The dnat and redirect statements are only valid in the prerouti= ng and output chains, they specify that the destination address of the pack= et should be modified\&. You can use non\-base chains which are called from= base chains of nat chain type too\&. All future packets in this connection= will also be mangled, and rules should cease being examined\&. > .sp > The \fBmasquerade\fR statement is a special form of snat which always use= s the outgoing interface\(cqs IP address to translate to\&. It is particula= rly useful on gateways with dynamic (public) IP addresses\&. > .sp > The \fBredirect\fR statement is a special form of dnat which always trans= lates the destination address to the local host\(cqs one\&. It comes in han= dy if one only wants to alter the destination port of incoming traffic on d= ifferent interfaces\&. > .sp > When used in the inet family (available with kernel 5\&.2), the dnat and = snat statements require the use of the ip and ip6 keyword in case an addres= s is provided, see the examples below\&. > .sp > Before kernel 4\&.18 nat statements require both prerouting and postrouti= ng base chains to be present since otherwise packets on the return path won= \(cqt be seen by netfilter and therefore no reverse translation will take p= lace\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&64.\ \&NAT statement values > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Expression > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt. > T{ > .sp > address > T}:T{ > .sp > Specifies that the source/destination address of the packet should be mod= ified\&. You may specify a mapping to relate a list of tuples composed of a= rbitrary expression key with address value\&. > T}:T{ > .sp > ipv4_addr, ipv6_addr, e\&.g\&. abcd::1234, or you can use a mapping, e\&.= g\&. meta mark map { 10 : 192\&.168\&.1\&.2, 20 : 192\&.168\&.1\&.3 } > T} > T{ > .sp > port > T}:T{ > .sp > Specifies that the source/destination address of the packet should be mod= ified\&. > T}:T{ > .sp > port number (16 bit) > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&65.\ \&NAT statement flags > .TS > allbox tab(:); > ltB ltB. > T{ > Flag > T}:T{ > Description > T} > .T& > lt lt > lt lt > lt lt. > T{ > .sp > persistent > T}:T{ > .sp > Gives a client the same source\-/destination\-address for each connection= \&. > T} > T{ > .sp > random > T}:T{ > .sp > In kernel 5\&.0 and newer this is the same as fully\-random\&. In earlier= kernels the port mapping will be randomized using a seeded MD5 hash mix us= ing source and destination address and destination port\&. > T} > T{ > .sp > fully\-random > T}:T{ > .sp > If used then port mapping is generated based on a 32\-bit pseudo\-random = algorithm\&. > T} > .TE > .sp 1 > .PP > \fBUsing NAT statements\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # create a suitable table/chain setup for all further examples > add table nat > add chain nat prerouting { type nat hook prerouting priority 0; } > add chain nat postrouting { type nat hook postrouting priority 100; } >=20 > # translate source addresses of all packets leaving via eth0 to address 1= \&.2\&.3\&.4 > add rule nat postrouting oif eth0 snat to 1\&.2\&.3\&.4 >=20 > # redirect all traffic entering via eth0 to destination address 192\&.168= \&.1\&.120 > add rule nat prerouting iif eth0 dnat to 192\&.168\&.1\&.120 >=20 > # translate source addresses of all packets leaving via eth0 to whatever > # locally generated packets would use as source to reach the same destina= tion > add rule nat postrouting oif eth0 masquerade >=20 > # redirect incoming TCP traffic for port 22 to port 2222 > add rule nat prerouting tcp dport 22 redirect to :2222 >=20 > # inet family: > # handle ip dnat: > add rule inet nat prerouting dnat ip to 10\&.0\&.2\&.99 > # handle ip6 dnat: > add rule inet nat prerouting dnat ip6 to fe80::dead > # this masquerades both ipv4 and ipv6: > add rule inet nat postrouting meta oif ppp0 masquerade > .fi > .if n \{\ > .RE > .\} > .sp > .SS "TPROXY STATEMENT" > .sp > Tproxy redirects the packet to a local socket without changing the packet= header in any way\&. If any of the arguments is missing the data of the in= coming packet is used as parameter\&. Tproxy matching requires another rule= that ensures the presence of transport protocol header is specified\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBtproxy to\fR \fIaddress\fR\fB:\fR\fIport\fR > \fBtproxy to\fR {\fIaddress\fR | \fB:\fR\fIport\fR} > .fi > .if n \{\ > .RE > .\} > .sp > This syntax can be used in \fBip/ip6\fR tables where network layer protoc= ol is obvious\&. Either IP address or port can be specified, but at least o= ne of them is necessary\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBtproxy\fR {\fBip\fR | \fBip6\fR} \fBto\fR \fIaddress\fR[\fB:\fR\fIport= \fR] > \fBtproxy to :\fR\fIport\fR > .fi > .if n \{\ > .RE > .\} > .sp > This syntax can be used in \fBinet\fR tables\&. The \fBip/ip6\fR paramete= r defines the family the rule will match\&. The \fBaddress\fR parameter mus= t be of this family\&. When only \fBport\fR is defined, the address family = should not be specified\&. In this case the rule will match for both famili= es\&. > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&66.\ \&tproxy attributes > .TS > allbox tab(:); > ltB ltB. > T{ > Name > T}:T{ > Description > T} > .T& > lt lt > lt lt. > T{ > .sp > address > T}:T{ > .sp > IP address the listening socket with IP_TRANSPARENT option is bound to\&. > T} > T{ > .sp > port > T}:T{ > .sp > Port the listening socket with IP_TRANSPARENT option is bound to\&. > T} > .TE > .sp 1 > .PP > \fBExample ruleset for tproxy statement\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > table ip x { > chain y { > type filter hook prerouting priority \-150; policy accept; > tcp dport ntp tproxy to 1\&.1\&.1\&.1 > udp dport ssh tproxy to :2222 > } > } > table ip6 x { > chain y { > type filter hook prerouting priority \-150; policy accept; > tcp dport ntp tproxy to [dead::beef] > udp dport ssh tproxy to :2222 > } > } > table inet x { > chain y { > type filter hook prerouting priority \-150; policy accept; > tcp dport 321 tproxy to :ssh > tcp dport 99 tproxy ip to 1\&.1\&.1\&.1:999 > udp dport 155 tproxy ip6 to [dead::beef]:smux > } > } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "SYNPROXY STATEMENT" > .sp > This statement will process TCP three\-way\-handshake parallel in netfilt= er context to protect either local or backend system\&. This statement requ= ires connection tracking because sequence numbers need to be translated\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBsynproxy\fR [\fBmss\fR \fImss_value\fR] [\fBwscale\fR \fIwscale_value\= fR] [\fISYNPROXY_FLAGS\fR] > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&67.\ \&synproxy statement attributes > .TS > allbox tab(:); > ltB ltB. > T{ > Name > T}:T{ > Description > T} > .T& > lt lt > lt lt. > T{ > .sp > mss > T}:T{ > .sp > Maximum segment size announced to clients\&. This must match the backend\= &. > T} > T{ > .sp > wscale > T}:T{ > .sp > Window scale announced to clients\&. This must match the backend\&. > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&68.\ \&synproxy statement flags > .TS > allbox tab(:); > ltB ltB. > T{ > Flag > T}:T{ > Description > T} > .T& > lt lt > lt lt. > T{ > .sp > sack\-perm > T}:T{ > .sp > Pass client selective acknowledgement option to backend (will be disabled= if not present)\&. > T} > T{ > .sp > timestamp > T}:T{ > .sp > Pass client timestamp option to backend (will be disabled if not present,= also needed for selective acknowledgement and window scaling)\&. > T} > .TE > .sp 1 > .PP > \fBExample ruleset for synproxy statement\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > Determine tcp options used by backend, from an external system >=20 > tcpdump \-pni eth0 \-c 1 \*(Aqtcp[tcpflags] =3D=3D (tcp\-sy= n|tcp\-ack)\*(Aq > port 80 & > telnet 192\&.0\&.2\&.42 80 > 18:57:24\&.693307 IP 192\&.0\&.2\&.42\&.80 > 192\&.0\&.2\&.= 43\&.48757: > Flags [S\&.], seq 360414582, ack 788841994, win 14480, > options [mss 1460,sackOK, > TS val 1409056151 ecr 9690221, > nop,wscale 9], > length 0 >=20 > Switch tcp_loose mode off, so conntrack will mark out\-of\-flow packets a= s state INVALID\&. >=20 > echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose >=20 > Make SYN packets untracked\&. >=20 > table ip x { > chain y { > type filter hook prerouting priority raw; policy = accept; > tcp flags syn notrack > } > } >=20 > Catch UNTRACKED (SYN packets) and INVALID (3WHS ACK packets) states and = send > them to SYNPROXY\&. This rule will respond to SYN packets with SYN+ACK > syncookies, create ESTABLISHED for valid client response (3WHS ACK packet= s) and > drop incorrect cookies\&. Flags combinations not expected during 3WHS wi= ll not > match and continue (e\&.g\&. SYN+FIN, SYN+ACK)\&. Finally, drop invalid p= ackets, this > will be out\-of\-flow packets that were not matched by SYNPROXY\&. >=20 > table ip foo { > chain z { > type filter hook input priority filter; policy accept; > ct state { invalid, untracked } synproxy mss 1460 wsc= ale 9 timestamp sack\-perm > ct state invalid drop > } > } >=20 > The outcome ruleset of the steps above should be similar to the one below= \&. >=20 > table ip x { > chain y { > type filter hook prerouting priority raw; policy = accept; > tcp flags syn notrack > } >=20 > chain z { > type filter hook input priority filter; policy ac= cept; > ct state { invalid, untracked } synproxy mss 1460= wscale 9 timestamp sack\-perm > ct state invalid drop > } > } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "FLOW STATEMENT" > .sp > A flow statement allows us to select what flows you want to accelerate fo= rwarding through layer 3 network stack bypass\&. You have to specify the fl= owtable name where you want to offload this flow\&. > .sp > \fBflow add @\fR\fIflowtable\fR > .SS "QUEUE STATEMENT" > .sp > This statement passes the packet to userspace using the nfnetlink_queue h= andler\&. The packet is put into the queue identified by its 16\-bit queue = number\&. Userspace can inspect and modify the packet if desired\&. Userspa= ce must then drop or re\-inject the packet into the kernel\&. See libnetfil= ter_queue documentation for details\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBqueue\fR [\fBnum\fR \fIqueue_number\fR] [\fBbypass\fR] > \fBqueue\fR [\fBnum\fR \fIqueue_number_from\fR \- \fIqueue_number_to\fR] = [\fIQUEUE_FLAGS\fR] >=20 > \fIQUEUE_FLAGS\fR :=3D \fIQUEUE_FLAG\fR [\fB,\fR \fIQUEUE_FLAGS\fR] > \fIQUEUE_FLAG\fR :=3D \fBbypass\fR | \fBfanout\fR > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&69.\ \&queue statement values > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Value > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt > lt lt lt. > T{ > .sp > queue_number > T}:T{ > .sp > Sets queue number, default is 0\&. > T}:T{ > .sp > unsigned integer (16 bit) > T} > T{ > .sp > queue_number_from > T}:T{ > .sp > Sets initial queue in the range, if fanout is used\&. > T}:T{ > .sp > unsigned integer (16 bit) > T} > T{ > .sp > queue_number_to > T}:T{ > .sp > Sets closing queue in the range, if fanout is used\&. > T}:T{ > .sp > unsigned integer (16 bit) > T} > .TE > .sp 1 > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&70.\ \&queue statement flags > .TS > allbox tab(:); > ltB ltB. > T{ > Flag > T}:T{ > Description > T} > .T& > lt lt > lt lt. > T{ > .sp > bypass > T}:T{ > .sp > Let packets go through if userspace application cannot back off\&. Before= using this flag, read libnetfilter_queue documentation for performance tun= ing recommendations\&. > T} > T{ > .sp > fanout > T}:T{ > .sp > Distribute packets between several queues\&. > T} > .TE > .sp 1 > .SS "DUP STATEMENT" > .sp > The dup statement is used to duplicate a packet and send the copy to a di= fferent destination\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fBdup to\fR \fIdevice\fR > \fBdup to\fR \fIaddress\fR \fBdevice\fR \fIdevice\fR > .fi > .if n \{\ > .RE > .\} > .sp > .it 1 an-trap > .nr an-no-space-flag 1 > .nr an-break-flag 1 > .br > .B Table\ \&71.\ \&Dup statement values > .TS > allbox tab(:); > ltB ltB ltB. > T{ > Expression > T}:T{ > Description > T}:T{ > Type > T} > .T& > lt lt lt > lt lt lt. > T{ > .sp > address > T}:T{ > .sp > Specifies that the copy of the packet should be sent to a new gateway\&. > T}:T{ > .sp > ipv4_addr, ipv6_addr, e\&.g\&. abcd::1234, or you can use a mapping, e\&.= g\&. ip saddr map { 192\&.168\&.1\&.2 : 10\&.1\&.1\&.1 } > T} > T{ > .sp > device > T}:T{ > .sp > Specifies that the copy should be transmitted via device\&. > T}:T{ > .sp > string > T} > .TE > .sp 1 > .PP > \fBUsing the dup statement\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # send to machine with ip address 10\&.2\&.3\&.4 on eth0 > ip filter forward dup to 10\&.2\&.3\&.4 device "eth0" >=20 > # copy raw frame to another interface > netdetv ingress dup to "eth0" > dup to "eth0" >=20 > # combine with map dst addr to gateways > dup to ip daddr map { 192\&.168\&.7\&.1 : "eth0", 192\&.168\&.7\&.2 : "et= h1" } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "FWD STATEMENT" > .sp > The fwd statement is used to redirect a raw packet to another interface\&= =2E It is only available in the netdev family ingress hook\&. It is similar= to the dup statement except that no copy is made\&. > .sp > \fBfwd to\fR \fIdevice\fR > .SS "SET STATEMENT" > .sp > The set statement is used to dynamically add or update elements in a set = =66rom the packet path\&. The set setname must already exist in the given t= able and must have been created with one or both of the dynamic and the tim= eout flags\&. The dynamic flag is required if the set statement expression = includes a stateful object\&. The timeout flag is implied if the set is cre= ated with a timeout, and is required if the set statement updates elements,= rather than adding them\&. Furthermore, these sets should specify both a m= aximum set size (to prevent memory exhaustion), and their elements should h= ave a timeout (so their number will not grow indefinitely) either from the = set definition or from the statement that adds or updates them\&. The set s= tatement can be used to e\&.g\&. create dynamic blacklists\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > {\fBadd\fR | \fBupdate\fR} \fB@\fR\fIsetname\fR \fB{\fR \fIexpression\fR = [\fBtimeout\fR \fItimeout\fR] [\fBcomment\fR \fIstring\fR] \fB}\fR > .fi > .if n \{\ > .RE > .\} > .PP > \fBExample for simple blacklist\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # declare a set, bound to table "filter", in family "ip"\&. > # Timeout and size are mandatory because we will add elements from packet= path\&. > # Entries will timeout after one minute, after which they might be > # re\-added if limit condition persists\&. > nft add set ip filter blackhole \e > "{ type ipv4_addr; flags dynamic; timeout 1m; size 65536; }" >=20 > # declare a set to store the limit per saddr\&. > # This must be separate from blackhole since the timeout is different > nft add set ip filter flood \e > "{ type ipv4_addr; flags dynamic; timeout 10s; size 128000; }" >=20 > # whitelist internal interface\&. > nft add rule ip filter input meta iifname "internal" accept >=20 > # drop packets coming from blacklisted ip addresses\&. > nft add rule ip filter input ip saddr @blackhole counter drop >=20 > # add source ip addresses to the blacklist if more than 10 tcp connection > # requests occurred per second and ip address\&. > nft add rule ip filter input tcp flags syn tcp dport ssh \e > add @flood { ip saddr limit rate over 10/second } \e > add @blackhole { ip saddr } drop >=20 > # inspect state of the sets\&. > nft list set ip filter flood > nft list set ip filter blackhole >=20 > # manually add two addresses to the blackhole\&. > nft add element filter blackhole { 10\&.2\&.3\&.4, 10\&.23\&.1\&.42 } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "MAP STATEMENT" > .sp > The map statement is used to lookup data based on some specific input key= \&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fIexpression\fR \fBmap\fR \fB{\fR \fIMAP_ELEMENTS\fR \fB}\fR >=20 > \fIMAP_ELEMENTS\fR :=3D \fIMAP_ELEMENT\fR [\fB,\fR \fIMAP_ELEMENTS\fR] > \fIMAP_ELEMENT\fR :=3D \fIkey\fR \fB:\fR \fIvalue\fR > .fi > .if n \{\ > .RE > .\} > .sp > The \fIkey\fR is a value returned by \fIexpression\fR\&. > .PP > \fBUsing the map statement\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # select DNAT target based on TCP dport: > # connections to port 80 are redirected to 192\&.168\&.1\&.100, > # connections to port 8888 are redirected to 192\&.168\&.1\&.101 > nft add rule ip nat prerouting dnat tcp dport map { 80 : 192\&.168\&.1\&.= 100, 8888 : 192\&.168\&.1\&.101 } >=20 > # source address based SNAT: > # packets from net 192\&.168\&.1\&.0/24 will appear as originating from 1= 0\&.0\&.0\&.1, > # packets from net 192\&.168\&.2\&.0/24 will appear as originating from 1= 0\&.0\&.0\&.2 > nft add rule ip nat postrouting snat to ip saddr map { 192\&.168\&.1\&.0/= 24 : 10\&.0\&.0\&.1, 192\&.168\&.2\&.0/24 : 10\&.0\&.0\&.2 } > .fi > .if n \{\ > .RE > .\} > .sp > .SS "VMAP STATEMENT" > .sp > The verdict map (vmap) statement works analogous to the map statement, bu= t contains verdicts as values\&. > .sp > .if n \{\ > .RS 4 > .\} > .nf > \fIexpression\fR \fBvmap\fR \fB{\fR \fIVMAP_ELEMENTS\fR \fB}\fR >=20 > \fIVMAP_ELEMENTS\fR :=3D \fIVMAP_ELEMENT\fR [\fB,\fR \fIVMAP_ELEMENTS\fR] > \fIVMAP_ELEMENT\fR :=3D \fIkey\fR \fB:\fR \fIverdict\fR > .fi > .if n \{\ > .RE > .\} > .PP > \fBUsing the vmap statement\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > # jump to different chains depending on layer 4 protocol type: > nft add rule ip filter input ip protocol vmap { tcp : jump tcp\-chain, ud= p : jump udp\-chain , icmp : jump icmp\-chain } > .fi > .if n \{\ > .RE > .\} > .sp > .SH "ADDITIONAL COMMANDS" > .sp > These are some additional commands included in nft\&. > .SS "MONITOR" > .sp > The monitor command allows you to listen to Netlink events produced by th= e nf_tables subsystem, related to creation and deletion of objects\&. When = they occur, nft will print to stdout the monitored events in either JSON or= native nft format\&. > .sp > To filter events related to a concrete object, use one of the keywords \f= Itables\fR, \fIchains\fR, \fIsets\fR, \fIrules\fR, \fIelements\fR, \fIrules= et\fR\&. > .sp > To filter events related to a concrete action, use keyword \fInew\fR or \= fIdestroy\fR\&. > .sp > Hit ^C to finish the monitor operation\&. > .PP > \fBListen to all events, report in native nft format\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > % nft monitor > .fi > .if n \{\ > .RE > .\} > .PP > \fBListen to deleted rules, report in JSON format\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > % nft \-j monitor destroy rules > .fi > .if n \{\ > .RE > .\} > .PP > \fBListen to both new and destroyed chains, in native nft format\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > % nft monitor chains > .fi > .if n \{\ > .RE > .\} > .PP > \fBListen to ruleset events such as table, chain, rule, set, counters and= quotas, in native nft format\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > % nft monitor ruleset > .fi > .if n \{\ > .RE > .\} > .sp > .SH "ERROR REPORTING" > .sp > When an error is detected, nft shows the line(s) containing the error, th= e position of the erroneous parts in the input stream and marks up the erro= neous parts using carets (^)\&. If the error results from the combination o= f two expressions or statements, the part imposing the constraints which ar= e violated is marked using tildes (~)\&. > .sp > For errors returned by the kernel, nft cannot detect which parts of the i= nput caused the error and the entire command is marked\&. > .PP > \fBError caused by single incorrect expression\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > :1:19\-22: Error: Interface does not exist > filter output oif eth0 > ^^^^ > .fi > .if n \{\ > .RE > .\} > .PP > \fBError caused by invalid combination of two expressions\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > :1:28\-36: Error: Right hand side of relational expression (=3D= =3D) must be constant > filter output tcp dport =3D=3D tcp dport > ~~ ^^^^^^^^^ > .fi > .if n \{\ > .RE > .\} > .PP > \fBError returned by the kernel\fR.=20 > .sp > .if n \{\ > .RS 4 > .\} > .nf > :0:0\-23: Error: Could not process rule: Operation not permitted > filter output oif wlan0 > ^^^^^^^^^^^^^^^^^^^^^^^ > .fi > .if n \{\ > .RE > .\} > .sp > .SH "EXIT STATUS" > .sp > On success, nft exits with a status of 0\&. Unspecified errors cause it t= o exit with a status of 1, memory allocation errors with a status of 2, una= ble to open Netlink socket with 3\&. > .SH "SEE ALSO" > .sp > .if n \{\ > .RS 4 > .\} > .nf > libnftables(3), libnftables\-json(5), iptables(8), ip6tables(8), arptable= s(8), ebtables(8), ip(8), tc(8) > .fi > .if n \{\ > .RE > .\} > .sp > There is an official wiki at: https://wiki\&.nftables\&.org > .SH "AUTHORS" > .sp > nftables was written by Patrick McHardy and Pablo Neira Ayuso, among many= other contributors from the Netfilter community\&. > .SH "COPYRIGHT" > .sp > Copyright \(co 2008\-2014 Patrick McHardy Copyright \= (co 2013\-2018 Pablo Neira Ayuso > .sp > nftables is free software; you can redistribute it and/or modify it under= the terms of the GNU General Public License version 2 as published by the = Free Software Foundation\&. > .sp > This documentation is licensed under the terms of the Creative Commons At= tribution\-ShareAlike 4\&.0 license, CC BY\-SA 4\&.0 http://creativecommons= \&.org/licenses/by\-sa/4\&.0/\&. -- To unsubscribe send an email to discuss+unsubscribe@mandoc.bsd.lv