I had implemented port knocking before with linux daemons and knocking clients but this requires installing software that is always running and consuming memory and processor resources. If you are using a Virtual Private Server –as I am–, you can’t afford to waste a single megabyte of memory. Therefore, you begin looking for creative alternatives that minimize the load on the server.
Some time ago, I found a curious implementation of port knocking using iptables. So, if you already have iptables installed on your (virtual) machine, you can get rid of an always-running daemon.
You can find the original script here, or get the more complete script I’ve made.
#!/bin/bash
## Port Knocking server configuration. It closes all ports but the webserver one.# When the correct sequence of ports is detected (1000. 2000. 3000. 4000), the# SSH port is opened for 5 seconds to allow connections.#
# Erase all the rulesiptables -F
# Close all incoming connectionsiptables -P INPUT DROPiptables -P OUTPUT ACCEPTiptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTiptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Open the web server port to the publiciptables -A INPUT -m state --state NEW -p TCP --dport 80 -j ACCEPT
# Allow the loopback interface (mysql, ...)iptables -A INPUT -i lo -j ACCEPT
# Port Knocking################ Original Script http://pub.ligatura.org/fs/netfilter/misc/portknock_multi## Netfilter/IPtables - example of multiple-port knocking# Note: Knock ports to open SSH port for 5 seconds.
iptables -N INTO-PHASE2iptables -A INTO-PHASE2 -m recent --name PHASE1 --removeiptables -A INTO-PHASE2 -m recent --name PHASE2 --setiptables -A INTO-PHASE2 -j LOG --log-prefix "INTO PHASE2: "
iptables -N INTO-PHASE3iptables -A INTO-PHASE3 -m recent --name PHASE2 --removeiptables -A INTO-PHASE3 -m recent --name PHASE3 --setiptables -A INTO-PHASE3 -j LOG --log-prefix "INTO PHASE3: "
iptables -N INTO-PHASE4iptables -A INTO-PHASE4 -m recent --name PHASE3 --removeiptables -A INTO-PHASE4 -m recent --name PHASE4 --setiptables -A INTO-PHASE4 -j LOG --log-prefix "INTO PHASE4: "
iptables -A INPUT -m recent --update --name PHASE1
iptables -A INPUT -p tcp --dport 1000 -m recent --set --name PHASE1iptables -A INPUT -p tcp --dport 2000 -m recent --rcheck --name PHASE1 -j INTO-PHASE2iptables -A INPUT -p tcp --dport 3000 -m recent --rcheck --name PHASE2 -j INTO-PHASE3iptables -A INPUT -p tcp --dport 4000 -m recent --rcheck --name PHASE3 -j INTO-PHASE4
iptables -A INPUT -p tcp --dport 22 -m recent --rcheck --seconds 5 --name PHASE4 -j ACCEPTOn the client side, I use a small bash function that performs the knocks and connects to the SSH server. The only requirement it needs is the netcat utility.
#!/bin/bash
# SSH Connection Port Knocker## 1 - Append this code to your .bashrc or .bash_profile file# 2 - Create a .portknocks file in your home directory with a list like# host1 port1# host1 port2# ...# host1 portN# host2 port1# ...# 3 - You must open a new terminal session to use the new function# 4 - Use it as you would use the ssh command# ssh user@server => pssh user@server## It accepts the usual options of the SSH program
pssh() {
while getopts "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:W:XYy" FLAG dotruedone
HOST=${@:$OPTIND:1} HOST=${HOST#*@} CNT=1
cat ~/.portknocks | grep ^$HOST | awk '{ for(i=2; i <= NF; i++) printf "%s\n", $i}' | \ while read PORT doecho "Knocking $HOST ($CNT)" nc -w 1 $HOST $PORT & sleep 0.5 && ((CNT++)) done
ssh $*}Enjoy it!

Pingback: Using SCP Port Knocking Remote Hosts | blog.franciscodavid.eu