Limit incoming connections using iptables per IP

15,973

Solution 1

Finally managed to do it with recent:

iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW \
         -m recent --rcheck --seconds 60 --hitcount 5 --name ssh --rsource \
         -j REJECT --reject-with icmp-port-unreachable

iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW \
         -m recent --set --name ssh --rsource

--update will restart the timer again on each receiving packet, but --rcheck will only check it. After 60 seconds the structure is deleted and a new timer is started again.

This is how I got it (I was not looking into sources - too lazy)

Solution 2

Use the hashlimit match extension:

port=9999
iptables -A INPUT -p tcp --dport $port        \
      -m conntrack --ctstate NEW              \
      -m hashlimit --hashlimit-name SuperUser \
                   --hashlimit-above 5/minute \
                   --hashlimit-mode srcip     \
      -j DROP

Debug version:

#!/bin/sh
dport=9999
limit=2/minute
burst=2

iptables -F
iptables -N SuperUser 2>/dev/null
iptables -N SuperUserLimited 2>/dev/null

# SuperUserLimited
iptables -A SuperUserLimited -j LOG                         \
                                 --log-level info           \
                                 --log-prefix 'SU:dropped '
iptables -A SuperUserLimited -j DROP

# SuperUser
iptables -A SuperUser -j LOG                         \
                          --log-level info           \
                          --log-prefix 'SU:new '
iptables -A SuperUser -m hashlimit                   \
                          --hashlimit-name SuperUser \
                          --hashlimit-above $limit   \
                          --hashlimit-burst $burst   \
                          --hashlimit-mode srcip     \
                      -j SuperUserLimited
iptables -A SuperUser -j LOG                         \
                          --log-level info           \
                          --log-prefix 'SU:accepted '

# main
iptables -A INPUT -p tcp --dport $dport \
                  -m state --state NEW  \
                  -j SuperUser
Share:
15,973

Related videos on Youtube

PoltoS
Author by

PoltoS

Updated on September 18, 2022

Comments

  • PoltoS
    PoltoS 2 months

    I need to limit access to some port per IP. Let's say 5 connections per minute - not more.

    I've seen iptables recent, connlimit and limit, but all of them are not fitting exactly what I need.

    Suppose you have a client trying to connect every second. In my scenario I need to allow 5 packets each minute.

    recent: If some IP tries to connect every 1 second, --hitcount 5 will memorize this IP and keep it in the list until no packets comes within --second 60 time. So, it will limit the client permanently in my scenario.

    limit: This one limits as I wish with --limit 5/min, but for all IPs - no way to specify this per IP.

    connlimit: Limits number of simultaneous connections, not per some time.

    In fact, I need a mixture of limit + recent. Who knows how to do it?

  • PoltoS
    PoltoS over 8 years
    Hm, never seen hashlimit while googling. But I don't understand how it works: iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m hashlimit --hashlimit-name SSH --hashlimit-mode srcip --hashlimit-above 5/min -j REJECT this call does not trap any command, while iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m hashlimit --hashlimit-name SSH --hashlimit-mode srcip --hashlimit 5/min -j REJECT traps all new connections...
  • Cristian Ciupitu
    Cristian Ciupitu over 8 years
    I don't see --hashlimit option in the documentation, so the second command should have raised an error.
  • PoltoS
    PoltoS over 8 years
    It seems I've an old iptables, where hashlimit seems to be same as hashlimit-upto. May be it does not work being to old.
  • Cristian Ciupitu
    Cristian Ciupitu over 8 years
    I have iptables-1.4.19.1-1.fc20.x86_64.
  • totti
    totti over 8 years
    @PoltoS, How is it ?
  • PoltoS
    PoltoS over 8 years
    iptables v1.4.12 finally was fixed with -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --rcheck --seconds 60 --hitcount 5 --name ssh --rsource -j REJECT --reject-with icmp-port-unreachable
  • PoltoS
    PoltoS over 8 years
    This is not what I want. This limits simultaneous connections, while I need to limit total number of connections established (and may be ended) during 1 minute.
  • Brijesh Valera
    Brijesh Valera over 5 years
    Can you please provide the full solution with some details? I know, we need to have --set rule for adding source IP into the list. I want to know how it can be done.
  • Brijesh Valera
    Brijesh Valera over 5 years
    I need a similar approach if a burst comes from an IP, I need to block that IP for few minutes. I am experimenting with recent option but, I could not block that IP address for few minutes. It is been added into the list which won't be removed at all.
  • Brijesh Valera
    Brijesh Valera over 5 years
    Let's assume a scenario where I need to block an IP for 5minutes if IP sends 10connection/second. I could not DROP the connection from an IP for 5mins. Please help.