diff options
Diffstat (limited to 'doc/payload-expression.txt')
-rw-r--r-- | doc/payload-expression.txt | 316 |
1 files changed, 290 insertions, 26 deletions
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt index 4bbf8d05..c7c267da 100644 --- a/doc/payload-expression.txt +++ b/doc/payload-expression.txt @@ -21,7 +21,15 @@ ether_type VLAN HEADER EXPRESSION ~~~~~~~~~~~~~~~~~~~~~~ [verse] -*vlan* {*id* | *cfi* | *pcp* | *type*} +*vlan* {*id* | *dei* | *pcp* | *type*} + +The vlan expression is used to match on the vlan header fields. +This expression will not work in the *ip*, *ip6* and *inet* families, +unless the vlan interface is configured with the *reorder_hdr off* setting. +The default is *reorder_hdr on* which will automatically remove the vlan tag +from the packet. See ip-link(8) for more information. +For these families its easier to match the vlan interface name +instead, using the *meta iif* or *meta iifname* expression. .VLAN header expression [options="header"] @@ -30,8 +38,8 @@ VLAN HEADER EXPRESSION |id| VLAN ID (VID) | integer (12 bit) -|cfi| -Canonical Format Indicator| +|dei| +Drop Eligible Indicator| integer (1 bit) |pcp| Priority code point| @@ -126,6 +134,14 @@ Destination address | ipv4_addr |====================== +Careful with matching on *ip length*: If GRO/GSO is enabled, then the Linux +kernel might aggregate several packets into one big packet that is larger than +MTU. Moreover, if GRO/GSO maximum size is larger than 65535 (see man ip-link(8), +specifically gro_ipv6_max_size and gso_ipv6_max_size), then *ip length* might +be 0 for such jumbo packets. *meta length* allows you to match on the packet +length including the IP header size. If you want to perform heuristics on the +*ip length* field, then disable GRO/GSO. + ICMP HEADER EXPRESSION ~~~~~~~~~~~~~~~~~~~~~~ [verse] @@ -236,6 +252,14 @@ Destination address | ipv6_addr |======================= +Careful with matching on *ip6 length*: If GRO/GSO is enabled, then the Linux +kernel might aggregate several packets into one big packet that is larger than +MTU. Moreover, if GRO/GSO maximum size is larger than 65535 (see man ip-link(8), +specifically gro_ipv6_max_size and gso_ipv6_max_size), then *ip6 length* might +be 0 for such jumbo packets. *meta length* allows you to match on the packet +length including the IP header size. If you want to perform heuristics on the +*ip6 length* field, then disable GRO/GSO. + .Using ip6 header expressions ----------------------------- # matching if first extension header indicates a fragment @@ -245,7 +269,7 @@ ip6 nexthdr ipv6-frag ICMPV6 HEADER EXPRESSION ~~~~~~~~~~~~~~~~~~~~~~~~ [verse] -*icmpv6* {*type* | *code* | *checksum* | *parameter-problem* | *packet-too-big* | *id* | *sequence* | *max-delay*} +*icmpv6* {*type* | *code* | *checksum* | *parameter-problem* | *packet-too-big* | *id* | *sequence* | *max-delay* | *taddr* | *daddr*} This expression refers to ICMPv6 header fields. When using it in *inet*, *bridge* or *netdev* families, it will cause an implicit dependency on IPv6 to @@ -280,6 +304,12 @@ integer (16 bit) |max-delay| maximum response delay of MLD queries| integer (16 bit) +|taddr| +target address of neighbor solicit/advert, redirect or MLD| +ipv6_addr +|daddr| +destination address of redirect| +ipv6_addr |============================== TCP HEADER EXPRESSION @@ -369,7 +399,33 @@ integer (16 bit) SCTP HEADER EXPRESSION ~~~~~~~~~~~~~~~~~~~~~~~ [verse] +____ *sctp* {*sport* | *dport* | *vtag* | *checksum*} +*sctp chunk* 'CHUNK' [ 'FIELD' ] + +'CHUNK' := *data* | *init* | *init-ack* | *sack* | *heartbeat* | + *heartbeat-ack* | *abort* | *shutdown* | *shutdown-ack* | *error* | + *cookie-echo* | *cookie-ack* | *ecne* | *cwr* | *shutdown-complete* + | *asconf-ack* | *forward-tsn* | *asconf* + +'FIELD' := 'COMMON_FIELD' | 'DATA_FIELD' | 'INIT_FIELD' | 'INIT_ACK_FIELD' | + 'SACK_FIELD' | 'SHUTDOWN_FIELD' | 'ECNE_FIELD' | 'CWR_FIELD' | + 'ASCONF_ACK_FIELD' | 'FORWARD_TSN_FIELD' | 'ASCONF_FIELD' + +'COMMON_FIELD' := *type* | *flags* | *length* +'DATA_FIELD' := *tsn* | *stream* | *ssn* | *ppid* +'INIT_FIELD' := *init-tag* | *a-rwnd* | *num-outbound-streams* | + *num-inbound-streams* | *initial-tsn* +'INIT_ACK_FIELD' := 'INIT_FIELD' +'SACK_FIELD' := *cum-tsn-ack* | *a-rwnd* | *num-gap-ack-blocks* | + *num-dup-tsns* +'SHUTDOWN_FIELD' := *cum-tsn-ack* +'ECNE_FIELD' := *lowest-tsn* +'CWR_FIELD' := *lowest-tsn* +'ASCONF_ACK_FIELD' := *seqno* +'FORWARD_TSN_FIELD' := *new-cum-tsn* +'ASCONF_FIELD' := *seqno* +____ .SCTP header expression [options="header"] @@ -387,12 +443,39 @@ integer (32 bit) |checksum| Checksum| integer (32 bit) +|chunk| +Search chunk in packet| +without 'FIELD', boolean indicating existence |================ +.SCTP chunk fields +[options="header"] +|================== +|Name| Width in bits | Chunk | Notes +|type| 8 | all | not useful, defined by chunk type +|flags| 8 | all | semantics defined on per-chunk basis +|length| 16 | all | length of this chunk in bytes excluding padding +|tsn| 32 | data | transmission sequence number +|stream| 16 | data | stream identifier +|ssn| 16 | data | stream sequence number +|ppid| 32 | data | payload protocol identifier +|init-tag| 32 | init, init-ack | initiate tag +|a-rwnd| 32 | init, init-ack, sack | advertised receiver window credit +|num-outbound-streams| 16 | init, init-ack | number of outbound streams +|num-inbound-streams| 16 | init, init-ack | number of inbound streams +|initial-tsn| 32 | init, init-ack | initial transmit sequence number +|cum-tsn-ack| 32 | sack, shutdown | cumulative transmission sequence number acknowledged +|num-gap-ack-blocks| 16 | sack | number of Gap Ack Blocks included +|num-dup-tsns| 16 | sack | number of duplicate transmission sequence numbers received +|lowest-tsn| 32 | ecne, cwr | lowest transmission sequence number +|seqno| 32 | asconf-ack, asconf | sequence number +|new-cum-tsn| 32 | forward-tsn | new cumulative transmission sequence number +|================== + DCCP HEADER EXPRESSION ~~~~~~~~~~~~~~~~~~~~~~ [verse] -*dccp* {*sport* | *dport*} +*dccp* {*sport* | *dport* | *type*} .DCCP header expression [options="header"] @@ -404,6 +487,9 @@ inet_service |dport| Destination port| inet_service +|type| +Packet type| +dccp_pkttype |======================== AUTHENTICATION HEADER EXPRESSION @@ -468,6 +554,160 @@ compression Parameter Index | integer (16 bit) |============================ +GRE HEADER EXPRESSION +~~~~~~~~~~~~~~~~~~~~~~~ +[verse] +*gre* {*flags* | *version* | *protocol*} +*gre* *ip* {*version* | *hdrlength* | *dscp* | *ecn* | *length* | *id* | *frag-off* | *ttl* | *protocol* | *checksum* | *saddr* | *daddr* } +*gre* *ip6* {*version* | *dscp* | *ecn* | *flowlabel* | *length* | *nexthdr* | *hoplimit* | *saddr* | *daddr*} + +The gre expression is used to match on the gre header fields. This expression +also allows to match on the IPv4 or IPv6 packet within the gre header. + +.GRE header expression +[options="header"] +|================== +|Keyword| Description| Type +|flags| +checksum, routing, key, sequence and strict source route flags| +integer (5 bit) +|version| +gre version field, 0 for GRE and 1 for PPTP| +integer (3 bit) +|protocol| +EtherType of encapsulated packet| +integer (16 bit) +|================== + +.Matching inner IPv4 destination address encapsulated in gre +------------------------------------------------------------ +netdev filter ingress gre ip daddr 9.9.9.9 counter +------------------------------------------------------------ + +GENEVE HEADER EXPRESSION +~~~~~~~~~~~~~~~~~~~~~~~~ +[verse] +*geneve* {*vni* | *flags*} +*geneve* *ether* {*daddr* | *saddr* | *type*} +*geneve* *vlan* {*id* | *dei* | *pcp* | *type*} +*geneve* *ip* {*version* | *hdrlength* | *dscp* | *ecn* | *length* | *id* | *frag-off* | *ttl* | *protocol* | *checksum* | *saddr* | *daddr* } +*geneve* *ip6* {*version* | *dscp* | *ecn* | *flowlabel* | *length* | *nexthdr* | *hoplimit* | *saddr* | *daddr*} +*geneve* *tcp* {*sport* | *dport* | *sequence* | *ackseq* | *doff* | *reserved* | *flags* | *window* | *checksum* | *urgptr*} +*geneve* *udp* {*sport* | *dport* | *length* | *checksum*} + +The geneve expression is used to match on the geneve header fields. The geneve +header encapsulates a ethernet frame within a *udp* packet. This expression +requires that you restrict the matching to *udp* packets (usually at +port 6081 according to IANA-assigned ports). + +.GENEVE header expression +[options="header"] +|================== +|Keyword| Description| Type +|protocol| +EtherType of encapsulated packet| +integer (16 bit) +|vni| +Virtual Network ID (VNI)| +integer (24 bit) +|================== + +.Matching inner TCP destination port encapsulated in geneve +---------------------------------------------------------- +netdev filter ingress udp dport 4789 geneve tcp dport 80 counter +---------------------------------------------------------- + +GRETAP HEADER EXPRESSION +~~~~~~~~~~~~~~~~~~~~~~~~ +[verse] +*gretap* {*vni* | *flags*} +*gretap* *ether* {*daddr* | *saddr* | *type*} +*gretap* *vlan* {*id* | *dei* | *pcp* | *type*} +*gretap* *ip* {*version* | *hdrlength* | *dscp* | *ecn* | *length* | *id* | *frag-off* | *ttl* | *protocol* | *checksum* | *saddr* | *daddr* } +*gretap* *ip6* {*version* | *dscp* | *ecn* | *flowlabel* | *length* | *nexthdr* | *hoplimit* | *saddr* | *daddr*} +*gretap* *tcp* {*sport* | *dport* | *sequence* | *ackseq* | *doff* | *reserved* | *flags* | *window* | *checksum* | *urgptr*} +*gretap* *udp* {*sport* | *dport* | *length* | *checksum*} + +The gretap expression is used to match on the encapsulated ethernet frame +within the gre header. Use the *gre* expression to match on the *gre* header +fields. + +.Matching inner TCP destination port encapsulated in gretap +---------------------------------------------------------- +netdev filter ingress gretap tcp dport 80 counter +---------------------------------------------------------- + +VXLAN HEADER EXPRESSION +~~~~~~~~~~~~~~~~~~~~~~~ +[verse] +*vxlan* {*vni* | *flags*} +*vxlan* *ether* {*daddr* | *saddr* | *type*} +*vxlan* *vlan* {*id* | *dei* | *pcp* | *type*} +*vxlan* *ip* {*version* | *hdrlength* | *dscp* | *ecn* | *length* | *id* | *frag-off* | *ttl* | *protocol* | *checksum* | *saddr* | *daddr* } +*vxlan* *ip6* {*version* | *dscp* | *ecn* | *flowlabel* | *length* | *nexthdr* | *hoplimit* | *saddr* | *daddr*} +*vxlan* *tcp* {*sport* | *dport* | *sequence* | *ackseq* | *doff* | *reserved* | *flags* | *window* | *checksum* | *urgptr*} +*vxlan* *udp* {*sport* | *dport* | *length* | *checksum*} + +The vxlan expression is used to match on the vxlan header fields. The vxlan +header encapsulates a ethernet frame within a *udp* packet. This expression +requires that you restrict the matching to *udp* packets (usually at +port 4789 according to IANA-assigned ports). + +.VXLAN header expression +[options="header"] +|================== +|Keyword| Description| Type +|flags| +vxlan flags| +integer (8 bit) +|vni| +Virtual Network ID (VNI)| +integer (24 bit) +|================== + +.Matching inner TCP destination port encapsulated in vxlan +---------------------------------------------------------- +netdev filter ingress udp dport 4789 vxlan tcp dport 80 counter +---------------------------------------------------------- + +ARP HEADER EXPRESSION +~~~~~~~~~~~~~~~~~~~~~ +[verse] +*arp* {*htype* | *ptype* | *hlen* | *plen* | *operation* | *saddr* { *ip* | *ether* } | *daddr* { *ip* | *ether* } + +.ARP header expression +[options="header"] +|================== +|Keyword| Description| Type +|htype| +ARP hardware type| +integer (16 bit) +|ptype| +EtherType| +ether_type +|hlen| +Hardware address len| +integer (8 bit) +|plen| +Protocol address len | +integer (8 bit) +|operation| +Operation | +arp_op +|saddr ether| +Ethernet sender address| +ether_addr +|daddr ether| +Ethernet target address| +ether_addr +|saddr ip| +IPv4 sender address| +ipv4_addr +|daddr ip| +IPv4 target address| +ipv4_addr +|====================== + RAW PAYLOAD EXPRESSION ~~~~~~~~~~~~~~~~~~~~~~ [verse] @@ -492,6 +732,8 @@ Link layer, for example the Ethernet header Network header, for example IPv4 or IPv6 |th| Transport Header, for example TCP +|ih| +Inner Header / Payload, i.e. after the L4 transport level header |============================== .Matching destination port of both UDP and TCP @@ -525,14 +767,15 @@ nftables currently supports matching (finding) a given ipv6 extension header, TC *dst* {*nexthdr* | *hdrlength*} *mh* {*nexthdr* | *hdrlength* | *checksum* | *type*} *srh* {*flags* | *tag* | *sid* | *seg-left*} -*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-permitted* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field' +*tcp option* {*eol* | *nop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field' *ip option* { lsrr | ra | rr | ssrr } 'ip_option_field' The following syntaxes are valid only in a relational expression with boolean type on right-hand side for checking header existence only: [verse] *exthdr* {*hbh* | *frag* | *rt* | *dst* | *mh*} -*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-permitted* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} +*tcp option* {*eol* | *nop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} *ip option* { lsrr | ra | rr | ssrr } +*dccp option* 'dccp_option_type' .IPv6 extension headers [options="header"] @@ -558,39 +801,45 @@ Segment Routing Header |Keyword| Description | TCP option fields |eol| End if option list| -kind -|noop| -1 Byte TCP No-op options | -kind +- +|nop| +1 Byte TCP Nop padding option | +- |maxseg| TCP Maximum Segment Size| -kind, length, size +length, size |window| TCP Window Scaling | -kind, length, count -|sack-permitted| +length, count +|sack-perm | TCP SACK permitted | -kind, length +length |sack| TCP Selective Acknowledgement (alias of block 0) | -kind, length, left, right +length, left, right |sack0| TCP Selective Acknowledgement (block 0) | -kind, length, left, right +length, left, right |sack1| TCP Selective Acknowledgement (block 1) | -kind, length, left, right +length, left, right |sack2| TCP Selective Acknowledgement (block 2) | -kind, length, left, right +length, left, right |sack3| TCP Selective Acknowledgement (block 3) | -kind, length, left, right +length, left, right |timestamp| TCP Timestamps | -kind, length, tsval, tsecr +length, tsval, tsecr |============================ +TCP option matching also supports raw expression syntax to access arbitrary options: +[verse] +*tcp option* +[verse] +*tcp option* *@*'number'*,*'offset'*,*'length' + .IP Options [options="header"] |================== @@ -611,7 +860,12 @@ type, length, ptr, addr .finding TCP options -------------------- -filter input tcp option sack-permitted kind 1 counter +filter input tcp option sack-perm exists counter +-------------------- + +.matching TCP options +-------------------- +filter input tcp option maxseg size lt 536 -------------------- .matching IPv6 exthdr @@ -624,6 +878,11 @@ ip6 filter input frag more-fragments 1 counter filter input ip option lsrr exists counter --------------------------------------- +.finding DCCP option +------------------ +filter input dccp option 40 exists counter +--------------------------------------- + CONNTRACK EXPRESSIONS ~~~~~~~~~~~~~~~~~~~~~ Conntrack expressions refer to meta data of the connection tracking entry associated with a packet. + @@ -637,11 +896,13 @@ is true for the *zone*, if a direction is given, the zone is only matched if the zone id is tied to the given direction. + [verse] -*ct* {*state* | *direction* | *status* | *mark* | *expiration* | *helper* | *label*} +*ct* {*state* | *direction* | *status* | *mark* | *expiration* | *helper* | *label* | *count* | *id*} *ct* [*original* | *reply*] {*l3proto* | *protocol* | *bytes* | *packets* | *avgpkt* | *zone*} *ct* {*original* | *reply*} {*proto-src* | *proto-dst*} *ct* {*original* | *reply*} {*ip* | *ip6*} {*saddr* | *daddr*} +The conntrack-specific types in this table are described in the sub-section CONNTRACK TYPES above. + .Conntrack expressions [options="header"] |================== @@ -698,12 +959,15 @@ integer (64 bit) conntrack zone | integer (16 bit) |count| -count number of connections +number of current connections| integer (32 bit) +|id| +Connection id| +ct_id| |========================================== -A description of conntrack-specific types listed above can be found sub-section CONNTRACK TYPES above. .restrict the number of parallel connections to a server -------------------- -filter input tcp dport 22 meter test { ip saddr ct count over 2 } reject +nft add set filter ssh_flood '{ type ipv4_addr; flags dynamic; }' +nft add rule filter input tcp dport 22 add @ssh_flood '{ ip saddr ct count over 2 }' reject -------------------- |