Using iptables to rate-limit incoming connections

Posted by Steve on Sun 17 Jul 2005 at 00:39

The iptables firewall has several useful extension modules which can be used to in addition to the basic firewall functionality. One of the more interesting of these extensions is the "recent" module which allows you to match recent connections, and perform simple throttling on incoming connections.

We've previously described keeping SSH access secure by limiting which users can connect, or just firewalling access so that only a small list of trusted IP addresses can connect. In most cases this is sufficient to protect your system.

However there are times when you have to allow arbitary incoming connections, when you are travelling for example.

In these situations you can open up your system to allow incoming connections and be the target of a dictionary attack - literally a machine trying to connect and login over and over again using usernames and passwords from a dictionary.

These attempts will be logged in your /var/log/auth.log file like this:

sshd[x]: Illegal user admin from aa.bb.cc.dd
sshd[x]: Illegal user test from  aa.bb.cc.dd
sshd[x]: Illegal user guest from aa.bb.cc.dd

In this situation you can create a collection of firewalling rules which will deny access from remote clients who attempt to connect "too many" times.

If you have an existing firewall in place, using iptables, then adding the rules is very straightforward.

The way the recent module works is fairly straightforward, you basically add IP addresses to a list, which can then be used in the future to test connection attempts against. This allows you to limit the number of connections against either a number of seconds, or connection attempts. In our example we'll do both.

An example is probably the simplest way to illustrate how it works. The following two rules will limit incoming connections to port 22 to no more than 3 attemps in a minute - an more than that will be dropped:

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
  --set

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
  --update --seconds 60 --hitcount 4 -j DROP

The --state flag takes a comma seperated list of connection states as an argument, by using "--state NEW" as we did we make sure that only new connections are managed by the module.

The --set parameter in the first line will make sure that the IP address of the host which initiated the connection will be added to the "recent list", where it can be tested and used again in the future i.e. in our second rule.

The second rule is where the magic actually happens. The --update flag tests whether the IP address is in the list of recent connections, in our case each new connection on port 22 will be in the list because we used the --set flag to add it in the preceeding rule.

Once that's done the --seconds flag is used to make sure that the IP address is only going to match if the last connection was within the timeframe given. The --hitcount flag works in a similar way - matching only if the given count of connection attempts is greater than or equal to the number given.

Together the second line will DROP an incoming connection if:

  • The IP address which initiated the connection has previously been added to the list and
  • The IP address has sent a packet in the past 60 seconds and
  • The IP address has sent more than 4 packets in total.

You can adjust the numbers yourself to limit connections further, so the following example will drop incoming connections which make more than 2 connection attempts upon port 22 within ten minutes:

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
  --set

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
  --update --seconds 600 --hitcount 2 -j DROP

If you wish to test these rules you can script a number of connection attempts from an external host with the netcat package.

The following script attempts to connect to the IP address 192.168.1.1 5 times. The first couple of attempts you should see a welcome banner such as "SSH-2.0-OpenSSH_3.8.1p1 Debian-8.sarge.4" - after that the script will hang as it's packets are dropped and no response is sent:

#!/bin/bash

for i in `seq 1 5` ; do
  echo 'exit' | nc 192.168.1.1 22 ;
done

There's a lot of documentation on the netfilter/iptables firewall, and it's available modules which you can find in the Netfilter Extension HOWTO.

This HOWTO contains documentation on many different modules, along with examples. A recommended read if you're interested in Linux firewalling.

If you wish to experiment with rules and testing it's worth remembering how to remove all active rules. The following commands will flush your iptables filewall, and remove all currently active rules:

iptables -F
iptables -X

 

 


Posted by Anonymous (201.7.xx.xx) on Sun 17 Jul 2005 at 04:04
Hi!

I am not so good in English, but when reading the title of your article, I thought that you were going to teach how to get the incoming connections faster (changing the TOS field, for example).
Isn't "Using iptables to limit incoming connections" a better title?

Beside this, it's a very good article. Really good.

