Securing your SSH Server

One of the most common questions that I see in my favorite IRC channel is: “How can I secure sshd on my server?” There’s no single right answer, but most systems administrators combine multiple techniques to provide as much security as possible with the least inconvenience to the end user.

Here are my favorite techniques listed from most effective to least effective:

SSH key pairs

By disabling password-based authentication and requiring ssh key pairs, you reduce the chances of compromise via a brute force attack. This can also help you protect against weak account passwords since a valid private key is required to gain access to the server. However, a weak account password is still a big problem if you allow your users to use sudo.

If you’re new to using ssh keys, there are many great guides that can walk you through the process.


Limiting the source IP addresses that can access your server on port 22 is simple and effective. However, if you travel on vacation often or your home IP address changes frequently, this may not be a convenient way to limit access. Acquiring a server with trusted access through your firewall would make this method easier to use, but you’d need to consider the security of that server as well.

The iptables rules would look something like this:

iptables -A INPUT -j ACCEPT -p tcp --dport 22 -s
iptables -A INPUT -j ACCEPT -p tcp --dport 22 -s
iptables -A INPUT -j DROP -p tcp --dport 22

Use a non-standard port

I’m not a big fan of security through obscurity and it doesn’t work well for ssh. If someone is simply scanning a subnet to find ssh daemons, you might not be seen the first time. However, if someone is targeting you specifically, changing the ssh port doesn’t help at all. They’ll find your ssh banner quickly and begin their attack.

If you prefer this method, simply adjust the Port configuration parameter in your sshd_config file.

Limit users and groups

If you have only certain users and groups who need ssh access to your server, setting user or group limits can help increase security. Consider a server which needs ssh access for developers and a manager. Adding this to to your sshd_config would allow only those users and groups to access your ssh daemon:

AllowGroups developers
AllowUsers jsmith pjohnson asamuels

Keep in mind that any users or groups not included in the sshd_config won’t be able to access your ssh server.

TCP wrappers

While TCP wrappers are tried and true, I consider them to be a bit old-fashioned. I’ve found that many new systems administrators may not think of TCP wrappers when they diagnose server issues and this could possibly cause delays when adjustments need to be made later.

If you’re ready to use TCP wrappers to limit ssh connections, check out Red Hat’s extensive documentation.

fail2ban and denyhosts

For those systems administrators who want to take a bit more active stance on blocking brute force attacks, there’s always fail2ban or denyhosts. Both fail2ban and denyhosts monitor your authentication logs for repeated failures, but denyhosts can only work with your ssh daemon. You can use fail2ban with other applications like web servers and FTP servers.

The only downside of using these applications is that if a valid user accidentally tries to authenticate unsuccessfully multiple times, they may be locked out for a period of time. This could be a big problem if you’re in the middle of a server emergency.

A quick search on Google will give you instructions on fail2ban configuration as well as denyhosts configuration.

Port knocking

Although port knocking is another tried and true method to prevent unauthorized access, it can be annoying to use unless you have users who are willing to jump through additional hoops. Port knocking involves a “knock” on an arbitrary port that then allows the ssh daemon to be exposed to the user who sent the original knock.

Linux Journal has a great article explaining how port knocking works and it provides some sample configurations as well.


The best way to secure your ssh daemon is to apply more than one of these methods to your servers. Weighing security versus convenience of access isn’t an easy task and it will be different for every environment. Regardless of the method or methods you choose, ensure that the rest of your team is comfortable with the changes and capable of adapting to them efficiently.


  1. As I have dynamic IPs (very common here), I cannot use iptables to allow connections only from specified IPs…
    However, I have always used this set of iptables rules:

    iptables -A INPUT -p tcp -m tcp –dport 22 -m state –state NEW -m recent –set –name DEFAULT –rsource
    iptables -A INPUT -p tcp -m tcp –dport 22 -m state –state NEW -m recent –update –seconds 300 –hitcount 4 –name DEFAULT –rsource -j DROP
    iptables -A INPUT -i eth0 -p tcp -m tcp –dport 22 -j ACCEPT

    It seems to be working really well!
    Basically, everyone is allowed to connect to SSH, but, if you make more than 5 connections (or connection attempts) in 5 minutes (300 seconds), you are banned automatically for a while.

    I found this to be very effective with bots: when the system bans them, they simply desist, and do not try again later.

    Of course I am using key pairs and not passwords, but this helps as well.

    • What you can do is set up a small 256 mb cloud server as a proxy. The only allow ssh access to your main server where your important files are held from that small cloud server.The trade off is obviously keeping two servers up-to-date and the very minuscule cost of a 256 mb server.

    • One of the first questions I ask clients is “where is your client base and work force connect from”. In most cases the information returned indicates that there is no legitimate reason for someone outside of your ICANN region to access your server. If your in the United States or Canada this is good news for you and bad news for your attackers.

      By simply blocking non-local ICANN regions, easily done through your iptables, you will block a large portion of your attacks. This combined with greylisting for mail and a brute force limiter, like fail2ban or denyhosts, will remove the largest portion of your attacks.

      I also have a general comment about the brute force limiters. First off Rackspace cloud comes with console access to your servers and if you are in a server emergency and are locked out from remote access that is only via your ip address. Fail2ban and denyhosts do not natively block users. So you can always reach your serve through your console and if you need to you can also create a remote access server with the sole purpose of proxy access to your server when your ip has been blocked. This server can be setup in fail2ban and denyhosts to never block.

  2. Another thing we do is not allow ssh to the root account. If you scan your logs you will see many bots are trying to get root access only. The default is to allow root. In /etc/ssh/sshd_config uncomment and set “PermitRootLogin” to no, then recycle your sshd daemon. Now your hacker has to guess a valid login name too (eliminate the common ones in /etc/passwd,) that password and su the root password.

    We also wrote our own fail2ban php script. We monitor the logs for suspicious login’s and block them after x attempts. In addition to a blacklist we have a whitelist so we don’t lock ourselves out when we mistype/forget passwords.

    slick iptable configuration Alessandro!

  3. Don’t allow password access of any kind.

    The first key to securing ssh is to not allow password access at all! The key vulnerability is password access. Just don’t allow it. Require a key. If you need to log in without a key, do it through the console.

  4. I always switch my sshd to a non-standard port, not for any sort of security (through obscurity) but just to reduce the noise in my auth.log – makes tracing a real problem much easier when you don’t need to wade through MBs of script kiddies.

  5. Good article, Major. I am always shocked when people allow root (thanks for the tip in the comments, Mike) or any privileged groups to log in remotely, rather than requiring su or sudo usage to jump privileges. I also like the use of denyhosts to automatically lock out people trying to brute force accounts.

    One thing you don’t mention is that changing the listening port significantly cuts down on the number of random and sporadic attacks. It makes focused attacks stand out much more clearly in your logs and is a great cost/benefit for small operations. Add denyhosts for more protection. It’s not security through obscurity, it’s using obscurity to enhance your overall security program – vastly different things.

    I’m also a bit on the fence with keys versus passwords. If you’re like me you’ve got about a dozen workstations you may be logging in from and don’t always have a key handy. I find that a strong password along with other precautions makes this a risk I will accept.

  6. Use strong passwords. Not always applicable, but where it is, I think it’s sufficient. Weak passwords are ultimately the vulnerability that these bots seek, and they cease to be a problem when you use good, lengthy, strong passwords that could not be persistently bruted nor dictionary attacked. The problem with key-only logins is that the vulnerability then moves to the keys, and the responsibility becomes the user’s to *guard* that key, and to under no circumstances lose it or have it compromised.


  7. Yes, +1 on disabling remote root, that’s one of the most important hardening tips.

    I’ve stopped using denyhosts, there is just too much potential for DOS, and depending on your denyhosts settings your hosts.deny file can swell up very large. A better and similar solution is to rate-limit SSH connections using iptables, this will very effectively thwart brute force attacks.

    If using password authentication at all, strong passwords are the key. I agree that key-based authentication is better, but also presents a separate set of challenges around keeping your secret key secret.

    I have also had good success around using a nonstandard port for SSH — this will help avoid 99% of casual script-kiddie attacks.

    Lastly, in a cloud situation, you don’t have to have SSH listening on the public interface at all on most of your machines: you can have one server with publicly available SSH, then just use your cloud LAN to access the other machines in your network from that machine. It creates an extra step to connect, but allowing no public access at all to SSH is the ultimate in SSH security. If you want to be totally obsessive about it, you can pop a tiny server that is a dedicated SSH server that has NO user data on it at all, then lock down SSH on all your other boxen to only allow SSH connections from that one SSH gateway box.

  8. Let’s also not forget that there is really no reason to have SSH v1 protocols enabled.

    First thing I do when I set up a new Cloud Server is do an apt-get update/upgrade and edit the /etc/ssh/ssh_config file to disable v1 by uncommenting the protocol line and removing the ,1

    # Protocol 2,1


    Protocol 2

    That knocks out a lot of them…

Comments are closed.