Running any kind of server at all is a risk, because the internet is a bad place full of bad people who like to destroy things for fun (and if you don’t believe me, read this). It becomes a matter of risk management—you have to expose certain things, like TCP ports 80 and maybe 443, for your web server to be reachable; you also probably need to expose at least one management port somewhere so that your server can be poked and prodded should things go wrong with it.
This usually means exposing port 22 for ssh if you’re on some kind of Unix-ish operating system like we are here at the Bigdinosaur.org compound. Blindly exposing your ssh port is not without peril, but there are several things you can do to manage the risk—namely, moving the ssh daemon onto a different port; controlling which local accounts are allowed to log on via ssh; and most importantly, installing and configuring something like DenyHosts, a TCP wrapper designed to help keep undesirables from being allowed to log on at all.
Changing sshd’s port
Changing the ssh port is the easiest thing you can do, though its efficacy is arguable. On one hand, this will avoid your being noticed by potential attackers randomly wardialing port 22 on a huge range of IP addresses; on the other hand, the ssh service fingerpring will be blindingly obvious to even a casual port scan, no matter where you’re running it. Still, it’s easy to implement and it certainly doesn’t make anything less secure.
There are two ways to change the port on which sshd is advertised to the world. If you’re behind a stateful firewall with NAT, by far the simplest is to use a DNAT rule to forward an arbitrary high port on your public address to port 22 on your web server. Exactly how to do this varies depending on what firewall you’re using, but if you know what “DNAT” is then you likely already know how to set up the rule.
The other way is to actually change the ssh daemon’s listening port, which on Ubuntu or any other Debian-based distro (and on most GNU/Linux distros in general) can be done by editing /etc/ssh/sshd_config
. Locate the following section in that file:
Change 22
to a high number—I’d suggest something higher than 30000 but below the maximum 65535. Restart ssh when you’re done.
Changing ssh’s AllowUsers
The GNU/Linux ssh daemon can be told to only allow certain accounts to authenticate via ssh, and unlike the maybe-effective-but-maybe-not first step above, this step is something everyone should be doing. The most obvious thing to do here is make sure root isn’t allowed to log on remotely, but it’s not a bad idea to ensure that only accounts that need to allow remote logon are allowed to do so.
Again, open /etc/ssh/sshd_config
for editing and search for AllowUsers
. If there is no AllowUsers
directive in the file, head to the bottom and add it yourself:
In the above example, only the accounts john
, mary
, and fred
can log on via ssh; logon attempts by the user bill
would be rejected.
Installing and configuring DenyHosts
However, it’s never wise to expose ssh to the Internet without breaking out the big guns, and that means something like DenyHosts. DenyHosts is a handy application which not only stops repeated bad logons to your server, but which also communicates with a central database to block known malcontents from logging onto your server before they even try.
DenyHosts is available from the Ubuntu or Debian repositories with a quick sudo aptitude install denyhosts
, but the version available in the repositories as of this blog post is out of date and is missing a critical bugfix. To install the latest version, run these two commands:
This will take care of installing DenyHosts and setting it up to run at startup. DenyHosts keeps track of bad ssh logon attempts, blocks IP addresses with too many bad attempts, and can optionally be configured to both download lists of known-naughty IP addresses from the DenyHosts central database and also to upload IP addresses which have tried and failed to log onto your server to the central database (so others can download them and automatically block them). All of DenyHosts’s configuration is kept in /etc/denyhosts.conf
, so that’s what we need to edit. Here are the DenyHosts settings I’ve modified away from default, along with why:
Leave all other settings to default, then restart the service with sudo /etc/init.d/denyhosts restart
. DenyHosts keys off of entries in your system’s main auth.log
file, and so keeping an eye on that file will reveal what DenyHosts is doing. Here’s a snippet from the Bigdino web server:
You can see a mix of outright denials and also a couple of root attempts (after which the host is added to the block list). The authentication log should be audited once a day or so in order to keep an eye on system-wide activity, so reviewing this should be something you’re doing regularly.
If a host is ever added to the block list by mistake, it’s a snap to remove it—the actual block list file is /etc/hosts.deny
and can be edited as needed. You can also manually add hosts you want to block in to the same file.
Installing DenyHosts is only one large number of things you can do to help secure your web server, and every little bit helps. It’s not necessary to create a completely air-tight and secure server because down that road lies madness, as you chase down every single tiny possible vulnerability. Rather, you only need to make your web server more secure than others. Remember the adage about the dragon and the hobbit: if you ever find yourself being pursued by a hungry dragon while in the company of a hobbit, remember that you don’t have to outrun the dragon—you just have to outrun the hobbit.
Discussion topic for the original blog entry at: http://blog.bigdinosaur.org//securing-your-server-with-denyhosts