Hundreds of failed ssh logins

Solution 1:

You can use iptables to rate-limit new incoming connections to the SSH port. I'd have to see your entire iptables configuration in order to give you a turnkey solution, but you're basically talking about adding rules like:

iptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 5 --name SSH --rsource -j DROP 
iptables -A INPUT -p tcp --dport 22 -m recent --set --name SSH --rsource -j ACCEPT 

These rules assume that you're accepting ESTABLISHED connections earlier in the table (so that only new connections will hit these rules). New SSH connections will hit these rules and be marked. In 60 seconds, 5 attempts from a single IP address will result in new incoming connections from that IP being dropped.

This has worked well for me.

Edit: I prefer this method to "fail2ban" because no additional software to be installed, and happens totally in kernel-mode. It doesn't handle parsing log files like "fail2ban" will, but if your problem is only with SSH I wouldn't use something user-mode that requires software installation and is more complex.

Solution 2:

fail2ban can help with this by blocking IP addresses with too many failed log in attempts.


Solution 3:

I'd recommend using a non-standard port for SSH if you can (ie. port 10222) but since you mentioned you can't do that I'd recommend using something such as DenyHosts.

http://denyhosts.sourceforge.net/

Great package, easy to install and configure.


Solution 4:

While it may be nice to be able to ssh into your system from arbitrary locations on the internet, there are automated password attack systems which will lock onto an open ssh port and apply various joe account and dictionary attacks against your system. This can be aggrevating to read in your nightly log summary and is a waste of your bandwidth.

If you have a web server on the same system, you can use php and tcp wrappers to restrict ssh inbound traffic to known systems, plus give you a back-door key to permit yourself access from arbitrary systems on the internet.

Here's how you do it:

deny all ssh connections in /etc/hosts.deny:

# /etc/hosts.deny fragment
sshd:  all

Allow known systems by IP in /etc/hosts.allow, plus add a file for temporary access:

# /etc/hosts.allow fragment
sshd:  10.0.10.2     # some system
sshd:  172.99.99.99  # some other system
sshd:  /etc/hosts.allow.temporary-sshd-access

Create a php file in your web server and give it a non-obvious name like my-sshd-access.php:

<?php
function get_ip()
{
    return getenv("REMOTE_ADDR"); 
}

?>

<?php
$out='/etc/hosts.allow.temporary-sshd-access';
$log='/var/log/sshd-access-addition-log';

print "Was:";
readfile($out);
print "<br>";
$ip=get_ip();
$fp=fopen($out,"w");
fputs($fp,$ip);
fclose($fp);

$lfp=fopen($log,"a");
fputs($lfp,$ip);
fputs($lfp,"n");
fclose($lfp);

print "Wrote: ";
readfile($out);
?>

Forgive the php code -- I swiped it from somewhere else, so it could probably stand to be cleaned up a whole bunch. All it does is add the IP address of the system accessing it to the /etc/hosts.allow.temporary-sshd-access file, which is read by sshd (due to its inclusion by /etc/hosts.allow) at connection time.

Now when you are at some arbitrary system on the web and want to ssh to this system, first use a web browser and hit this file (or use wget or equivilent):

$ wget http://your.system.name/my-sshd-access.php

Now you should be able to ssh in to your system. If this is somewhere you will likely be ssh'ing in from frequently, it would be trivial to read the contents of the /etc/hosts.allow.temporary-sshd-access file and permanently add the IP address to /etc/hosts.allow.


Solution 5:

You may want to look at denyhosts as well.

FYI: OpenSSH 6.7 drops tcpwrappers support, meaning denyhosts probably isn't the solution for new installations.

Tags:

Linux

Ssh

Redhat