APLawrence.com -  Resources for Unix and Linux Systems, Bloggers and the self-employed

SSH Login Attacks

Web Site: http://www.soloport.com

From http://www.soloport.com/iptables.htm, used by permission.


A few months ago, I began seeing our 'secure' log files fill up with entries stating: "Failed password for illegal user [username]". I decided to search the Internet to find out if others were experiencing these attacks and, hopefully, find a solution. I did uncover a lot of information on the subject, but discovered only a few script-based solutions. None of these, however, seemed... well... elegant.

What I wanted was a way to stop the attacks altogether, yet allow ssh access from anywhere, when needed. In addition, I wanted to avoid using an approach that was so complicated it could lead to more pain than I was experiencing from the original problem.

My requirements looked something like this:

  • Keep port 22 closed, until needed
  • Provide a simple way to open and close port 22 from any remote location
  • Ensure the method used is reasonably difficult for attackers to discover
  • Use an "elegant" method (i.e. not a lot of software)

The solution should behave similar to the following shell prompt activity:

    $ ssh name@hostname # No response (Ctrl-C to abort)
    $ telnet hostname 1600 # Telnet into port 1600 to open port 22
    $ ssh name@hostname # Now logins are allowed
    name@hostname's password:
    $ telnet hostname 1601 # Telnet into port 1601 to close port 22

Note that the ports used to open and close port 22 should appear closed, as well. This approach would be a sort of simplified "port knocking" technique.

Proposed Solution

The 'recent' module in iptables is designed to detect malicious access attempts and then block or at least honeypot the potential intruder with delays. I've sort of turned this module on its head and, instead, used it to let people in.

The following represents the contents of an iptables file, drawn from a Red Hat distribution (the usual path is /etc/sysconfig/iptables). The highlighted text outlines the changes needed to support our style of port knocking.

:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -s -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m recent --rcheck --name SSH -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m udp -p udp --dport 123 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 1599 -m recent --name SSH --remove -j DROP
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 1600 -m recent --name SSH --set -j DROP
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 1601 -m recent --name SSH --remove -j DROP
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited

Note that there is a "close" port on either side of the "open" port. This should cause most linear port scans (ascending or descending) to leave port 22 closed, upon completion. For an even more robust approach, use two separate "open" ports -- such as a knock at port 1300, followed by a knock at port 1600. Also keep in mind, once you have ssh-connected, you can then close the port without losing your established connection.


