Why putting SSH on another port than 22 is bad idea

Warning: This blogpost has been posted over two years ago. That is a long time in development-world! The story here may not be relevant, complete or secure. Code might not be complete or obsoleted, and even my current vision might have (completely) changed on the subject. So please do read further, but use it with caution.
Posted on 12 Mar 2012
Tagged with: [ ssh

Hi there! This is probably one of the most visited pages of my blog, most likely because this post is very controversial. It's also an old post, and got much feedback on the post (both negative and positive, both constructive and not-so-much). I've decided to rewrite some of the post but left most of the arguments in tact. However, please note that on some of these arguments i've been convinced by others that they are not good arguments, and on some I am still not. Please read with care, but don't consider it as an absolute truth.
The basic argument I've tried to make: don't do security-through-obscurity. You may use it, but don't solely use it. Use other - better - defences to increase your security (like pubkey authentication for instance).

I see a lot of companies and users moving their SSH port to a non-privileged port like 2222 or even 36797. People like to move this port away in order to lower the number of attacks on the SSH port.

Now, at first glance, this seems a valid reason: if you don’t know which port to attack, you can’t attack it at all :-). But if you re-read that last line, you will notice this is nothing more than security through obscurity.

But there are more reasons why this is a bad idea and one of the most important reason has to do with a bit of the (Linux) way of handling TCP/IP ports. When you are logged onto a system as a non-root user (anyone not being uid 0), you cannot create a listing TCP or UDP port below 1024. This is because port numbers below 1024 are so-called privileged ports and can only be opened by root or processes that are running as root. So for instance, when your webserver (apache, nginx etc) will start, it will do so as the privileged root user in order to open up a listening connection to port 80 (the port that by default will be used for HTTP traffic). Now, as soon as the port is opened and everything that needs to be done as root is done, the webserver will fall back to a non-privileged user (either the www-data, apache, or nobody user). From that point, when something bad is happening, it is only limited to the rights that that user has. Now, back to SSH: when we start SSH on port 22, we know for a fact that this is done by root or a root-process since no other user could possibly open that port. But what happens when we move SSH to port 2222? This port can be opened without a privileged account, which means I can write a simple script that listens to port 2222 and mimics SSH in order to capture your passwords. And this can easily be done with simple tools commonly available on every linux system/server. So running SSH on a non-privileged port makes it potentially LESS secure, not MORE. You have no way of knowing if you are talking to the real SSH server or not. This reason, and this reason alone makes it that you should NEVER EVER use a non-privileged port for running your SSH server.

On to the next reason not to change ports: A lot of applications actually EXPECT ssh traffic on port 22. Even though you can easily change the port in many applications but not all of them do. Trust me, it WILL be annoying for developers, sysadmins and users to operate on your SSH-port 52241, especially since they are using 20 boxes, each with a different SSH port.

Another issue: many corporations have incoming and outgoing firewalls, meaning you cannot go to any site to any random port and expect it to work. Some secure ports, like port 22 are often exempt from that, while other ports like port 25 or 110 are blocked.

Now, let’s pretend you STILL want to move the port away because you get so many attacks on your SSH port. First of all: are you able to logon as root? If so, fix that now. Secondly: are you using passwords? If so, fix that now and change into public key authentication. But think about it: is it a problem to have so many people banging at the front of your house? They are just there testing your defenses! :-) I’d rather have an angry mob outside my house knowing it would mean I would do everything to make sure they can’t break into my house, than to have an open door, that I do not know about, until some lonely passant just drops in to say hi (and trash the place, or worse).

But if you are REALLY worried about that angry mob, there are better ways to hide the door than to move it. Try port-knocking. Again, security through obscurity, but if you must, this is probably the only viable way to do it. There are several ways to implement port-knocking. There are 3rd party tools, which are A) way to big and complex and B) are implemented in userland so don’t use them. Instead, you can do this with simply using iptables, which has got a very nifty module called “recent”, which allows you to create simple - yet effective - port knocking sequences.

Take a look at the following example:

${IPTABLES} -A INPUT -p tcp --dport 3456 -m recent --set --name portknock
${IPTABLES} -A INPUT -p tcp --syn --dport 22 -m recent --rcheck --seconds 60 --name portknock -j ACCEPT
${IPTABLES} -A INPUT -p tcp --syn --dport 22 -j DENY

What this does, is that as soon as something tries to connect to port 3456 (yes, a non-privileged port, but no problem as nothing is running on it), it will set a flag called “portknock”. Now, when we try to setup a connection to the SSH port, it will check to see if your IP has set a “portknock” flag during the last 60 seconds. If not, it will not accept the connection. And the third line will by default deny any access to SSH together as a failsafe. (I’ve heard before that it would be hard for users to remember that they need to connect to another port first, but somebody who cannot click a link, type a url, or telnet to a port, should he or she really have SSH access to begin with???).

Now, don’t directly copy/paste this into your firewall, but you can see how easy it is to “hide” your ports. You can even create a whole serie of knock sequences if you like but this will only annoy your users and gains you nothing.

Again, this does not change ANYTHING on the fact that it should not matter if your port is out in the open or not. Don’t fall for security through obscurity, because that will probably be the easiest way to get your box hacked. And please, as a hosting company, a system administrator or even a developer, don’t ever tell others that moving your SSH port away is a good thing. Because it’s not, and it never will be.