I am usually using different methods in a combination. In the sshd_config
I declare AllowGroups
with the group ssh-users
. This group does never contain root
. Furthermore I set PasswordAuthentication no
and generally authenticate only by key. Root login is of course not allowed either, except in single-user mode (PermitRootLogin no
). Of course root
has a different key, which will only be used in emergency cases, i.e. in single-user mode. Martin F. Krafft, author of the Debian book, has a nice recipe for this (note, that there is an erratum on the book’s website). Set this in your /etc/inittab
:
sh:S:respawn:/usr/sbin/sshd -Do 'AllowUsers=root'
That will already keep out most attackers since they will try passwords most of the time. However, we can make it a bit harder for them. In order to achieve this, you just need a recent version of iptables
. You will need the ipt_recent
module of iptables
installed as well. There are two programs coming with iptables, which can be used to save and restore the iptables
rules. They are aptly named iptables-save
and iptables-restore
. We’ll use the latter one for our purposes. It allows us to declare rules and have them stored conveniently in a file. I usually call the file something like /etc/firewall.conf
, but that’s a matter of taste.
*filter # Accept a particular IP to connect without restrictions. This could # be an IP from your network, for example -A INPUT -i eth0 -p tcp -m tcp --dport 22 --source YourOtherIP ↵ -m state --state NEW,ESTABLISHED -j ACCEPT # This rule checks whether the IP that connects has tried in vain # more than "hitcount" within "seconds". -A INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW ↵ -m recent --update --seconds 60 --hitcount 4 --name RecentList ↵ --rsource -j DROP # If the connection wasn't dropped, increase the "counter" for the # previous rule to check next time the IP makes an attempt. -A INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW ↵ -m recent --set --name RecentList --rsource # Commit above rules COMMIT
(The “line breaks” marked by ↵ should not be copied 😉 )
Change YourOtherIP to your taste and, if needed, repeat the rule for other IPs you want to allow. Subnet matching requires special support, so giving single IPs is the better choice. RecentList is just the name of the “counter” – feel free to change it as well. COMMIT is required to commit the rules and have them take effect. In my case (Debian Etch), I am using /etc/network/interfaces
to declare a comment that is being executed when the network interface comes up. Here’s how the line looks on my machine:
up iptables-restore -c < /etc/firewall.conf
Of course you can adjust the parameters --seconds 60
and --hitcount 4
to suit your needs. In my case anyone trying to brute-force at a normal pace will just get stuck after the fourth connection attempt.
In addition to this, you could install something like DenyHosts or pam_abl
. However, something like fail2ban
, which is essentially doing the same as the simple rules above, just with the help of a Python script. But it may be effective if the attackers are very persistent (just keep an eye on your logs) or if you are very paranoid 😉 😆
// Oliver