83

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?

16 Answers 16

70

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.

5
  • 1
    I like this solution and I am planning on getting it in place tonight, once I get today's fires out. Jun 2, 2009 at 20:10
  • 3
    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. Jun 2, 2009 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, 2011 at 9:24
  • 2
    dont you need --dport 22 in these rules so that they are applied only for ssh traffic?
    – clime
    Jan 7, 2013 at 22:00
  • 2
    @clime - Yep. Hard to believe this has been here 2 1/2 years and nobody noticed! Good catch. Jan 7, 2013 at 22:43
39

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

2
25

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.

2
  • 6
    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. Jan 25, 2011 at 10:24
  • 1
    OpenSSH 6.7 drops tcpwrappers support, which is what denyhosts uses.
    – Zoredache
    Oct 30, 2014 at 21:31
15

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.

5
  • To make this safer, run this page on https. Jun 2, 2009 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. Aug 18, 2009 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. Aug 18, 2009 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. Jan 25, 2011 at 10:25
  • OpenSSH 6.7 drops tcpwrappers support, which is what is being used in your answer.
    – Zoredache
    Oct 30, 2014 at 21:31
9

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.

9

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.

2

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

4
  • 4
    The original poster said he needed to run on the standard port.
    – kbyrd
    Jun 2, 2009 at 16:30
  • 1
    sorry, I must read the questions more carefully :)
    – disserman
    Jun 2, 2009 at 16:55
  • 2
    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... Oct 5, 2009 at 4:22
  • ..it's not that the bots are "stupid", it's that they're designed to look for low-hanging fruit. So moving the SSH port is in the style of ..keep your fruit off the ground.
    – elrobis
    Feb 27, 2019 at 17:05
2

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.

1

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.

1

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.

1

It's a quite old topic and needs some refresh ;) Nowadays, the best option is to use 2FA like https://ubuntu.com/tutorials/configure-ssh-2fa#1-overview. After setting it up on my server, bots stopped trying to intrude immediately unlike the accepted iptables solution.

0

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.

0

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).

0

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

0

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 :)

0

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .