portknocking -- adding an extra layer of security to your openSSH installation
First of all, what is portknocking? Portknocking is a technique to externally open ports on the firewall after the external host has sent network traffic predefined by the system administrator. For instance the external host could try to connect (i.e. "knock") to a predefined sequence of closed ports. After connection attempts to all ports in the right order, the protected port is opened. Note that the host carrying out the sequence does not get any response from the firewall what the current state is or if the protected port is now open.
There are very sophisticated portknocking implementations around, which feature protection by cryptographic techniques. Here, however, we restrict ourselves to a simple approach using just connection attempts to a predefined sequence of ports. The very simple implementation presented here relies on the recent extension of the IPtables firewall implementation. These building blocks are available on virtually any Linux installation. Moreover, the knocking sequence can be generated using programs that are present on almost all client systems. Even web browsers are suitable as the only requirement is that the program can open a TCP connection.
Obviously, while the implementation presented here is very simple on the server and client side, it is susceptible to replay attacks. This means that an attacker that has the ability to eavesdrop the communication somewhere between the client and the server can open the protected port.
See this Wikipedia article for an overview over the different implementations.
MotivationTo gain access to my home network, I have a secure shell server running on standard port 22 of the dynamic IP address of my DSL internet connection. However, there are many (unsuccessful) attempts to log in as root via ssh. To get an impression, some unix magic is in place.
cl@raspberrypi ~ $ sudo zgrep ssh /var/log/auth.log.2 | perl -n -e'/.*Failed password for root from ([\.0-9]+) port/ && print "$1\n";' | sort | uniq -c | sort -n [...] 133 184.108.40.206 1359 220.127.116.11 2679 18.104.22.168 4410 22.214.171.124This lists the IPs of the hosts from which the failed login attempts originated from.
To keep these scans from even reaching my ssh installation, I installed portknocking on my Raspberry Pi.
Importance of a time limit for the steps in the sequenceLet's consider the following very simple model of a portknocking implementation. For illustration, we restrict ourselves to a configuration with two ports to knock until the ssh port is open. So, after port p1 has been contacted, port p2 has to be knocked. Knocking port p2 before port p1 has been contacted has no effect. After knocking p2, the ssh port is open.
We introduce the symbols:
Implementation with time limitWe consider the same installation, but now with a timeout at each state transition. After transitioning to the next state, one has to proceed again before a timeout occurs. This makes it considerably more challenging for the attacker to succeed just by random, brute force scanning.
Of course, the implementation of portknocking must not result in a disregardful administration attitude. It is just an additional layer of security and software maintenance (i.e. deployment of security updates and reasonable configuration) has to continue.
An attacker "just" has to hit the sensitive ports in the right order within the time window. Any other ports touched in between are irrelevant. Therefore, do not make the time window too long; otherwise increases the likelihood that the SSH port is exposed to the attacker. 5 seconds should be OK.
A few remarks concerning port scanners: