I do not wish to limit the rate of a specific service. My goals is to limit rate based solely on the incoming IP address. For example using a pseudo-rule:
john.domain.local (192.168.1.100) can only download from our httpd/ftp servers at "10KB/s" (instead of 1MB/s)
How could I rate limit using IPTables based on incoming IP addresses?
IPTables isn't made for this kind of work, where lots and lots of packets need to be analyzed to make these decisions. IPTables is partly the answer though!
The real answer to this is the awesome and underused traffic control facilities in Linux. Note that mucking around with this without knowing what is going on may lead to you losing network connectivity to the machine! You have been warned!
Assuming eth0 is the outgoing device you will need to create a class-based traffic control queue which will by default output most traffic through the 'fast' queue and put a specific list of people into the 'slow' queue.
The beauty of this is you can create a situation whereby you allow lots of outbound traffic for the slow user unless an overriding class wants the bandwidth, but this example does not do this (will always provide 10kbps to the slow users). The queuing system will look something like this:
To do this, first you'll need to setup the queuing discipline in the kernel. The following will do this for you.. you must run this as one whole script
The "default 11" is important as it tells the kernel what to do with traffic not classified.
Once this is done, you can then setup an iptables rule to classify packets that match a certain criteria. If you plan on putting lots and lots of people into this slow rule an ipset rule is more appropriate (which should be available on rhel6 I believe).
So, create an ipset database to do the matching against...
Then create the iptables rule to do the match..
This instructs the kernel that if you match the destination IP with the source port from the set, classify it into the slow queue you setup with traffic control.
Now, finally whenever you want to slow an IP down you can use the ipset command to add the ip to the set such as this:
You can test it works using the command "tc -s class show dev eth0" and you will see stats in there indicating packets being redirected to the slow queue.
Note the only real downside to this is making it survive reboots. I don't think there are any init scripts available to create the ipsets from dumps on reboot (and they also must be created before iptables rules) and I'm certain there's no init scripts to resetup traffic control rules on reboot. If your not bothered, you can just recreate the whole thing from invoking a script in rc.local.
It's as simple as taking a rate limiting rule and adding the
-s
switch. The-s
switch matches incoming IPs. For exampleiptables -A INPUT -s 1.1.1.1
and then finishing up with your preferred method of rate limiting for that rule.