Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to decrease the likelihood of a successful ssh attack on a linux system. The only port that is open is 22 (I use port forwarding for everything else), and of course I made sure that ssh accepts only key-pair-based logins (no passwords).

The volume of failed ssh login attempts (output of last -f /var/log/btmp) was fairly large (as anybody opening up port 22 should expect), so for the last 2+ years I've been relying on a variation af the iptables-based solutions often mentioned to block ssh attacks, for example Hundreds of failed ssh logins.

One annoying drawback of such a scheme is that it limits the number of new connections from an ip address per amount of time, no matter whether previous connections from that ip were successful or not and whether they were trying to log in as the same user or not. Imagine a script containing half a dozen of rsync commands used from abroad to update various areas on that server: it typically hits the "new connection limit" and fails somewhere in the middle. The same goes if several users behind a router (showing up as the same IP address) do connect on my server more or less at the same time.

So, I am wondering if, without resorting to parsing the /var/log files, it is possible to implement the following strategy with iptables:

  1. accept established connections
  2. allow new connections from previously successful connections
  3. put IPs with failed connections in jail for some time

Bonus points:

  1. Same as above, but allowing/jailing specific user@ip instead of everybody @ip.

And to attempt to curb botnet attacks:

  1. Temporarily put in jail a user (no matter which IP (s)he connects from) after a failed ssh attempt.
share|improve this question
up vote 5 down vote accepted

Without parsing logfiles, you can't know if an ssh login attempt was succesful. Fortunately you don't have to parse those logfiles yourself. fail2ban can do this for you. I generally jail an IP for a week after 3 failed login attempts.

share|improve this answer

First of all do not have ssh listen on port 22 to reduce the chance of your port being found by automated scanners.

Also use psad to automatically block hosts which scan your machine for a configurable amount of time (1 hour by default).

A very simple solution is to just rent a 64 or 128 meg openvz container & configure openvpn so you have a fixed ip address & then limit your iptables rule to --source vpn.ip.address on the host you wish to protect.

A better solution is to completely stealth your ssh port withfwknop. There is then no need to run fail2ban as your ssh port is closed until you send a gpg signed & encrypted packet from the fwknop-client which will open your firewall for a configurable amount of time (30 seconds by default). You can also configure fwknop to only accept certain ip addresses (such as your vpn).

I have some quite extensive notes here for fwknop.

If you are serious about ssh security you should also be using ed25519 keys. More notes here for using secure ciphers with openssh. Another a good choice is tinyssh which has no dependency on openssl & is secure by default.

All of the software mentioned here exists in Alpine Linux which also benefits from address space layout randomization via PaX in it's Grsecurity kernel.

share|improve this answer

Your Answer


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.