Preventing brute force attacks using iptables recent matching

General idea

In recent times our network has seen a lot of attempts to brute-force ssh passwords. A method to hamper such attacks by blocking attacker’s IP addresses using iptables ‘recent’ matching is presented in this text:

When the amount of connection attempts from a certain IP address exceeds a defined threshold, this remote host is blacklisted and further incoming connection attempts are ignored. The host is only removed from the blacklist after it has been stopped connecting for a certain time.

Edit: The fail2ban scripts offer a more sophisticated (but also more heavy-weighted) solution for this problem.

Software requirements

Linux kernel and iptables with ‘recent’ patch. (It seems that this patch has entered the mainline some time ago. ‘Recent’ matching e.g. is known to be included with kernels 2.4.31 and 2.6.8 of Debian Sarge 4.0.)

Implementation

We begin with empty tables…

iptables -F

and add all the chains that we will use:

iptables -N ssh
iptables -N blacklist

Setup blacklist chain

One chain to add the remote host to the blacklist, dropping the connection attempt:

iptables -A blacklist -m recent --name blacklist --set
iptables -A blacklist -j DROP

The duration that the host is blacklisted is controlled by the match in the ssh chain.

Setup ssh chain

In the ssh chain, incoming connections from blacklisted hosts are dropped. The use of --update implies that the timer for the duration of blacklisting (600 seconds) is restarted every time an offending packet is registered. (If this behaviour is not desired, --rcheck may be used instead.)

iptables -A ssh -m recent --update --name blacklist --seconds 600 --hitcount 1 -j DROP

These rules are just for counting of incoming connections.

iptables -A ssh -m recent --set --name counting1
iptables -A ssh -m recent --set --name counting2
iptables -A ssh -m recent --set --name counting3
iptables -A ssh -m recent --set --name counting4

With the following rules, blacklisting is controlled using several rate limits. In this example, a host is blacklisted if it exceeds 2 connection attempts in 20 seconds, 14 in 200 seconds, 79 in 2000 seconds or 399 attempts in 20000 seconds.

iptables -A ssh -m recent --update --name counting1 --seconds 20 --hitcount 3 -j blacklist
iptables -A ssh -m recent --update --name counting2 --seconds 200 --hitcount 15 -j blacklist
iptables -A ssh -m recent --update --name counting3 --seconds 2000 --hitcount 80 -j blacklist
iptables -A ssh -m recent --update --name counting4 --seconds 20000 --hitcount 400 -j blacklist

The connection attempts that have survived this scrutiny are accepted:

iptables -A ssh -j ACCEPT

Setup INPUT chain

Allow packets that belong to existing connections:

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

Allow all packets from loopback interface:

iptables -A INPUT -i lo -j ACCEPT

Optionally we may allow all packets from certain friendly subnets. However this should be used sparingly and it should be kept in mind that hosts from friendly subnets may be compromised and out of a sudden be not so friendly anymore…

iptables -A INPUT -s aa.bb.cc.0/24 -j ACCEPT

Now we direct all incoming ssh connections to the chain of the same name:

iptables -A INPUT -p TCP --dport ssh -m state --state NEW -j ssh

What remains in this chain has no right to continue:

iptables -A INPUT -j DROP

Variations

  • Depending on personal taste, the check against the blacklist (first rule of ssh chain) might be moved to the top of the INPUT chain so that all communication (not only subsequent connection attempts) from the blacklisted host is blocked immediately.
  • Many other packet matching criteria might be conceived that would warrant putting the sender on the blacklist.
  • Identical or similar effects possibly may be achieved using different extensions to iptables.

Limitations

Denial of Service

The described method opens a DoS vulnerability that may be exploited using SYN-packets with fake sender address to disable ssh connections from a certain host. Therefore ‘recent’ matching should not be used, when the ability to connect to the machine from any location and at all times is mission-critical.

Also it should be mentioned, that the ssh daemon itself in its current implementation is vulnerable to DoS: There is an upper value for concurrent connections.

No substitute for secure passwords

The approach described here by no means is a substitute for using secure passwords that are difficult to guess and to brute-force! Disabling root logins in sshd is very much recommended! (Oh, by the way: There is also an option to disallow empty passwords for sshd. ;-) )

Security by Obscurity

It should be noted that this scheme partly employs methods of ‘security by obscurity’ to increase its effectivity. A casual attacker probably will be blocked for a long time (possibly forever) after several tries. Yet a determined, observant attacker still may try passwords at the rate specified by the counting4 rule. However this is still a considerable improvement compared to no limit at all.

Often ‘security by obscurity’ is frowned upon as offering ‘no real’ security. Yet, such an opinion is undifferentiated. It may be very well true that secrecy does not increase the hardness of the system with respect to ‘the most elaborate attack’ that still will be averted. However for sure it is well suited to stall casual attacks and by such reduce the overall number of attacks. Seen in this light, it might also be sensible to use a non-standard port for ssh service.

Further Reading

About this document

These are some random scribblings prepared for a meeting of sysadmins (February 2006) at TUM Physik-Department. Most of the idea and implementation go back to Roland Kuhn.

Dieser Beitrag wurde unter Computing abgelegt und mit , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

3 Antworten auf Preventing brute force attacks using iptables recent matching

  1. Marcin sagt:

    Hello Thiemo,

    I was trying to use your solution in my iptables rules but a totally don’t know why these two rules doesn’t work
    iptables -A ssh -m recent –update –name counting3 –seconds 2000 –hitcount 80 -j blacklist
    iptables -A ssh -m recent –update –name counting4 –seconds 20000 –hitcount 400 -j blacklist

    The funny thing is that two lines above works …

    iptables -A ssh -m recent –update –name counting1 –seconds 20 –hitcount 3 -j blacklist
    iptables -A ssh -m recent –update –name counting2 –seconds 200 –hitcount 15 -j blacklist

    do You have any idea what may be the reason?

    the error says: iptables: Invalid argument. Run `dmesg’ for more information.
    but nothing interesting is in dmesg … only something like this:

    [ 9591.724862] ip_tables: (C) 2000-2006 Netfilter Core Team
    [12902.858290] nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
    [12902.858818] CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Please use
    [12902.858818] nf_conntrack.acct=1 kernel parameter, acct=1 nf_conntrack module option or
    [12902.858818] sysctl net.netfilter.nf_conntrack_acct=1 to enable it.

    regards,
    Marcin

  2. Pingback: Suggested iptables reading | mildly interesting

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

CAPTCHA-Bild

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>