nftables quotas let you cap the amount of data or connection attempts from a specific IP address over a defined period, effectively rate-limiting bandwidth or connection rates.

Let’s see it in action. Imagine we want to limit a single IP address, 192.168.1.100, to only 1 megabyte of traffic every minute. We also want to limit the number of new TCP connections it can establish to 10 per minute.

# First, create a table if you don't have one already
nft add table ip my_traffic_control

# Add a chain to hold our quota rules
nft add chain ip my_traffic_control input { type filter hook input priority 0 \; }

# Add the data quota rule
nft add rule ip my_traffic_control input ip saddr 192.168.1.100 meter { name data_quota, bytes 1m, timeout 1m } accept

# Add the connection quota rule
nft add rule ip my_traffic_control input ip saddr 192.168.1.100 meter { name conn_quota, packets 10, timeout 1m } accept

# To view the meters and their current state
nft list meter ip my_traffic_control

This sets up two independent limits for 192.168.1.100: one for data volume and one for connection attempts, both resetting every minute. If either limit is exceeded, subsequent packets or connection attempts from that IP will be dropped by default if there isn’t a subsequent accept rule, or handled by whatever rule comes next in the chain.

The core problem nftables quotas solve is preventing a single user or a compromised machine from saturating your network link or overwhelming your services with excessive traffic or connection requests. This is crucial for maintaining service availability and fairness among legitimate users.

Internally, nftables uses "meters" to track usage. Each meter has a name, a type (bytes, packets, or both), a limit, and a timeout. When a packet matches a rule containing a meter, the meter is updated. If the meter’s current value exceeds its limit within the specified timeout period, the meter is considered "exceeded." Subsequent packets matching that rule will then be subject to the policy defined by the meter object itself, or more commonly, the policy of the rule following the meter in the nftables chain.

The bytes and packets parameters define the threshold. bytes refers to the total size of packets (including headers), and packets refers to the number of distinct packets. The timeout specifies the duration over which this usage is measured. When the timeout expires, the meter resets to zero, allowing the IP to start accumulating usage again.

Crucially, the accept keyword after the meter in our example is not strictly about accepting the traffic based on the quota. It signifies that if the meter has not exceeded its limit, the packet should proceed to the accept verdict. If the meter has exceeded its limit, this accept verdict is skipped, and the packet falls through to the next rule. If there are no more rules, it will be handled by the chain’s default policy (often drop).

You can combine multiple meters within a single rule, but they operate independently. If a rule has meter { name data_quota, bytes 1m, timeout 1m } meter { name conn_quota, packets 10, timeout 1m } accept, both the data quota and the connection quota must be met for the accept verdict to be reached.

The real power comes from applying these rules not just to specific IPs, but to sets of IPs or even dynamically generated sets using ipset integration. For instance, you could limit all IPs within a subnet or all IPs that have recently generated a high number of alerts.

When you define a meter, nftables allocates a small amount of memory to track its state. The nft list meter command shows you the current count and expiration time for each active meter. This is invaluable for debugging and understanding exactly how your quotas are being applied in real-time.

One aspect that often trips people up is the interaction between the meter and the verdict. The accept or drop verdict in a rule with a meter only takes effect if the meter’s condition is met. If the meter is exceeded, that specific verdict is ignored, and processing continues to the next rule. This means you need to structure your rules carefully. If you want to drop traffic after a quota is exceeded, you’d place your drop rule after the meter rule, or configure the meter itself to have a drop verdict.

To make this more robust, you would typically have a rule like this before the meter rule:

nft add rule ip my_traffic_control input ip saddr 192.168.1.100 counter accept

This counter rule would accept all traffic from 192.168.1.100 and count it. Then, your meter rules would follow, and if the meter is exceeded, the traffic would fall through to a subsequent drop rule.

Another common use case is rate-limiting connection attempts to prevent SYN floods or brute-force attacks. You’d use the packets limit with a small timeout, like packets 5, timeout 10s, to limit new connections from a single IP to 5 per 10 seconds.

The next step in controlling network traffic with nftables is often learning about how to dynamically manage sets of IP addresses using ipset and applying quotas to those sets.

Want structured learning?

Take the full Nftables course →