Guide to Port Knocking
This guide will primarily focus on Debian-based distros, as it is what I am familiar with.
A crib sheet to port knocking
Firstly, an introduction to port knocking. Port knocking is based on the concept of sending a certain sequence of TCP/UDP knocks. This works by having a daemon (the knockd daemon) listening for a series of knocks at a low level – this ensures that no open ports are needed.
After receiving the correct sequence of knocks, the knockd daemon will then run a program. It is usually used to dynamically instruct the firewall (iptables) to open/close the desired port (such as an SSH port).
So in essence, it is a little like Ali-Baba and the forty thieves – you have to execute a certain sequence of knocks before the door (the firewalled port) will open to reveal the riches (the SSH server, for example).
Server End
For Debian-based distros, it is very simple to install the knockd daemon – simple run:
sudo aptitude -y install knockd
Next, edit its configuration file, located in /etc/knockd.conf. Two examples are shown here: the first has two separate sequence of knocks to open and close the firewalled port respectively. The second has a single sequence to open the port, after which it will close the port automatically after a set period.
1st Example:
[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
A quick explanation of the options above: logfile is fairly obvious – it logs all knock attempts. openSSH and closeSSH are the names given to the knock sequences. sequence is the sequence in which the knocks are to be made. If no protocol is specified, then TCP is automatically assumed. You can, however, specify UDP or TCP as you wish. For example, for a port 7000/UDP, 8000/TCP, 9000/TCP sequence, the sequence line would look like:
sequence = 7000:udp,8000:tcp,9000:tcp
The command line is the command to be executed. I prefer using the iptables command, although you could also, for example, instruct the knockd daemon to sing a song by running mplayer. But the idea of doing so just scares me, because of the potential havoc that this can wreak. Note that %IP% is the knocker’s IP address, so the firewall restricts the SSH connection to that IP only.
2nd Example:
[opencloseSSH]
sequence = 7000,8000,9000
seq_timeout = 5
tcpflags = syn
start_command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
cmd_timeout = 10
stop_command = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
This particular example merges the previous example’s [openSSH] and [closeSSH] stanzas. In effect, it will open the SSH port on the fireall for 10 seconds (the cmd_timeout line) upon receiving the knock sequence, before closing it. This is more useful because it saves people the hassle of having to close the port after opening it.
However, you will have to insert one additional line into your permanent iptables configuration file (not the knockd file!). This is because when the firewall closes the port, any existing SSH sessions would be terminated as well. So to prevent that, any established connections previously made will still be allowed.
iptables -I INPUT -p TCP -s 0/0 --dport ssh -m state --state ESTABLISHED -j ACCEPT
You’re done! To add the knockd daemon to startup (otherwise you will be locking yourself out), run
sudo update-rc.d knockd defaults
This should add it to all default runlevels.
Client end
On the client end, you can use virtually any client to execute the knock sequence – telnet, netcat (nc) or even ssh. However, because there is a timeout (5 seconds in the configuration files above) between knocks, it would be wise to use the knock client, unless you really fancy having 3 terminal windows open, or having fast fingers to hit Ctrl+C and type in the new port number in 5 seconds. So to install the knock client, again run
sudo aptitude -y install knockd
Then, run
knock <hostname> <port1> <port2> <port3>
to open up the firewalled port and connect to it.
Considerations
Port knocking merely adds on another layer of security – it prevents the need for open ports – but it does not protect against weak passwords, or security holes. It should not be taken as a be-all and end-all for security. Security through obscurity has never been part of my belief system, but port knocking fits well into the general environment because it minimizes the target. It should not, however, be the only component in a well-designed secured environment.
That said, however, it is useful because a cracker wanting to open up a single port would have to try every single combination of 3 port knocks. Then he’d have to port scan the firewall for the open port. Mathematically speaking, that means 65535^4 packets to detect an open port. If you increase the number of ports in the sequence, that makes things even harder.
The port numbers provided above should be changed, as the sequence 7000, 8000 and 9000 are the default. You can try using more or less port numbers, and mixing TCP and UDP knocks together. One cardinal rule is to never use ports in sequence – for example 6001, 6002 and 6003. Some script kiddie running a port scan could get lucky. You’ll never know. So, its a good idea to mix the port numbers, for example, 5003, 1025 and 65522.
You should also take advantage of port knocking to close all ports on the firewall (flush all the external rules and set a default policy of DROP), and let knockd handle everything.