Thank you and sorry if my English is wrong :-)

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Sun 17 Jul 2005 at 10:12
[ View Steve's Scratchpad | View Weblogs ]

In my experience "throttling" usually refers to slowing things down, rather than speeding things up - which is what I expect from TOS manipulations.

I think the title might be a little ambiguous though, so I'll change it based upon your suggestion. Thanks :)

Steve
-- Steve.org.uk

[ Parent | Reply to this comment ]

Posted by Serge (213.119.xx.xx) on Sun 17 Jul 2005 at 07:39
[ View Serge's Scratchpad | View Weblogs ]
Hi,

any comments on how to combine those rules with 'managed firewalls', by which I mean, an iptables based rule-making-daemon where one does not write the rules directly?

In my case, I use Shorewall a lot, and as a side effect, I'm very bad at iptables scripting. Can those iptables rules just be added at the bottom of an exisiting script, or is there more to it than that? I guess I have a heard time to figure out to which extent the order of iptables rules are important :)


--

Serge van Ginderachter


[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Sun 17 Jul 2005 at 09:48
[ View Steve's Scratchpad | View Weblogs ]

This thread I found via Google seems to suggest mixing the rules into an existing Shorewall setup is possible.

I guess if you know which ethN device to use, and you're not using conflicting rules then there should be no real harm in it ..

Steve
-- Steve.org.uk

[ Parent | Reply to this comment ]

Posted by Serge (213.119.xx.xx) on Sun 17 Jul 2005 at 11:55
[ View Serge's Scratchpad | View Weblogs ]
Thanks Steve,

looks like I found an even better solution for shorewall:

http://blog.blackdown.de/2005/02/18/mitigating-ssh-brute-force-at tacks-with-ipt_recent/



--

Serge van Ginderachter


[ Parent | Reply to this comment ]

Posted by Anonymous (68.15.xx.xx) on Sun 17 Jul 2005 at 13:19
Steve,
This is a very timely article given all of the brute force ssh attacks going on right now. Thanks for the great info!

-Ben

[ Parent | Reply to this comment ]

Posted by ajt (82.133.xx.xx) on Sun 17 Jul 2005 at 14:52
[ View Weblogs ]

I've seen lots of SSH activity on my home box. Someone at a LUG[1] meeting suggested the "MaxStartups" option which sets the number of unauthorised connections that SSHd will accept at any time. While it doesn't stop the attention, it does keep it down.

MaxStartups
Specifies the maximum number of concurrent unauthenticated connections to the sshd daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection. The default is 10.
Alternatively, random early drop can be enabled by specifying the three colon separated values "start:rate:full" (e.g., "10:30:60"). sshd will refuse connection attempts with a probability of "rate/100" (30%) if there are currently "start" (10) unauthenticated connections. The probability increases linearly and all connection attempts are refused if the number of unauthenticated connections reaches "full" (60).

[1] Hants-LUG

--
"It's Not Magic, It's Work"
Adam

[ Parent | Reply to this comment ]

Posted by Anonymous (212.202.xx.xx) on Mon 18 Jul 2005 at 07:32
My ssh is running in port 1022 and since I changed this, I haven't had a singe faild login.

[ Parent | Reply to this comment ]

Posted by ajt (204.193.xx.xx) on Mon 18 Jul 2005 at 08:15
[ View Weblogs ]
Remember this won't keep determined crackers out. It does cut down on the number of script kiddies having a go, and cluttering up your logs though.

--
"It's Not Magic, It's Work"
Adam

[ Parent | Reply to this comment ]

Posted by bignose (150.101.xx.xx) on Tue 19 Jul 2005 at 01:07

However there are times when you have to allow arbitary incoming connections, when you are travelling for example.

In these situations you can open up your system to allow incoming connections and be the target of a dictionary attack - literally a machine trying to connect and login over and over again using usernames and passwords from a dictionary.

Dictionary attacks against passwords are only possible if your SSH accepts password authentication. If you need to accept arbitrary connections, turn off password authentication and only allow something more secure, like DSA public keys.

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Tue 19 Jul 2005 at 08:16
[ View Steve's Scratchpad | View Weblogs ]

This is true, but the intention of the article wasn't meant to be completely SSH specific.

There are other situations where it's possible to want to imagine the need to slow down and limit incoming connections..

Steve
-- Steve.org.uk

[ Parent | Reply to this comment ]

Posted by justr (217.244.xx.xx) on Wed 20 Jul 2005 at 05:45
I've done this on a fresh installed stable Debian (Sarge). After setting the iptables (confirmed the setting via iptables --list) I did the netcat test, but it always let me establish a connection (done from the local subnet and from the internet). Are there other prerequisites for this to work?

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Wed 20 Jul 2005 at 12:09
[ View Steve's Scratchpad | View Weblogs ]

Nope, if you've added the correct rules it should just work.

Steve
-- Steve.org.uk

[ Parent | Reply to this comment ]

Posted by cyn (192.55.xx.xx) on Wed 20 Jul 2005 at 19:57
Does your machine have multiple NICs (and/or did you change the IP to match)? You can remove the "-i eth0" part from the examples if you're sure you want this running on all interfaces, otherwise you can update it to match whichever interface(s) you do want it on.

Works for me, in fact my system monitor just got angry because 4 packets isn't enough for two ssh connections even, so the one-a-minute-test got blocked and tried to tell me ssh was broken :)

[ Parent | Reply to this comment ]

Posted by Anonymous (213.54.xx.xx) on Wed 20 Jul 2005 at 20:01
Arghh... Right, eth0 is another NIC in my system. eth1 would be fine for me. Thanks!

[ Parent | Reply to this comment ]

Posted by cyn (192.55.xx.xx) on Thu 21 Jul 2005 at 17:08
So I've decided to buckle down and implement this, and I've been doing some searching and have what looks like it should be a good set of rules (slightly modified from http://cert.uni-stuttgart.de/archive/suse/security/2005/02/msg000 25.html )
-----
IPT="/sbin/iptables";

$IPT -N SSH_bruteforce
$IPT -A SSH_bruteforce -m recent --name SSH_brutes --set -j LOG --log-level DEBUG --log-prefix "SSH bruteforce attempt: "
$IPT -A SSH_bruteforce -j REJECT

$IPT -A INPUT -p tcp --dport ssh ! --syn -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -p tcp --dport ssh --syn -m recent --name SSH_brutes --update --seconds 20 -j REJECT
$IPT -A INPUT -p tcp --dport ssh --syn -m recent --name sshconn --update --seconds 60 --hitcount 6 -j SSH_bruteforce
#$IPT -A INPUT -p tcp --dport ssh --syn -m recent --name sshconn --update --seconds 60 --hitcount 6 -m limit --limit 6/minute -j SSH_bruteforce
$IPT -A INPUT -p tcp --dport ssh --syn -m recent --name sshconn --set
$IPT -A INPUT -p tcp --dport ssh --syn -j ACCEPT
---

The idea is that sshconn is incremented on each new connection (the SYN packet - I could just as easily be using --state NEW probably) and if there are 6 of them in a minute it marks the IP as a brute - and new connections from brutes are denied right up front.

It does work (blocking), but the 'recent' isn't clearing out properly (it's set down to 20 for testing) - after many minutes it still continues to jump down the SSH_brutes match (which should only match for 20 seconds by my reading). It also seems to block too early, as if multiple SYN packets are sent if you do bad protocol negotiation a-la the 'echo exit | netcat' bit - not sure about that.

What I'd really like though would be a way to reset the names entirely when a successful ssh login happens, so that for e.g. scp's and the likes wouldn't trigger anything unpleasant.

Any ideas?

[ Parent | Reply to this comment ]

Posted by Anonymous (80.132.xx.xx) on Mon 8 Aug 2005 at 19:49
Hi!

After replacing my

IPTABLES -A INPUT -p TCP -s 0/0 --destination-port 22 -j ACCEPT

with the "...-m state --state NEW..." rules no one can connect to my server. And I cannot figure out why. :-(
Any idea?

Thorsten

[ Parent | Reply to this comment ]

Posted by Anonymous (65.29.xx.xx) on Sun 16 Oct 2005 at 22:55
Your 'default' state may be DENY instead of ACCEPT. insert the rules from this script above that one, dont replace it.

[ Parent | Reply to this comment ]

Posted by drummond_junior (201.78.xx.xx) on Fri 7 Jul 2006 at 03:28
Try to use your OLD rule after the two new statment, because the new rules will only DROP as soon as the the conditions are satisfield (the timing and repetition of the incoming packets).
So, since you don't have any statment allowing the packets to go throught your box, those "new" rules became useless. I'm not sure if you change the default behavior of the input filter to accept instead of drop would be a great ideia OR would really work. Did not work for me.

try this:

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
--set

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
--update --seconds 60 --hitcount 4 -j DROP

iptables -I INPUT -p tcp --dport 22 -i eth0 -j ACCEPT

By the way, you need to change the 'eth0' by your internet device.

Regards

Drummond Júnior.

[ Parent | Reply to this comment ]

Posted by Anonymous (84.60.xx.xx) on Fri 19 Aug 2005 at 10:04
I have applied this strategy to port 25 after we have had problems with people sending thousands of automated messages to us within just a few hours (obviously trying to and in effect causining some trouble). It works beautifully. Thanks!

[ Parent | Reply to this comment ]

Posted by Anonymous (82.209.xx.xx) on Fri 2 Sep 2005 at 17:48
Hi.

This looks like exactly the thing I'm looking for. However, for some reason, I get the above message when I try it. I have tried with the netfilter kernel modules as modules and built-in. What's the problem?

[ Parent | Reply to this comment ]

Posted by Anonymous (82.209.xx.xx) on Sat 3 Sep 2005 at 10:04
Sorry if I bothered anyone with this. It seems connection tracking must also be enabled in the kernel.

[ Parent | Reply to this comment ]

Posted by Anonymous (80.109.xx.xx) on Sat 10 Sep 2005 at 11:02
Hello!

I implemented the rules on my firewall. The rules seem to work ok, if I test them with a netcat-burst (10 connections as fast as it goes). The first 3 (my setting) are ok but then the limit kicks in. But I get 3 ok-connections for every call of the testscript with the netcat-burst. Also when I try to connect with ssh from the same location 1-2 seconds after a netcat-burst I still get a login-prompt (just to test it). The seconds-parameter doesn't seem to do anything.
Any ideas?
(I'm using Debian Sarge with iptables 1.2.11-10 and kernel 2.6.12.3)

regards

Philipp

[ Parent | Reply to this comment ]

Posted by ajt (84.12.xx.xx) on Fri 23 Sep 2005 at 22:33
[ View Weblogs ]

I have a question...

I've tried this on one of my boxen. It works perfectly for a few days, then it refuses to accept PuTTY connections from a work machine. If I reboot the system, it behaves okay again for several days, then stops working.

I've had a look at the number of packets in the "recent" log, and it's less than the trigger, yet the remote PuTTY connection fails. As far as I can tell the PuTTY connection is dropped before the packets should be explicitly dropped.

With the drop action off, I see only one new packet in the "recent" log, and the connection is accepted.

$IP $CHAIN --dport 22 -i eth0 -m state --state NEW -j LOG --log-prefix "New SSH Request "
$IP $CHAIN --dport 22 -i eth0 -m state --state NEW -m recent --name cracker --set
$IP $CHAIN --dport 22 -i eth0 -m state --state NEW -m recent --name cracker --update --seconds 60 --hitcount 4 -j DROP

Any suggestions...?

Debian Sarge, i386, kernel 2.6.8-2-686, eveything else is stock.

--
"It's Not Magic, It's Work"
Adam

[ Parent | Reply to this comment ]

Posted by denny99 (194.244.xx.xx) on Mon 10 Oct 2005 at 16:35
I'm having a similar problem. If I try to connect to one of my debian boxes, the first connection attempt works and I can log into the system. If I logout and soon try to login again, the connections is dropped. no matter how many hitcounts, I cannot login right after I logout.
If I raise the hitcount to 21 (or more) connections on port 22 are never dropped by iptables. however this setting is useless :\ I'm using a test value of 60 seconds timeframe.

I haven't tried to reboot since the machine is in a production enviroment (so I just can't nor want to reboot it).

[ Parent | Reply to this comment ]

Posted by jabgoe (194.231.xx.xx) on Fri 18 Nov 2005 at 16:09
Did you find a solution for this problem? I have exactly the same behaviour: one connection is accepted, the rest is dropped. With hitcounts more than 21 all connections come through. I can't find any hints to explain this behaviour.

My attempt was:

TIME=60 # Timeframe in seconds
HITS=4 # connection attempts
IP=123.456.789.101 # Limit this to the host
NAME=SSH_SCAN # Name of list with the collected IPs

/sbin/iptables -A INPUT -p tcp --dport 22 -i eth0 -s homeip -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -i eth0 -d "$IP" -m state \
--state NEW -m recent --name "$NAME" --rcheck --seconds "$TIME" \
--hitcount "$HITS" --rttl -j LOG --log-prefix "SSH brute force attack: "
/sbin/iptables -A INPUT -p tcp --dport 22 -i eth0 -d "$IP" -m state \
--state NEW -m recent --name "$NAME" --update --seconds "$TIME" \
--hitcount "$HITS" --rttl -j DROP<br>
/sbin/iptables -A INPUT -p tcp --dport 22 -i eth0 -d "$IP" -m state \
--state NEW -m recent --name "$NAME" --set


Why should a reboot help?

This sounded too god to be true ...:-(

[ Parent | Reply to this comment ]

Posted by denny99 (62.196.xx.xx) on Wed 23 Nov 2005 at 15:08
Still no solution. I had to reboot the server last month - actually I accidentally disconnected the power cord :-) but I couldn't try and see if it worked. Now I'm working for another company and I can't try anymore... sorry.

[ Parent | Reply to this comment ]

Posted by thoger (195.28.xx.xx) on Fri 2 Dec 2005 at 14:48
This thread is too old, but yet this answer may help someone...

ipt_recent module stores list of last N packets for each IP. N is fixed value and defaults to 20, but can be overriden at load time using parameter ip_pkt_list_tot. If you set hitcount to value higher than N, this hitcount can not be reached (ipt_recent will only store last N packets). Hence all traffic is silently passed through.

HTH

[ Parent | Reply to this comment ]

Posted by Anonymous (83.211.xx.xx) on Sat 14 Jan 2006 at 18:34
Doesn't work on Sarge?
What i noticed is that on my Debian Sarge the options --second end --hitcount don't work on the same line.
I did this:
iptables -N denylog
iptables -A denylog -m limit -j LOG
iptables -A denylog -j DROP
iptables -N SSH_BRUTE
iptables -I FORWARD -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I FORWARD -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 20 --name SSH -j SSH_BRUTE
iptables -I SSH_BRUTE -p tcp --dport 22 -m state --state NEW -m recent --update --hitcount 3 --name SSH -j denylog
The result is not the same but it works this way:
- accept the first 3 connection in the first 20 seconds
- any other connection is allowed only at the rate of 1 every 20 seconds
In the average are 3 connection accepted every 60 seconds.
Hope this help and is not a too old post
Dan. Bec.

[ Parent | Reply to this comment ]

Posted by Anonymous (209.161.xx.xx) on Mon 13 Feb 2006 at 23:31
I'm sorry to report that the recent module is broken!
For more details see:
http://blog.blackdown.de/2005/05/09/fixing-the-ipt_recent-netfilt er-module/

[ Parent | Reply to this comment ]

Posted by Anonymous (82.210.xx.xx) on Wed 12 Oct 2005 at 11:37
Does it imply default policy set to ACCEPT? I have default policy set to DROP. I could not make it work (was rejecting the first connection), until I swapped the rules and added -j ACCEPT to the --set rule

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Wed 12 Oct 2005 at 11:39
[ View Steve's Scratchpad | View Weblogs ]

Yes it does. If you had DROP then you'd not accept any traffic, so rate-limitting would be meaningless...

Steve
--

[ Parent | Reply to this comment ]

Posted by Anonymous (82.210.xx.xx) on Wed 12 Oct 2005 at 14:30
Steve, so why not to swap the rules and add -j ACCEPT after the set, so it looks like:

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
--update --seconds 60 --hitcount 3 -j DROP

iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
--set -j ACCEPT

so it will work not matter which default policy is used?

[ Parent | Reply to this comment ]

Posted by Anonymous (12.208.xx.xx) on Thu 10 Nov 2005 at 03:15
Sorry to bump up an old thread, but if you've got testing or better, you might want to check out fail2ban - it is specifically tailored to grep logs looking for an configurable # of pam authentication failures within x amount of time, and inserts a iptables rule that blocks the login for y amount of time. Worked Great For Me (TM). It also does apache blocking, although I don't use it and it can be turned off. Don't forget to edit /etc/fail2ban.conf for extra goodness - the ssh section is down at the bottom.
Course, this doesn't help you if you block yourself out if you're a bad typist...

[ Parent | Reply to this comment ]

Posted by Anonymous (24.177.xx.xx) on Tue 22 Nov 2005 at 03:32
This could also be helpful to limit connections on port 80, I think, particularly if you're having trouble with DDOS attacks that keep sending packets through that protocol. :-)

I just have a question, but I'm not sure if anyone will answer me because this is an older article. Anyways, is there a way to change the iptables setting, so that, for instance you wanted to change the limit of 4 connections per minute to 5 per minute (after already setting it), how would you do that? Would you just use the same command but replace it with the new arguments? Thanks! :D

[ Parent | Reply to this comment ]

Posted by Anonymous (82.234.xx.xx) on Sat 3 Dec 2005 at 18:05
This is very easy: When you create a new, general iptables rule (not only in the context of the recent module), for example by:
iptables -I INPUT (...)
(for inserting a the beginning)
or:
iptables -A INPUT (...)
(for appending at the end)
you can later delete that same rule simply with:
iptables -D INPUT (...)
The important thing is that the rule itself (the "(...)") is absolutely identical and in this case the actual position of the rule does not matter !
Then you can recreate new rules, for exemple with the different limit 5 instead of 4. If the position of the rule in the ruleset matters you can use the syntax:
iptables -I INPUT position (...)
where "position" is just a number (1, 2, ...) giving the position of the new rule in the INPUT chain. By default this is 1 (with -I alone) or at the end (with -A).

You can also use:
iptables -R INPUT position (...)
to replace an actual rule at the postion by the new rule. This is only slightly more dangerous if you are wrong about the exact position of the rule to replace. In case of doubt it is better first to delete (with -D) and then to insert (with -I). Use the "iptables -L INPUT" to show the actual rule set of the INPUT chain.


In general you should use a script with all iptables-rules which you execute at the boot of your computer but sometimes it is necessaire to change only a few rules in a very long and complicated ruleset (sometimes created by other software such as shorewall etc.). In particular, the complete rerunning of the main script has typically the effect to clear the special files in /proc/net/ipt_recent/
which are created when using the ipt_recent module. When you use the option "--name bad_ip_list" with the above rules in this topic you will have a virtual file /proc/net/ipt_recent/bad_ip_list and you can simply look at its content (i.e.: the actual matched IP-numbers with their attempted access number) by: "cat /proc/net/ipt_recent/bad_ip_list". This is very useful to survey the proper working of your firewall setting with ipt_recent. (For this you should also use a lot of rules with "-j LOG ..." to give messages in /var/log/messages.)

When you change only a few rules in the way described above you may eventually keep the content of these special files. Otherwise when you flush the INPUT chain (with "-F") then you will certainly erases these files which is not always desired.

[ Parent | Reply to this comment ]

Posted by gizurieta (196.40.xx.xx) on Wed 28 Dec 2005 at 20:14
Steve, thanks for your article. It has been to me very usefull for my work, because recently I was in charge of an installation and discovered in logs files the attempts of non-authorized connection via ssh.

[ Parent | Reply to this comment ]

Posted by Anonymous (24.173.xx.xx) on Sat 31 Dec 2005 at 19:59
Shouldn't the order of the rules be reversed? Since you are using -I to insert the rules at the top of the chain, don't you want to insert the DROP rule first, since the --set rule will be inserted above it and processed first? If you do this:
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
the end result will look like this:
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
           tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: SET name: DEFAULT side: source
DROP       tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: UPDATE seconds: 60 hit_count: 4 name: DEFAULT side: source
Note the --set rule is first. Thomas

[ Parent | Reply to this comment ]

Posted by Anonymous (24.173.xx.xx) on Sat 31 Dec 2005 at 20:06
Argh. Darn it, I fat-fingered. I meant this: You need to add the rules in this order:
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
in order to get this configuration:
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
           tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: SET name: DEFAULT side: source
DROP       tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: UPDATE seconds: 60 hit_count: 4 name: DEFAULT side: source

Sorry for the confusion.
Thomas

[ Parent | Reply to this comment ]

Posted by Anonymous (24.124.xx.xx) on Tue 21 Feb 2006 at 17:33
Has anyone found a version of this that actually works? I've put the rules in both as the article has them and as Thomas posting them and there hasn't been any limit to how many times an IP can attempt to connect. If anyone has any suggestions it would be appreciated.

[ Parent | Reply to this comment ]

Posted by Anonymous (81.228.xx.xx) on Fri 20 Jan 2006 at 21:45
Thanks alot! I've been looking for this since i've installed ssh. It worked like a charm. //Stefan

[ Parent | Reply to this comment ]

Posted by Anonymous (200.180.xx.xx) on Wed 10 May 2006 at 15:03
What about using DenyHosts? (http://denyhosts.sf.net/)
I'm using in a few servers with incredible success, even in low-end machines (300MHz Celeron).
I use iptables only to throttle SYNs to the ssh server (I limit them on 0.5/second, experimentally chosen according to SSH usage over here). Recently I also tried connlimit, but that didn't work as expected/documented.

[ Parent | Reply to this comment ]

Posted by Anonymous (128.153.xx.xx) on Wed 7 Jun 2006 at 19:06
I was about to ask "Has anyone heard of DenyHosts?" :P Works great for my server and home box (which I like to SSH to), but I was looking for a way to stop bruteforce DOS style attacks on Port 80, I'll have to give this a try! As always Debian-Administration.org is as valuble to a sysadmin as Perl ;P

[ Parent | Reply to this comment ]

Posted by Dino (213.6.xx.xx) on Sun 2 Jul 2006 at 21:34
Have you guys use tc qdisc? for bandwith shaping?

It was working fine in 2.4 and after i upgrade to kernel 2.6 it seems not working

Linux deb 2.6.17-1-686 #1 SMP Thu Jun 29 21:48:36 UTC 2006 i686 GNU/Linux

and i got an something when the ppp clients login to the box

Jul 2 23:22:08 deb kernel: Ingress scheduler: Classifier actions prefered over netfilter

the tc qdisc showing me this so im not sure if it's working or no

deb:/etc/ppp/ip-up.d# tc qdisc show
qdisc pfifo_fast 0: dev eth0 [Unknown qdisc, optlen=20]
qdisc pfifo_fast 0: dev eth1 [Unknown qdisc, optlen=20]
qdisc htb 1: dev ppp1 r2q 10 default 1 direct_packets_stat 0
qdisc ingress ffff: dev ppp1
qdisc htb 1: dev ppp3 r2q 10 default 1 direct_packets_stat 0
qdisc ingress ffff: dev ppp3
deb:/etc/ppp/ip-up.d#

so tell me guys if i need to enable it in the kernel and what do i have to do

thanks
Dino

[ Parent | Reply to this comment ]

Posted by Anonymous (72.192.xx.xx) on Thu 3 Aug 2006 at 15:44
Through trial and error I discovered that rate limiting does not work on a NAT box with port 22 forwarded to an internal host. I found that the rate limiting rules has to be on the target host.

[ Parent | Reply to this comment ]

Posted by mnaumann (213.39.xx.xx) on Wed 11 Oct 2006 at 19:24
[ View Weblogs ]

Many have not realized it yet, so I'm adding this note here.

The ipt_recent implementation in 2.6 kernels prior to 2.6.18 was considered bad if not broken code by several kernel hackers. Some of these vanilla kernels were also vulnerable to two related security issues, namely CVE-2005-2872 and CVE-2005-2873.

With 2.6.12, CVE-2005-2872 was fixed, however CVE-2005-2873 was not fixed before July 10th. It is unclear which was the first kernel version to contain both security fixes, it may have been fixed in a later 2.6.17 version - please check the linux changelogs. Linux 2.6.18 contains a complete rewrite of ipt_recent, which should be reliable and not vulnerable to these issues.

More information on blog.blackdown.de

[ Parent | Reply to this comment ]

Posted by Anonymous (66.191.xx.xx) on Mon 13 Nov 2006 at 02:30
Another solution would be to use denyhosts, that is if your looking to block ssh attempts, but this has nothing to do with rate-limiting.

[ Parent | Reply to this comment ]

Posted by kjteoh (203.115.xx.xx) on Wed 7 Feb 2007 at 06:24
/usr/sbin/iptables -A INPUT -i eth0 -m state --state NEW,ESTABLISHED,RELATED \
-p tcp -s 0.0.0.0 -d 123.123.123.123 --dport 22 \
-m limit --limit 1/minute --limit-burst 2 -j ACCEPT
kjteoh

[ Parent | Reply to this comment ]

Posted by lars (69.221.xx.xx) on Fri 30 Mar 2007 at 15:39
Is it possible to have an iptables rule that doesn't block accepted connections only failed ones? The problem with rate limiting that I ran into in the past was that I like to scp files and if I set the rules to tight I end up dropping myself. As I understand it iptables and ssh are separate entities and iptables doesn't know if a connection was accepted by ssh or failed. I saw an article on linux.com and the author suggested iptables limiting rules but stated "if a user enters the wrong password" .. then they will be blocked. But really I think (please tell me if I am wrong) users will get limited by iptables no mater the state of the connection.

[ Parent | Reply to this comment ]

Posted by Steve (62.30.xx.xx) on Sun 1 Apr 2007 at 11:53
[ View Steve's Scratchpad | View Weblogs ]

You almost certainly want the fail2ban or denyhosts package - rather than an iptables based solution.

There are some simple ssh tips on this site which might be useful too.

Steve

[ Parent | Reply to this comment ]

Posted by Anonymous (85.73.xx.xx) on Wed 4 Apr 2007 at 20:55
recent module works perfect on my lan devices ex: eth0 , eth1 , ra0(wireless) but when i put the same rules but instead of eth0,eth1,ra0 use ppp0 then it just drop the connections to the servers.. amy idea ?
Or if i dont put interface parametre on iptables command recent modules works fine on my lans... not for internet clients that try to connect..
Any solution ??

I have installed:
net-firewall/iptables-1.3.7
sys-kernel/gentoo-sources-2.6.20-r4

[ Parent | Reply to this comment ]

Posted by Anonymous (193.109.xx.xx) on Tue 12 Aug 2008 at 15:26
Great Work! but:
I dlike to abuse this script to stop spamers;
U think im a fool but my Mailservers are under very heavy load (3000 Mails/Minute each)
So i adjust the setting to Port TCP25 and it seems to work but:

the Spammers are not locked out / only rate-limited ;-)

So i have to add something to block this IPs for more than a few seconds; 10 or 15 Minutes would be very nice;

Any advice?

[ Parent | Reply to this comment ]

Posted by Anonymous (24.230.xx.xx) on Sun 29 Nov 2009 at 21:24
http://www.aczoom.com/cms/blockhosts

Use this configuration
Post from Sun, 2005-07-03 10:01
just scroll down in http://www.aczoom.com/cms/blockhosts

[ Parent | Reply to this comment ]

Posted by Anonymous (212.49.xx.xx) on Fri 4 Dec 2009 at 13:59
Hi,

I have one script that depends on the conditions make some N amount of SSH connections to the server.

If I just use example that was brought earlier the script will be banned sometime.

Is it possible to use ssh-brute-force iptables rules but with user exception? That user "John" can make any amount of connections?

Thanks.

[ Parent | Reply to this comment ]

Posted by Anonymous (195.83.xx.xx) on Mon 15 Nov 2010 at 12:29
Hi,

Sorry to bump this thread post at my turn... I have a little question :

I have a set of rules based on the first post and it works perfectly.

I'm just wondering how to increase the lenght of the "ban".
I understand that "--seconds 60 --hitcount 4" is needed to evaluate the rate so... where can I define how much time a DROP will be valid ?


Best regards,

Extract :

#!/bin/sh
#
#       Custom Iptables&n bsp;Script
###############################################################

.
.
.

# SSH Brute Force
iptables -A INPUT -i $INT_DEV -p tc p --dport 22 -m state --state NEW&n bsp;-m recent --set --name SSH
iptables -A INPUT -i $INT_DEV -p tc p --dport 22 -m state --state NEW&n bsp;-j SSH_WHITELIST
iptables -A INPUT -i $INT_DEV -p tc p --dport 22 -m state --state NEW&n bsp;-m recent --update --seconds 60 --hi tcount 4 --rttl --name SSH -j LOG&n bsp;--log-prefix 'SSH_brute_force '
iptables -A INPUT -i $INT_DEV -p tc p --dport 22 -m state --state NEW&n bsp;-m recent --update --seconds 60 --hi tcount 4 --rttl --name SSH -j DROP

.
.
.

[ Parent | Reply to this comment ]

Posted by Anonymous (195.83.xx.xx) on Mon 15 Nov 2010 at 12:31
Please don't pay attention to the "&n bsp;" -_-'

[ Parent | Reply to this comment ]

Posted by Anonymous (77.202.xx.xx) on Tue 7 Dec 2010 at 02:59
your second rule don't work for me, 600 seconds block just 60 seconds

[ Parent | Reply to this comment ]

Sign In

Username:

Password:

[Register|Advanced]

 

Flattr

 

Current Poll

What do you use for configuration management?








( 458 votes ~ 5 comments )