iptables Limit Requests Per IP Per Minute – Configuration Guide

debianiptableslinuxSecurity

I'm running Debian and iptables and are trying to limit users to accept my site more than 10 times per minute.

This is my original attempt:

# Max connection in seconds
TIME_PERIOD=60
# Max connections per IP
BLOCKCOUNT=10

# default action can be DROP or REJECT
DACTION="DROP"

iptables -I INPUT -p tcp --dport 8443 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 8443 -i eth0 -m state --state NEW -m recent --update --seconds $TIME_PERIOD --hitcount $BLOCKCOUNT -j $DACTION

And I've also tried this:

iptables -I INPUT -p tcp --syn --dport 8443 -m connlimit --connlimit-above 50 -j REJECT

But none if them seems to work.

Running this script for testing:

#!/bin/bash
ip="76.44.126.11"
port="8443"
for i in {1..100}
do
  # do nothing just connect and exit
  echo "exit" | nc ${ip} ${port};
done

Simply gives me this in iptables -nvL when I've run it twice:

Chain INPUT (policy DROP 6 packets, 820 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443 flags:0x17/0x02 #conn src/32 > 50 reject-with icmp-port-unreachable
    0     0 DROP       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source mask: 255.255.255.255
  200 12800 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443

So it seems to simply allow all packets through…

What to do?

UPDATE

I need to put --set first, so now it's:

Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0            tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443 state NEW recent: SET name: DEFAULT side: source mask: 255.255.255.255
    0     0 DROP       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source mask: 255.255.255.255
  100  6400 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443

But still fails.

UPDATE

Removed eth0 so now it is:

Chain INPUT (policy DROP 19 packets, 4244 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0            tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443 state NEW recent: SET name: DEFAULT side: source mask: 255.255.255.255
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source mask: 255.255.255.255
  101  6464 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443

Same result, fails.

Best Answer

Your problem is that you are using iptables -I instead of iptables -A. This causes your rules to be in the reverse order. The option -I means to insert the rule at head of chain (when no rule number is specified).

The rule using --set option should be first, and the second rule should be the one that drops traffic when exceeding defined limit.