What's really convenient about this method is, when you're at a specific, trusted location (say, in the office) and you unlock a target site (say, a home server), you need only knock once; The port will stay open for that specific source IP address, indefinitely (or until iptables is restarted). If you attempt to use the port from another location (say, a client's office), it will appear closed -- until you knock. What I find really elegant about this approach is, you don't have to fill up your iptables with dozens of DROP entries in order to block the world of would-be crackers.

Sample Log

Here is a representative sample from a 'secure' log file:

Jan  7 09:58:47 hostname sshd[24729]: Illegal user test from [IP_ADDRESS_A]
Jan  7 09:58:50 hostname sshd[24729]: Failed password for illegal user test from [IP_ADDRESS_A] port 51250 ssh2
Jan  7 09:58:52 hostname sshd[24731]: Illegal user guest from [IP_ADDRESS_A]
Jan  7 09:58:54 hostname sshd[24731]: Failed password for illegal user guest from [IP_ADDRESS_A] port 51396 ssh2
Jan  7 09:58:56 hostname sshd[24733]: Illegal user admin from [IP_ADDRESS_A]
Jan  7 09:58:58 hostname sshd[24733]: Failed password for illegal user admin from [IP_ADDRESS_A] port 51546 ssh2
Jan  7 09:59:00 hostname sshd[24735]: Illegal user admin from [IP_ADDRESS_A]
Jan  7 09:59:03 hostname sshd[24735]: Failed password for illegal user admin from [IP_ADDRESS_A] port 51688 ssh2
Jan  7 09:59:04 hostname sshd[24737]: Illegal user user from [IP_ADDRESS_A]
Jan  7 09:59:07 hostname sshd[24737]: Failed password for illegal user user from [IP_ADDRESS_A] port 51828 ssh2
Jan  7 09:59:11 hostname sshd[24739]: Failed password for root from [IP_ADDRESS_A] port 51963 ssh2
Jan  7 09:59:15 hostname sshd[24741]: Failed password for root from [IP_ADDRESS_A] port 52114 ssh2
Jan  7 09:59:20 hostname sshd[24743]: Failed password for root from [IP_ADDRESS_A] port 52288 ssh2
Jan  7 09:59:22 hostname sshd[24745]: Illegal user test from [IP_ADDRESS_A]
Jan  7 09:59:24 hostname sshd[24745]: Failed password for illegal user test from [IP_ADDRESS_A] port 52419 ssh2
Jan  7 16:35:22 hostname sshd[25103]: Failed password for nobody from [IP_ADDRESS_C] port 53721 ssh2
Jan  7 16:35:25 hostname sshd[25105]: Illegal user patrick from [IP_ADDRESS_C]
Jan  7 16:35:28 hostname sshd[25105]: Failed password for illegal user patrick from [IP_ADDRESS_C] port 53832 ssh2
Jan  7 16:35:31 hostname sshd[25107]: Illegal user patrick from [IP_ADDRESS_C]
Jan  7 16:35:33 hostname sshd[25107]: Failed password for illegal user patrick from [IP_ADDRESS_C] port 53907 ssh2
Jan  7 16:35:39 hostname sshd[25109]: Failed password for root from [IP_ADDRESS_C] port 54003 ssh2
Jan  7 16:35:45 hostname sshd[25111]: Failed password for root from [IP_ADDRESS_C] port 54093 ssh2
Jan  7 16:35:50 hostname sshd[25113]: Failed password for root from [IP_ADDRESS_C] port 54181 ssh2
Jan  7 16:35:58 hostname sshd[25115]: Failed password for root from [IP_ADDRESS_C] port 54312 ssh2
Jan  7 16:36:04 hostname sshd[25117]: Failed password for root from [IP_ADDRESS_C] port 54395 ssh2
Jan  7 16:36:07 hostname sshd[25119]: Illegal user rolo from [IP_ADDRESS_C]
Jan  7 16:36:10 hostname sshd[25119]: Failed password for illegal user rolo from [IP_ADDRESS_C] port 54488 ssh2
Jan  7 16:36:14 hostname sshd[25121]: Illegal user iceuser from [IP_ADDRESS_C]
Jan  7 16:36:16 hostname sshd[25121]: Failed password for illegal user iceuser from [IP_ADDRESS_C] port 54577 ssh2
Jan  7 16:36:21 hostname sshd[25123]: Illegal user horde from [IP_ADDRESS_C]
Jan  7 16:36:23 hostname sshd[25123]: Failed password for illegal user horde from [IP_ADDRESS_C] port 54681 ssh2
Jan  7 16:36:26 hostname sshd[25125]: Illegal user cyrus from [IP_ADDRESS_C]
Jan  7 16:36:28 hostname sshd[25125]: Failed password for illegal user cyrus from [IP_ADDRESS_C] port 54786 ssh2
Jan  7 16:36:32 hostname sshd[25127]: Illegal user www from [IP_ADDRESS_C]
Jan  7 16:36:34 hostname sshd[25127]: Failed password for illegal user www from [IP_ADDRESS_C] port 54878 ssh2
Jan  7 16:36:37 hostname sshd[25129]: Illegal user wwwrun from [IP_ADDRESS_C]
Jan  7 16:36:40 hostname sshd[25129]: Failed password for illegal user wwwrun from [IP_ADDRESS_C] port 54966 ssh2
Jan  7 16:36:43 hostname sshd[25131]: Illegal user matt from [IP_ADDRESS_C]
Jan  7 16:36:46 hostname sshd[25131]: Failed password for illegal user matt from [IP_ADDRESS_C] port 55050 ssh2
Jan  7 16:36:50 hostname sshd[25133]: Illegal user test from [IP_ADDRESS_C]
Jan  7 16:36:53 hostname sshd[25133]: Failed password for illegal user test from [IP_ADDRESS_C] port 55152 ssh2
Jan  7 16:36:57 hostname sshd[25135]: Illegal user test from [IP_ADDRESS_C]
Jan  7 16:36:59 hostname sshd[25135]: Failed password for illegal user test from [IP_ADDRESS_C] port 55263 ssh2
Jan  7 16:37:02 hostname sshd[25137]: Illegal user test from [IP_ADDRESS_C]
Jan  7 16:37:04 hostname sshd[25137]: Failed password for illegal user test from [IP_ADDRESS_C] port 55366 ssh2
Jan  7 16:37:08 hostname sshd[25139]: Illegal user test from [IP_ADDRESS_C]
Jan  7 16:37:10 hostname sshd[25139]: Failed password for illegal user test from [IP_ADDRESS_C] port 55457 ssh2
Jan  7 16:37:13 hostname sshd[25141]: Illegal user www-data from [IP_ADDRESS_C]
Jan  7 16:37:16 hostname sshd[25141]: Failed password for illegal user www-data from [IP_ADDRESS_C] port 55548 ssh2
Jan  7 16:37:21 hostname sshd[25143]: Failed password for mysql from [IP_ADDRESS_C] port 55637 ssh2
Jan  7 16:37:26 hostname sshd[25145]: Failed password for operator from [IP_ADDRESS_C] port 55724 ssh2
Jan  7 16:37:33 hostname sshd[25147]: Failed password for adm from [IP_ADDRESS_C] port 55799 ssh2
Jan  7 16:37:42 hostname sshd[25149]: Failed password for apache from [IP_ADDRESS_C] port 55912 ssh2
Jan  7 16:37:52 hostname sshd[25151]: Illegal user irc from [IP_ADDRESS_C]
Jan  7 16:37:54 hostname sshd[25151]: Failed password for illegal user irc from [IP_ADDRESS_C] port 56036 ssh2


The security gained from using the above information cannot be guaranteed. If you use the above information for any purpose, you do so at your own risk.
Copyright © 2001-2005 SOLOPORT CORPORATION. All rights reserved.


More Articles by

Click here to add your comments
- no registration needed!

Interesting article and a very workable concept.

It's a bit strange that this article appeared when it did, as it addresses something that I have been working on for a while. Over the last several weeks, a server belonging to a client has been getting hammered by someone attempting an ssh log-in with about every known name in the English dictionary, as well as the usual root, bin, etc.

My initial thought was to block his apparently static IP address. However, I figured this would not permanently solve the problem -- it isn't possible to add more and more IP addresses to a filter table indefinitely. In any case, I was somewhat annoyed with having to constantly flush all this failed log-in crap out of syslog -- along with having to explain to the client why his Internet bandwidth was being gobbled up by some socially-challenged, miscreant who obviously doesn't have a life.

So I decided to seek another solution. Without going into any details as to how it was accomplished, the would-be cracker was identified and, I was informed today, will be getting an unannounced visit from law enforcement in his locale.

If anyone who is reading this thinks they can attempt to penetrate a computer system without being caught, try not to get too smug. In the old days, it was hard to track someone down. Not any more! It really wasn't all that difficult to catch up with this clown.

BTW, in the USA this type of activity is a Federal offense. There's no such thing as parole in the Federal prison system, and one only gets a small sentence reduction for good behavior. At a minimum, 80 percent of the sentence will have to be served.

Judging by what I've seen on various TV programs, Uncle Sam's prisons are anything but the Ritz. The food doesn't appear to be very appetizing, there's no unlimited Internet access, and some of the other inhabitants don't look too friendly. I sure wouldn't want to be a guest at one of these crossbar hotels.


---January 19, 2005

What about disabling password authenticated logons all together?

OpenSSH/SSH supports a veriaty of authentication methods and password authentication is the weakest one that you can use.

For example you can setup hostbased authencation method combined with passwords, or use a RSA private key, public key pair. You could set it up that a user can only use a private key to authenticate and combine that with a passphrase you basicly eliminate all possiblity of a successfull brute force attack against a SSH server. Plus it would aleviate the need to make users remember and occasionally change complex and hard to remember passwords. Then if a cracker gets ahold of some physical media or cracks a home computer and gets a key, they still would have to know the passphrase.

I know, of course, that this isn't practical for lots of situations, unfortunately.



---January 19, 2005

I have seen the same kinds of things in my logs, and I ended up blacklisting their IP's. Since blacklisting their IP's, I have not seen anymore attempts. I also only allow my username to login. I am also investigating using pam_tally to limit the number of failed login attempts before locking the account. Since my username has a password that is not in a dictinonary, and has been run through crack, and John the Ripper, without being guessed (yet), I feel that using pam_tally will keep the clown out. It may be a bit of a pain, since it is possible they could lock by username out, but first, they have to guess the correct username, since SSH only allows my username login access.

I do like the idea of opening, and closing the ssh port. That seems like an interesting solution. I may give it a whirl, and see how well it works.


---January 28, 2005

After seeing an extensive (and meaningless) ssh attack, I moved the ssh port to a "funny" port off in the nether regions of my TCP stack. Since doing this, all dictionary attacks and the like have ceased. No port knocking, etc. though nearly all accounts on the system have no shell (cannot login) and root doesn't accept logins except with RSA keys.

Tue Jul 19 06:04:10 2005: 809   anonymous

I've seen these attacks on most of my machines, from various IP addresses, some of which was internet cafe's. I've checked with the authoroties over here and whilst it is sometimes possible to track the orrigon of the attacks it's relatively hard to presecute such an attacker unless he actually managed to gain access _and_ you have some kind of pre-login banner that states the exact law the person will be breaking if he gains access, something like:

Unauthorized access of this system is in direct violation of the
Electronic Communication and Transaction Act 25 of 2002. All access
violations are logged and perpetrators will be prosecuted accordingly!

Wed Aug 10 00:27:05 2005: 951   anonymous

This worked well for me.


Wed Nov 2 03:20:04 2005: 1268   anonymous

as my hackers are using open proxies to get access to me;

here's an example site that lists them: (link)

I'm getting hacked at every night at the moment, all from anonynized ips.

I will probably install fail2ban & the pam module anyway, but will definitely add this filter to iptables and nat-map my hardware firewall to a high port.

many thanks for providing me with some peace of mind!

Thu Jul 6 00:37:44 2006: 2215   TonyLawrence

Dirk Hart sent along a pointer to this knockd daemon: (link)

Fri Feb 23 17:32:43 2007: 2876   anonymous

The following rule is very basic and efficient for me :





$IPTABLES -A INPUT --src \! -p tcp --syn --destination-port ssh -j SshLimit

$IPTABLES -A SshLimit -m hashlimit --hashlimit-mode srcip --hashlimit-name SshLoginAttack --hashlimit 1/minute --hashlimit-burst 4 -j ACCEPT

$IPTABLES -A SshLimit -j LOG --log-level DEBUG --log-prefix "SshLoginAttack: "


Sat Feb 23 16:29:59 2008: 3696   anonymous

This way of opening and closing the SSH port is easy to detect. Imagine a cracker who wants to get acsess to your computer. The first thing he would do is to scan all ports. This action opens the SSH port. When this fails he will continue to scan common ports. This is a common thing to do if you have a firewall that can detect scans. Then he finds the SSH port wide open.

Sat Feb 23 17:35:10 2008: 3697   TonyLawrence

Well, Jon described a simplistic use here, but usually port knocking requires a pattern: 1600 followed by 3200 followed by 1300, for example. A scan is unlikely to hit that.

Don't miss responses! Subscribe to Comments by RSS or by Email

Click here to add your comments

If you want a picture to show with your comment, go get a Gravatar
Kerio Connect Mailserver

Kerio Samepage

Kerio Control Firewall

Have you tried Searching this site?

Unix/Linux/Mac OS X support by phone, email or on-site: Support Rates

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.

Contact us

Jump to Comments

Many of the products and books I review are things I purchased for my own use. Some were given to me specifically for the purpose of reviewing them. I resell or can earn commissions from the sale of some of these items. Links within these pages may be affiliate links that pay me for referring you to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain. I also may own stock in companies mentioned here. If you have any question, please do feel free to contact me.

I am a Kerio reseller. Articles here related to Kerio products reflect my honest opinion, but I do have an obvious interest in selling those products also.

Specific links that take you to pages that allow you to purchase the item I reviewed are very likely to pay me a commission. Many of the books I review were given to me by the publishers specifically for the purpose of writing a review. These gifts and referral fees do not affect my opinions; I often give bad reviews anyway.

We use Google third-party advertising companies to serve ads when you visit our website. These companies may use information (not including your name, address, email address, or telephone number) about your visits to this and other websites in order to provide advertisements about goods and services of interest to you. If you would like more information about this practice and to know your choices about not having this information used by these companies, click here.

This post tagged: