Limiting Failed SSH Logins using PAM

Ever wanted to limit the number of ssh login attempts a user can make
before their account gets locked? Well, not really, but when brute force
tools are so common and easy to use it’s another useful trick in the
sysadmins arsenal.

In this example I’ll show you how to install, configure and audit failed
ssh loging attempts on Linux. While the PAM mod_tally module is available for a
number of different distros and Unix variants we’ll set it up on Debian.
First of all grab the package if you don’t already have it -

apt-get install libpam-modules

Now we’ve installed mod_tally you have to add a couple of lines to the
/etc/pam.d/ssh PAM config file for ssh.

The ordering of the lines is important. In some configurations
previous PAM checks can shortcut the full process. While this post
isn’t the place to learn all about PAM the first line of the example
sets what to do if something strange happens, such as the log file being
unavailable (onerr=fail) and how many times a login can fail before
being locked (deny=3). The second line tells PAM to reset the counter
once a successful login has occurred for a specific user. If you leave
this one out every failure is remembered for ever and eventually all will
be locked out.

Now you’re up and running how do you find out what’s happening? If you
want to look at the current status then you can run the
pam_tally command and you’ll see output like this -

pam_tally also logs wherever your authentication events go
(/var/log/auth.log on Debian by default ) so you can keep
historical information or feed the attempts in to your normal log
monitoring systems

To close the loop let’s cover resetting the locked accounts. If you have
a user complaining then you can run pam_tally --reset --user
lockme to clear their tally. Another option (worth considering) is a
scheduled reset. This gives you the benefit of slowing down brute force
attacks while not requiring you to unlock all accidentally locked accounts.
The simplest way to do this is to add a cronjob that runs a reset. Newer
versions have an unlock_time=n option you can supply in the
ssh PAM config file but that didn’t work for me under Etch.