There are many things to make your computer more secure and sometimes something as simple as port knocking can do the trick.

Port knocking as technique is used for a long time now and many implementations are already out there although for my specific use none of them seemed to be appropriate.

For complete listing of these implementations please visit portknocking.org website. There you can also find a complete explanation of the methods as well as recommendations of use.

Requirements (or why no other port knocking solution worked for me):

Knocking and service must share the same port (for example – let’s suppose you have a computer behind some router or firewall and have no access to this device; all you do have is one forwarded port to your computer – let’s say for ssh as most commonly used for system administration). I guess you can see now where the problem is with other implementations of port knocking: lack of ports that can be used for knocking.

Also, as I prefer a portable solution that is deployable anywhere (without any additional software clients) I want to make it possible so that it can be used with simple tools available on any system.

I’m trying to make this as simple as possible so all I’ll use is iptables. Why? Imagine a following scenario: something gets broken on a port knocking script/program/server and it’s not listening to knocks anymore. There comes a need for a visit to the computer to fix this directly as our ssh connection don’t let us do it remotely anymore. If iptables gets broken there is no firewall anyway so you’ll have a completely different set of problems, at least connecting to fix it wouldn’t be one of them.

One thing that is needed beside plain iptables is their recent module – either compiled in or as separate module. Few words about recent module parameters used here:

–name [name] defines a name of the list

–set puts the source IP matched in a list defined by –name (if name is not defined all matches go in some default list)

–rcheck does a rulecheck on a IPs from list

–seconds [seconds] is used to filter out the list for IPs seen within the indicated number of seconds

–hitcount [hits] filters out the list for minimum number of packets from some IP, can be combined with seconds to make the filtering more accurate

OK, so we’ll start with a standard firewall passing new ssh connections (I’ll use the iptables-save format as it’s easier to tweak the firewall and set comments though you can make this also with usual iptables commands) – port 22 is passed thru without any additional checks:

# pass established connections

-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

# pass new ssh connection

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j ACCEPT

For starters we’ll need to start listening on this port:

# pass established connections

-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

# listen to new connections on ssh port

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -m recent –set –name sshknock -j LOG “knock knock: ”

# pass new ssh connection

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j ACCEPT

Now, after initiating a ssh connection we have a entry in /proc/net/ip_recent/sshknock list showing us the address and main parameters of the packet. As connection was initiated one rule later and all later packets were are picked up by ESTABLISHED state rule that’s all we’re going to get for now.

So let’s start filling in this list with new packets by dropping them instead of accepting and also enabling the port knocking mechanism:

# pass established connections

-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

# if at least 2 new packets inside 5 seconds open ssh port

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -m –rcheck –name sshknock –hitcount 2 –seconds 5 -j ACCEPT

# listen to new connections on ssh port

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -m recent –set –name sshknock -j LOG “knock knock: ”

# pass new ssh connection

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j DROP

We might stop at this as we have achieved our goal – 2 packet knock in a short amount of time is needed to open the port which will go under a radar for most port sniffers marking it as filtered port (of course, tweaking with more knocks and probably larger timespan is recommended to be more sure).

But, as we have a very well known port here which is targeted quite often let’s add an additional twist to this. By simply bombing the ssh port it will open without any defense at all.

# pass established connections

-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

# if more then 2 new packets inside 3 seconds arrive drop

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -m –rcheck –name sshknock –hitcount 2 –seconds 3 -j ACCEPT

# if at least 2 new packets inside 5 seconds open ssh port

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -m –rcheck –name sshknock –hitcount 2 –seconds 5 -j ACCEPT

# listen to new connections on ssh port

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -m recent –set –name sshknock -j LOG “knock knock: ”

# pass new ssh connection

-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j DROP

Another line to firewall is added – but what does it actually do?

If someone attempts to flood the port with packets it will refuse to open; and instead of only having number and time of knocks defined also rate at which these knocks must be employed is set – sending them at too high or too low frequency has no effect on opening the port – exactly 2 knocks is needed for 3rd packet to get to ssh server inside 3 – 5 seconds of the first knock.

So there it is, port knocking with only a few additional rules to iptables. Knocking packets can be generated with a simple telnet or ssh client. It most certainly isn’t the complete solution for the security and maybe isn’t as secure as some other port knocking solutions (additional encryption of the knocks, more complicated schemes of knocking) but it’s easily deployable and rises the security of the system significantly.