Home - Writings - Pictures - Code - Resume - Links





The iptables Rate-Limiting Module

Youssef M. Assad


Contents

pt This document was written by Youssef M. Assad
(youssef_assad@myrealbox.com) and is copyright 2003. Licensing is under the OPL; look it up, I'm not pasting it in here. I'll be happy to accept corrections. Hope you find it useful.

Introduction

What is rate limiting with iptables?

iptables (http://www.netfilter.org) is the packet filtering firewall rolled into the GNU/Linux kernel starting with version 2.4.

In the transition from ipchains to iptables, many fairly significant changes were made. The most widely acknowledged was the introduction of statefulness, or 'connection tracking'. The more fundamental, and in my opinion, more exciting shift, has been the increased emphasis on modules.

This article will discuss the rate limiting module. The module itself is not overly complex, and I will try to emphasise application more than plain old invocation.

Applications

It is important to observe that rate limiting is conceptually different from bandwidth throttling/limiting; a bandwidth-throttled connection will queue packets and limit the rate at which they are transmitted/received. Rate limiting will not do this; when you use rate limiting on, for example, incoming TCP connection attempts to your identd, and connections exceeding the specified limit will be denied; there is no queueing of packets.

I personally use rate limiting (rlim) on a standalone dialup machine; many of the ideas expressed in this article will, however, be useful on more involved setups.

Invocation and Syntax

Referencing and loading the module

It is assumed that the reader is familiar with the basic syntax for rule composition in iptables:
iptables -A TABLENAME [matches ...] -j TARGET

The matches ... part of the command contains the description of matches for the rule; it is in here that we load modules and give them arguments like this:

-m MODULENAME -option-one value1 ...-option-n valuen

The rate limiting module resides in /lib/modules/$KERNELVERSION
/kernel/net/ipv4/netfilter/
and is called ipt_limit.o. This corresponds to a MODULENAME of limit.

Module arguments

The limitn module takes two arguments, both optional:

-limit [X/[second/minute/hour/day]] $\backslash$
-limit-burst [Y]

-limit, according to the man page, is the ``Maximum average matching rate''. What this means, in plain english, is the maximum number of matches per time period for other parameters in the rule that will be accepted for the target to kick in.

-limit-burst is the number of packets matching the rule's other match criteria to constitute one match for -limit above.

Don't worry if none of this makes sense; I get the feeling it's not really supposed to, at least not initially.

Using rate limiting

Hopefully, none of this will have made terribly much sense so far; I'd hate to think I was the only one with trouble understanding this nifty gadget. Let's take some examples - things will become clear rather faster than you expect.

Incoming traffic

One obvious application of rate limiting on incoming traffic is to block ping flooding. We can obviously block ping floods with a rule blocking incoming echo-request ICMP packets altogether, but this is inelegant; this is linux, remember? What we want to do, rather, is to allow such packets but only in small quantities. Have a look at the relevant rule:

iptables -A INPUT -p ICMP -icmp-type echo-request $\backslash$
-m limit -limit 1/minute -limit-burst 5 -j ACCEPT

-limit 1/minute will do what it says; it will only match for a rate of incoming packets up to an average of 1 per minute. The operative word here is average. So, does this mean that the first ping request you get will be accepted, then none for a whole minute? Not quite.

-limit-burst 5 tells iptables to let 5 such packets in before permitting the rule to match; so, in one minute, we can have 5 ping requests popping through. So, -limit 1/minute permits a maximum of 1 packet per minute on average, but -limit-burst 5 permits 5 in one shot. Have we found a logical error in iptables? No you silly clod, remember, -limit stes a limit on average, whereas -limit-burst limits by number of packets in one go. What will happen then in our example?

The firewall will let the first 5 packets in in the first minute, thanks to -limit-burst 5; this means, however, that the packets/minute now is 5, so any further packets are blocked until packets/minute = 1, i.e. 5 minutes later. In the sixth minute, packets/minute will be 5/6 < 1, so another ping request will be let in. When the extra ping request is admitted, the ratio becomes 6/6 = 1 again, and packets are DROPped again until the next minute. Again, average is the operative word.

Now, if you want to make life really simple and decide that you really don't want to bother with averages and limit bursts, and that you want to deal with -limit on actual basis rather than average, you can do that too;

iptables -A INPUT -p ICMP -icmp-type echo-request $\backslash$
-m limit -limit 1/minute -limit-burst 1 -j ACCEPT
There; one match per minute is all you're getting, no more. Though it must be said, I hope you don't use this if you're admining a large site. One connection per minute is beyond paranoid. Let's loosen that rule up a bit.
iptables -A INPUT -p ICMP -icmp-type echo-request $\backslash$
-m limit -limit 1/minute -limit-burst 2 -j ACCEPT
Now, like this, you get maybe 2 matches in the first minute, and maximum one for the rest of your uptime. This is still pathetic, but you should be beginning to get the broad idea here. -limit keeps tabs on the average, and -limit-burst regulates how big a bite you take out of the sandwich each time. A more reasonable set of figures for someone on dialup like me might look like this (YMMV):

iptables -A INPUT -p ICMP -icmp-type echo-request $\backslash$
-m limit -limit 10/minute -limit-burst 20 -j ACCEPT

10 pings a minute is good and safe; a limit-burst of 20 is generous, and not enough to knock me down. More fool you, broadband-bestowed script-kiddies!

These same ideas can be applied to any other form of incoming traffic. I run an ident server; I only use it for IRC connections, so I don't expect more than 1 or two connections a minute:

iptables -A INPUT -p TCP -m state -state NEW $\backslash$
-dport 113 -m limit -limit 1/minute -limit-burst 2 -j ACCEPT

Actually, we might even do this:

iptables -A INPUT -p TCP -m state -state NEW $\backslash$
-m limit -limit 1/minute -limit-burst 2 -j ACCEPT

Same as the previous rule, only it's more generic; any old TCP connection attempt will match, not just ones to port 113. Of course, if you're running other servers, you might want to fiddle with those values.

Log Summarising

Rate limiting is also commonly used for summarising logging. Let's say I'm not only rate limiting connections to my ident server, but I'm logging those connections too:

iptables -A INPUT -p TCP -m state -state NEW $\backslash$
-dport 113 -m limit -limit 1/minute -limit-burst 2 -j LOG

Now, I don't have to log all them connection attempts (successful and otherwise); I'm going to get at most a couple of syslog entries a minute. This can be nice when you're experiencing synflooding, or icmp flooding; you can put it on your outbound icmp traffic too to prevent becoming a participant in a distributed smurf attack too. Never know.

Outgoing traffic

You get the basic idea by now; the trick is to identify the expected and eccepted rates of traffic for the specific kind of packet you will be looking for, and you know how to adjust -limit and -limit-burst to deal with this. It's really no different for outgoing traffic, though it's more rare. Rate-limiting outbound traffic is usually done to limit the potential for attacks from your machine, whether from a malicious local user or whether because you've been cracked.

iptables -A OUTPUT -p ICMP -icmp-type echo-request $\backslash$
-s ! $MY_IP -m limit -limit 10/second -limit-burst 30 $\backslash$
-j LOG -log-prefix "Forged echo-request: "|

iptables -A OUTPUT -p ICMP -icmp-type echo-request $\backslash$
-s ! $MY_IP -m limit -limit 10/second -limit-burst 30 $\backslash$
-j ACCEPT

Same semantics, different chains. Common practise is, as above, to write two identical rules with a LOG target then a ACCEPT target for this type of malicious activity. In fact, it may be worth considering, on local systems with numerous (and potentially untrustworthy) users, to impose carefully selected and very precise outbound limits; having your resources used in inflicting cracker activity is almost as bad as being victim.

As ever, if the log entries become too numerous, you just delete the first rule.

Caveat Emptor

Rate limits vs. bandwidth allocation

Rate limiting, as we said earlier, is not bandwidth limiting or throttling. For a newbie like me, the difference is subtle; rate limiting simply reduces your exposure to what you would consider excessive quantities of certain types of packets. Bandwidth limiting is more a resource allocation technique.

As such, iptables won't queue packets with the limit module. You might want to use it to set a cieling on the number of connection attempts (as opposed to actual connections) to your web server, but you won't be using it to limit the amount of data an existing connection will make away with.

If it's bandwidth limiting you want to do, try Squid proxy;
http://www.tldp.org has a very nice Bandwidth limiting HOWTO.

The bigger picture

iptables is a splendid packet filtering tool, but it falls short in terms of identifying larger patterns. This is not a deficiency, it is what a packet filter does - filter packets. What this means is that you can't expect iptables with its modules such as limit to function as an IDS.

It may technically be possible to do so, with some truly horrendous scripts and perhaps a SQL database as a log target all jazzed up with funky triggers, but that is:

To make a long story short, hammers are for nails and screwdrivers for screws. Don't build kludgy iptables scripts to act as rudimentary intrusion detection systems; it won't work all that well, and you will come quickly to appreciate that it doesn't take all that many rules before your packet filtering rules begin to munch appreciably on those precious CPU cycles.

Acknowledgements

Rusty Russell for his packet filtering HOWTO; Donald Knuth for TEX

About this document ...

The iptables Rate-Limiting Module

This document was generated using the LaTeX2HTML translator Version 2K.1beta (1.48)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -split 0 ratelim.tex

The translation was initiated by Youssef M. Assad on 2003-05-01



Youssef M. Assad 2003-05-01



This page is copyright Youssef M. Assad 2003. This article is freely redistributable in UNMODIFIED FORM, covering both the content and credits. If anyone's publishing it, I'd like to know about it first, however.