Difference between revisions of "Meters"

From nftables wiki
Jump to navigation Jump to search
m (1000 is 1000 milliseconds)
(9 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== Flow tables ==
== Meters ==


Since Linux Kernel 4.3 and nft v0.6 nftables supports flow tables.
This feature used to be known as ''flow tables'' before nft v0.8.1.


Flow tables provides a native replacement for the ''hashlimit'' match in iptables, however, you can use any selector, one or many through [[concatenations]].
Since Linux Kernel 4.3 and nft v0.8.1 nftables supports this feature.


== Using flow tables ==
Meters provide a native replacement for the ''hashlimit'' match in iptables, however, meters are a lot more flexible since you can use any selector, one or many through [[concatenations]].


The following commands create a table named ''filter'', a chain named ''input'' which hooks incoming traffic and a rule that uses a flow table:
== Using meters ==
 
The following commands create a table named ''filter'', a chain named ''input'' which hooks incoming traffic and a rule that uses a meter:


<source lang="bash">
<source lang="bash">
% nft add table filter
% nft add table filter
% nft add chain filter input {type filter hook input priority 0\;}
% nft add chain filter input {type filter hook input priority 0\;}
% nft add rule filter input tcp dport 22 ct state new flow table ssh-ftable { ip saddr limit rate 10/second } accept
% nft add rule filter input tcp dport 22 ct state new meter ssh-meter { ip saddr limit rate 10/second } accept
</source>
</source>


In this example we create a rule to match ''new''  ''ssh'' (port 22) connections, which uses a flow table named ''ssh-ftable'' to limit the traffic rate to 10 packets per second for each source IP address. The available time units on limits are: ''second'', ''minute'', ''hour'', ''day'' and ''week''.
In this example we create a rule to match ''new''  ''ssh'' (port 22) connections, which uses a meter named ''ssh-meter'' to limit the traffic rate to 10 packets per second for each source IP address. The available time units on limits are: ''second'', ''minute'', ''hour'', ''day'' and ''week''.
 
Since kernel 4.18, you can do this without using the ''meter'' syntax:
 
<source lang="bash">
% nft add table filter
% nft add chain filter input {type filter hook input priority 0\;}
% nft add set filter ssh-meter { type ipv4_addr\; flags dynamic\; }
% nft add rule filter input tcp dport 22 ct state new add @ssh-meter { ip saddr limit rate 10/second } accept
</source>


You can also use [[concatenations]] to build selectors:
You can also use [[concatenations]] to build selectors:


<source lang="bash">
<source lang="bash">
% nft add rule filter input flow table cnt-ftable { iif . ip saddr . tcp dport timeout 60s counter }
% nft add rule filter input meter cnt-meter { iif . ip saddr . tcp dport timeout 60s counter }
</source>
</source>


This rule counts incoming packets based on the tuple ''(input interface index, IP source address, TCP destination port)'', the counters are dropped after 60 seconds without update.
This rule counts incoming packets based on the tuple ''(input interface index, IP source address, TCP destination port)'', the counters are dropped after 60 seconds without update.


== Listing flow tables ==
== Listing meters ==


To list the content matched by the flow table use:
To list the content matched by the meter use:


<source lang="bash">
<source lang="bash">
% nft list flow table filter cnt-ftable
% nft list meter filter cnt-meter
table ip filter {
table ip filter {
flow table cnt-ftable {
meter cnt-meter {
type iface_index . ipv4_addr . inet_service
type iface_index . ipv4_addr . inet_service
flags timeout
flags timeout
Line 39: Line 50:
}
}
</source>
</source>
== Doing connlimit with nft ==
Since 4.18, there is a new ''ct count'' selector that allows you to count the number of existing connections. This extension uses the information available in the Connection Tracking System table, therefore, the counting of connection is based on the existing entries in the table.
The following example shows how to do ''connlimit'' from nftables:
table ip filter {
        set connlimit {
                type ipv4_addr
                size 65535
                flags dynamic
        }
        chain y {
                type filter hook output priority filter; policy accept;
                ct state new add @connlimit { ip daddr ct count over 20 } counter packets 0 bytes 0 drop
        }
}
The example above dynamically populates the set ''connlimit'' from the packet path. For the first packet of each connection (ie. packets matching ''ct state new''), this adds an entry into ''connlimit'' set, this entry uses the IPv4 destination address as a key. If the number of connection goes over 20, then packets are dropped.
Since ''connlimit'' is a set, you can perform any operation on it, such as listing and flushing its content.


== Doing iptables hashlimit with nft ==
== Doing iptables hashlimit with nft ==


Flow tables replace iptables hashlimit in nft. You can use the tool '''iptables-translate''' to see how to translate hashlimit rules, currently available in the [https://git.netfilter.org/iptables/ iptables git tree] and expected in the next official release, current release is v1.6.1.
Meters replace iptables hashlimit in nft. From iptables v1.6.2 onward, you can use the tool '''iptables-translate''' to see how to translate hashlimit rules.


Almost all hashlimit options are available in nft, starting with --hashlimit-mode, it is replaced by the selector in a flow table. All modes are available except no mode, a flow table demands a selector, an iptables rule without hashlimit-mode isn't supported in nft. A simple rule translation is:
Almost all hashlimit options are available in nft, starting with --hashlimit-mode, it is replaced by the selector in a meter. All modes are available except no mode, a meter demands a selector, an iptables rule without hashlimit-mode isn't supported in nft. A simple rule translation is:


<source lang="bash">
<source lang="bash">
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-above 200/sec --hashlimit-mode srcip,dstport --hashlimit-name http1 -j DROP
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-above 200/sec --hashlimit-mode srcip,dstport --hashlimit-name http1 -j DROP
nft add rule ip filter INPUT tcp dport 80 flow table http1 { tcp dport . ip saddr timeout 1s limit rate over 200/second burst 5 packets} counter drop
nft add rule ip filter INPUT tcp dport 80 meter http1 { tcp dport . ip saddr limit rate over 200/second } counter drop
</source>
</source>


Notice that a flow table is named, like hashlimit, and using multiple hashlimit-modes is similar to using a concatenation of selectors. Also, --hashlimit-above is translated to ''limit rate over'', to simulate --hashlimit-upto just omit or replace ''over'' with ''until'' in the rule.
Notice that a meter is named, like hashlimit, and using multiple hashlimit-modes is similar to using a concatenation of selectors. Also, --hashlimit-above is translated to ''limit rate over'', to simulate --hashlimit-upto just omit or replace ''over'' with ''until'' in the rule.
Notice also that the translator defaults --hashlimit-htable-expire and --hashlimit-burst to 1000 milliseconds and 5 packets respectively so ''timeout 1s'' and ''burst 5 packets'' are inserted. You may remove either or both of these if you wish.


The options --hashlimit-burst and --hashlimit-htable-expire are translated to ''burst'' and ''timeout'' in a flow table:
The options --hashlimit-burst and --hashlimit-htable-expire are translated to ''burst'' and ''timeout'' in a meter:


<source lang="bash">
<source lang="bash">
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-above 200kb/s --hashlimit-burst 1mb --hashlimit-mode srcip,dstport --hashlimit-name http2 --hashlimit-htable-expire 3000 -j DROP
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-above 200kb/s --hashlimit-burst 1mb --hashlimit-mode srcip,dstport --hashlimit-name http2 --hashlimit-htable-expire 3000 -j DROP
nft add rule ip filter INPUT tcp dport 80 flow table http2 { tcp dport . ip saddr timeout 3s limit rate over 200 kbytes/second burst 1 mbytes} counter drop
nft add rule ip filter INPUT tcp dport 80 meter http2 { tcp dport . ip saddr timeout 3s limit rate over 200 kbytes/second burst 1 mbytes} counter drop
</source>
</source>


This rule shows how ''timeout'' and ''burst'' are used in a flow table, also notice that flow tables, similarly to hashlimit, accepts limiting rates by bytes frequency instead of packets.
This rule shows how ''timeout'' and ''burst'' are used in a meter, also notice that meters, similarly to hashlimit, accepts limiting rates by bytes frequency instead of packets.


Another hashlimit option is to limit the traffic rate on subnets, of IP source or destination addresses, using the options --hashlimit-srcmask and --hashlimit-dstmask. This feature is available in nft by attaching a subnet mask to a flow table selector, attach to ''ip saddr'' for source address and to ''ip daddr'' for destination adress:
Another hashlimit option is to limit the traffic rate on subnets, of IP source or destination addresses, using the options --hashlimit-srcmask and --hashlimit-dstmask. This feature is available in nft by attaching a subnet mask to a meter selector, attach to ''ip saddr'' for source address and to ''ip daddr'' for destination adress:


<source lang="bash">
<source lang="bash">
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-upto 200 --hashlimit-mode srcip --hashlimit-name http3 --hashlimit-srcmask 24 -j DROP
$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-upto 200 --hashlimit-mode srcip --hashlimit-name http3 --hashlimit-srcmask 24 -j DROP
nft add rule ip filter INPUT tcp dport 80 flow table http3 { ip saddr and 255.255.255.0 timeout 1s limit rate 200/second burst 5 packets} counter drop
nft add rule ip filter INPUT tcp dport 80 meter http3 { ip saddr and 255.255.255.0 limit rate 200/second } counter drop
</source>
</source>


This rule will limit packets rate, grouping subnets determined by the first 24 bits of the IP source address, from the incoming packets on port 80.
This rule will limit packets rate, grouping subnets determined by the first 24 bits of the IP source address, from the incoming packets on port 80.


The remaining options, --hashlimit-htable-max, --hashlimit-htable-size and --hashlimit-htable-gcinterval don't apply to flow tables.
The remaining options, --hashlimit-htable-max, --hashlimit-htable-size and --hashlimit-htable-gcinterval don't apply to meters.

Revision as of 10:59, 5 February 2019

Meters

This feature used to be known as flow tables before nft v0.8.1.

Since Linux Kernel 4.3 and nft v0.8.1 nftables supports this feature.

Meters provide a native replacement for the hashlimit match in iptables, however, meters are a lot more flexible since you can use any selector, one or many through concatenations.

Using meters

The following commands create a table named filter, a chain named input which hooks incoming traffic and a rule that uses a meter:

% nft add table filter
% nft add chain filter input {type filter hook input priority 0\;}
% nft add rule filter input tcp dport 22 ct state new meter ssh-meter { ip saddr limit rate 10/second } accept

In this example we create a rule to match new ssh (port 22) connections, which uses a meter named ssh-meter to limit the traffic rate to 10 packets per second for each source IP address. The available time units on limits are: second, minute, hour, day and week.

Since kernel 4.18, you can do this without using the meter syntax:

% nft add table filter
% nft add chain filter input {type filter hook input priority 0\;}
% nft add set filter ssh-meter { type ipv4_addr\; flags dynamic\; }
% nft add rule filter input tcp dport 22 ct state new add @ssh-meter { ip saddr limit rate 10/second } accept

You can also use concatenations to build selectors:

% nft add rule filter input meter cnt-meter { iif . ip saddr . tcp dport timeout 60s counter }

This rule counts incoming packets based on the tuple (input interface index, IP source address, TCP destination port), the counters are dropped after 60 seconds without update.

Listing meters

To list the content matched by the meter use:

% nft list meter filter cnt-meter
table ip filter {
	meter cnt-meter {
		type iface_index . ipv4_addr . inet_service
		flags timeout
		elements = { "wlan1" . 64.62.190.36 . 55000 expires 38s : counter packets 2 bytes 220, "wlan1" . 83.98.201.47 . 35460 expires 39s : counter packets 10 bytes 5988, "wlan1" . 172.217.7.142 . 43254 expires 46s : counter packets 1 bytes 98}
	}
}

Doing connlimit with nft

Since 4.18, there is a new ct count selector that allows you to count the number of existing connections. This extension uses the information available in the Connection Tracking System table, therefore, the counting of connection is based on the existing entries in the table.

The following example shows how to do connlimit from nftables:

table ip filter {
       set connlimit {
               type ipv4_addr
               size 65535
               flags dynamic
       }

       chain y {
               type filter hook output priority filter; policy accept;
               ct state new add @connlimit { ip daddr ct count over 20 } counter packets 0 bytes 0 drop
       }
}

The example above dynamically populates the set connlimit from the packet path. For the first packet of each connection (ie. packets matching ct state new), this adds an entry into connlimit set, this entry uses the IPv4 destination address as a key. If the number of connection goes over 20, then packets are dropped.

Since connlimit is a set, you can perform any operation on it, such as listing and flushing its content.

Doing iptables hashlimit with nft

Meters replace iptables hashlimit in nft. From iptables v1.6.2 onward, you can use the tool iptables-translate to see how to translate hashlimit rules.

Almost all hashlimit options are available in nft, starting with --hashlimit-mode, it is replaced by the selector in a meter. All modes are available except no mode, a meter demands a selector, an iptables rule without hashlimit-mode isn't supported in nft. A simple rule translation is:

$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-above 200/sec --hashlimit-mode srcip,dstport --hashlimit-name http1 -j DROP
nft add rule ip filter INPUT tcp dport 80 meter http1 { tcp dport . ip saddr limit rate over 200/second } counter drop

Notice that a meter is named, like hashlimit, and using multiple hashlimit-modes is similar to using a concatenation of selectors. Also, --hashlimit-above is translated to limit rate over, to simulate --hashlimit-upto just omit or replace over with until in the rule.

The options --hashlimit-burst and --hashlimit-htable-expire are translated to burst and timeout in a meter:

$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-above 200kb/s --hashlimit-burst 1mb --hashlimit-mode srcip,dstport --hashlimit-name http2 --hashlimit-htable-expire 3000 -j DROP
nft add rule ip filter INPUT tcp dport 80 meter http2 { tcp dport . ip saddr timeout 3s limit rate over 200 kbytes/second burst 1 mbytes} counter drop

This rule shows how timeout and burst are used in a meter, also notice that meters, similarly to hashlimit, accepts limiting rates by bytes frequency instead of packets.

Another hashlimit option is to limit the traffic rate on subnets, of IP source or destination addresses, using the options --hashlimit-srcmask and --hashlimit-dstmask. This feature is available in nft by attaching a subnet mask to a meter selector, attach to ip saddr for source address and to ip daddr for destination adress:

$ iptables-translate -A INPUT -m tcp -p tcp --dport 80 -m hashlimit --hashlimit-upto 200 --hashlimit-mode srcip --hashlimit-name http3 --hashlimit-srcmask 24 -j DROP
nft add rule ip filter INPUT tcp dport 80 meter http3 { ip saddr and 255.255.255.0 limit rate 200/second } counter drop

This rule will limit packets rate, grouping subnets determined by the first 24 bits of the IP source address, from the incoming packets on port 80.

The remaining options, --hashlimit-htable-max, --hashlimit-htable-size and --hashlimit-htable-gcinterval don't apply to meters.