Mitigating SSH Attacks

first published:
Feb 14, 2008
tags:

Brute-force password-guessing attacks on SSH services are common on the Internet today. They are a threat for two reasons:

Both of these scenarios are bad. We can substantially reduce, or even eliminate these threats by rate-limiting incoming SSH connections — not globally, but on a per-source-IP basis. On Linux, we can use the RECENT match facility available in modern versions of iptables to achieve this.

Here is prettified version of the configuration that is currently running on Kalimdor; see the comments in-line for an explanation of what each rules does.

⚠ Caution

Before proceeding, check that your kernel version is greater than or equal to 2.6.18. Do not use the RECENT match implementation included in kernels prior to 2.6.18 as it is faulty; see CAN-2005-2872 and CAN-2005-2873 for details.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# INPUT:
#   First, we add any inbound SSH connection attempts to an
#   'ssh-clients' list.</span>
iptables -A INPUT -i eth0 -p tcp -m tcp -m state --state NEW --dport 22 \
        -m recent --set --name ssh-clients --rsource

#   Then, we check to see if the source of the current packet has
#   attempted to connect more than 5 times in the last 60 seconds.  If
#   it has, then we treat it as a brute-force attack and send it to the
#   SSHATTACK chain, which does not return.
iptables -A INPUT -i eth0 -p tcp -m tcp -m state --state NEW --dport 22 \
        -m recent --update --seconds 60 --hitcount 5 --name ssh-clients \
        --rsource -j SSHATTACK

# SSHATTACK ruleset:
#   First, we log the incoming SSH attack.  However, because many
#   logged attacks could DoS our logging filesystems (and, because the
#   kernel echos everything to our slow serial terminal, the kernel as a
#   whole) we rate-limit the log messages, too.
iptables -A SSHATTACK -m limit --limit 1/minute --limit-burst 5 -j LOG \
        --log-prefix "SSH ATTACK: "

#   Finally, we reject the connection attempt.  Currently, we simply
#   return a 'port-unreachable' error packet, as if there were no
#   service listening -- but other options, such as
#   "icmp-admin-prohibited" might be more net-friendly.
iptables -A SSHATTACK -j REJECT --reject-with icmp-port-unreachable

This scheme will likely become wildly impractical as IPv6 takes off; with 128-bits of address-space and a liberal allocation scheme, any intelligent attacker would jump between available addresses within the netblock that they control. When this happens, more sophisticated mechanisms for identifying and dropping packets from whole netblocks will become necessary.