Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Every night I get hundreds, sometimes thousands, of failed ssh logins on my RedHat 4 server. For firewall reasons from remote sites, I need to run on the standard port. Is there anything I should be doing to block this. I notice that many come from the same IP address. Shouldn't it be stopping those after a while?

share|improve this question
add comment

15 Answers

up vote 50 down vote accepted

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.

share|improve this answer
1  
I like this solution and I am planning on getting it in place tonight, once I get today's fires out. –  MattMcKnight Jun 2 '09 at 20:10
2  
It slows down attacks and I do recommend it, but because there are ditributed scanning botnets out there, it's not a panacea. There will still be invalid logons from botnets running distributed scans against you. There's not really too much you can do about that, short of some kind of "port knocking" scheme to remotely bring the SSH port up when you want to get in. –  Evan Anderson Jun 2 '09 at 20:16
1  
+1 for @Evan's "port knocking" suggestion. Some info: linux.die.net/man/1/knockd . But don't do it the man page way (i.e., adding/deleting iptables rules), but instead use -m condition iptables match instead. –  pepoluan Mar 10 '11 at 9:24
    
dont you need --dport 22 in these rules so that they are applied only for ssh traffic? –  clime Jan 7 '13 at 22:00
1  
@clime - Yep. Hard to believe this has been here 2 1/2 years and nobody noticed! Good catch. –  Evan Anderson Jan 7 '13 at 22:43
add comment

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

share|improve this answer
8  
i dont like tools/scripts reading logs and issue commands on behalf of the sysadmin user –  asdmin Aug 17 '09 at 18:24
add comment

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.

share|improve this answer
4  
I don't know why people upvote this; SSH is on a standard port 22. This means that when you're on a foreign network, you're not relying on them having open a non-standard port through the outbound firewall. The real solution to this problem is documented above, either restrict the number of repeat connections via your inbound firewall, or, switch-off password logins. –  Andrew Taylor Jan 25 '11 at 10:24
add comment

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.

share|improve this answer
    
To make this safer, run this page on https. –  Robert Munteanu Jun 2 '09 at 18:32
    
If you change the script so it doesn't output the contents of the "allowed temporary IP address" file, there won't be anything for a would-be sniffer to sniff. Then you can run it on http instead of https. –  Barry Brown Aug 18 '09 at 1:40
    
The "allowed temporary IP address" is always that of the requester (ie yours). I don't think it matters one way or another. Https does mean that the requested URL is encrypted meaning that it isn't trivial to sniff it off the wire. –  David Mackintosh Aug 18 '09 at 12:47
    
This won't work if you're on a network that proxies HTTP connections but your direct route to the internet is via a different egress. –  Andrew Taylor Jan 25 '11 at 10:25
add comment

You may want to look at denyhosts as well.

share|improve this answer
add comment

Do yourself a favor and disable the password login. Use exclusively authentication keys (google ssh-keygen for instance - Example: http://www.puddingonline.com/~dave/publications/SSH-with-Keys-HOWTO/document/html/SSH-with-Keys-HOWTO-4.html ) Your server will be more secure, you will connect to it more comfortably (check ssh-agent, ssh-add, keychain) and you will be no more the victim of ssh brute force attacks.

share|improve this answer
add comment

another solution is just move ssh to another port. these worms are pretty stupid.

share|improve this answer
2  
The original poster said he needed to run on the standard port. –  kbyrd Jun 2 '09 at 16:30
1  
sorry, I must read the questions more carefully :) –  disserman Jun 2 '09 at 16:55
1  
I have to agree...I have my SSH running on "alternative" ports and it makes a WORLD of difference in the logs. The worms are about as smart as a brick, so it works well against dumb automation scripts; not so well against human attackers. Still, the logs have the blessed sound of silence in them... –  Avery Payne Oct 5 '09 at 4:22
add comment

Another option might be to require all ssh connections be verified by a certificate and do away with passwords altogether.

I use to use Denyhosts, but I found I was only connecting regularly remotely from a handful of places, so I blocked all port 22 connections except from anywhere else, and use port knocking so I can connect from anywhere with my laptop if I have to.

share|improve this answer
add comment

Any solution which involves automatically blocking IPs after multiple failures introduces risk of denial of service attacks. As long as there's a good password policy in place to reduce the effectiveness of brute force or dictionary attacks, I wouldn't worry too much about them.

If you limit the users/groups to only those who should be allowed to ssh in in the first place, and disable logging in as root, you should be more than secure enough. And, if that's not sufficient, there's always key-based authentication.

share|improve this answer
add comment

Honestly, if you have to run SSH (and on port 22), you can't avoid these. If you must accept passwords, you're in even worse shape.

Your best bet is to configure your log analysis software to exclude the SSH logs. Then run a separate instance to only look at SSH logs, and use procmail to filter out the unsuccessful attempts. You might even write scripts to watch for successful logins from IP addresses with multiple unsuccessful attempts.

There's no way to stop people from probing your SSH server. Denyhosts, fail2ban, and the iptables example will work up to a point, but with the additional danger of accidentally blocking legitimate users. The best method is to suck it up and try to automate the log-analysis process to reduce the amount of time you have to think about it.

share|improve this answer
add comment

When you say you are getting failed shh log in attemps on your red hat server, what sort of firewall is it sitting behind and how many people need to shh into it. I suggest that if you can you want to limit attempts at the firewall before they get anywhere near your actual server.

If you can restrict the range of ip addresses that legitimately need access you should be able to set up an access list on the fire wall. If you can restrict traffic at the firewall i would suggest you look at network intrusion systems, as it sounds like your server is being targeted by something.

share|improve this answer
add comment

Most webhosts use APF+BFD to ip-block failed SSH logins. Nowadays there's CSF (Configserver firewall) which includes a tool called LFD that does the same thing, and more, including block IPs from certain countries you don't want accessing your server (eg Korea, China etc, where 99% of my SSH probes seem to originate from).

share|improve this answer
add comment

Ive been using fail2ban and it has been helping me out alot.

share|improve this answer
add comment

Should you need to address this issue across more than one host, you may want to check out OSSEC: http://www.ossec.net/main/ossec-architecture

This will allow you to configure multiple agents from a centralized location to automatically respond to brute-force attacks (along with any other pattern you can extract from logs).

Very nice piece of software :)

share|improve this answer
add comment

Another option similar to DenyHosts is sshutout http://www.techfinesse.com/sshutout/sshutout.html

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.