Apache: Limit the Number of Requests/Traffic per IP?

Solution 1:

This is my iptables solution for this kind of issue. Adjust --seconds --hitcount as you need, also iptables table.

iptables -A FORWARD -m state --state NEW -m recent --rcheck --seconds 600 --hitcount 5 --name ATACK --rsource -j REJECT --reject-with icmp-port-unreachable
iptables -A FORWARD -d 192.168.0.113/32 -o eth1 -p tcp -m tcp --dport 80 -m recent --set --name ATACK --rsource -j ACCEPT

Explained:

  1. iptables check if source IP is listed on /proc/net/ipt_recent/ATACK file for 5 or more times in 600 seconds interval and if it's a NEW request. If it is, do a reject; else

  2. iptables check if request is destinated to port 80. If so, print IP and timestamp to /proc/net/ipt_recent/ATACK and forward packet.

It's working fine for my needs.

Solution 2:

If you want a pure Apache solution bw_mod for Apache 2.0 and mod_bandwidth for Apache 1.3. They can throttle the bandwidth of your server to limit bandwidth usage.

There is also mod_limitipconn, which prevents one user from making lots of connections to your server. mod_cband is another option, but I have never used it.

If you don't want to mess with your Apache installation you can put a squid proxy in front of Apache. It gives you more control also over the throttling.

However, in most cases the problem is a few large objects when you want to limit bandwidth per IP, and you want to give a sane error message when a user pulls too much data and you block him. In that case it might be easier to write a PHP script and store the access information in a temporary table in a database.