Open Sesamy: Port-knocking using just one port

Port knocking is a mechanism to provide additional security to firewalling. Port knocking is normally used in firewalls. A target port needed for a particular service (e.g. SecureShell, SSH) is normally closed and the service is unreachable. Only by ‘knocking’ on a number of ports in a particular order opens the target port. Knocking means: sending a TCP or UDP packet to the port. Though the knock ports are closed and won’t respond, the firewall notices the knocks. To the outside world the firewall appears totally closed. Portscans fail. Only when the proper sequence of ports is knocked the target port opens and the service is reachable for a few seconds. During this time-span the service can be reached.

There are a large number of port knock implementation. See for an overview: portknocking.orgOpen Sesamy differs from other mechanism because only one port for knocking is needed. It may even be the target port. It is implemented using Linux iptables. This is another difference: most port knocking algorithms are implemented as scripts scrutenising the log files. Using iptables the packet filtering is exploited as present in the Linux kernel or modules.

Why I created Open Sesamy

At home I have an internet server with a great number of goodies. When I am at work I occasionally need a few of the goodies. However, at work I am stuck with a company firewall that only allow TCP connections to
port 80 (HTTP) and 443 (HTTPS). On port 80 I run a webserver. On port 443 I run a SecureShell (SSH) server, which I like to protect by means of port knocking. Because no other connection are allowed to other ports, I cannot use regular port knocking. So I created Open Sesamy. I can use port 443 for knocking and for SSH!

How it works

In Open Sesamy 4 sequences of knocks are sent to the knock port at regular time intervals (e.g. 4 seconds). When correct sequences are received, the secured port opens for the period equal to one time interval. During this period, connection can be made to the opened secure port. Only the machine that performed the knocks can connect. A knock may be a TCP SYN packet or an UDP packet.

Implementation

Next piece of code implements the necessary iptables code. Open Sesamy has been implemented as function portKnockListener(). The download section contains an example implementing a simple firewall only allowing access to a SSH server after port knocking (1-2-3-4 knocks).

#************************************************************************#
#
# FUNCTION: portKnockListener
# Open Sesamy Port knock listener. This listener listens to sequences
# of knocks, separated by time intervals.
# This function takes an input chain like INPUT as input parameter
#
#************************************************************************#

portKnockListener()
{
  KNOCKPORT=22
  SECUREPORT=22
  KNOCKWINDOW=3
  SEQUENCE1=1
  SEQUENCE2=2
  SEQUENCE3=3
  SEQUENCE4=4


  TAG=${1}

  SEQSUM=$[SEQUENCE1+SEQUENCE2+SEQUENCE3+SEQUENCE4]

  $IPTABLES -N CHECKKNOCKS_$TAG
  $IPTABLES -N RESETKNOCKS_$TAG

########################################################################
# Packets for the SECUREPORT: check it! 
  $IPTABLES -A ${1} -p tcp    --dport $SECUREPORT -j CHECKKNOCKS_$TAG
  
########################################################################
# Some residu clean up. If to may hits are counted, reset                          

# If more packets are received 
  $IPTABLES -A ${1} -m recent --rcheck \
                              --hitcount $[SEQSUM+1] \
                              --seconds $[KNOCKWINDOW*4]\
                              --name knocks_$TAG \
                           -j RESETKNOCKS_$TAG
  $IPTABLES -A ${1} -m recent --rcheck \
                              --hitcount $[2*SEQSUM+1] \
                              --name knocks_$TAG \
                           -j RESETKNOCKS_$TAG

########################################################################
# Packets for the KNOCKPORT: increase counter. This may be UDP or TCP                               
  $IPTABLES -A ${1} -p udp    --dport $KNOCKPORT \
                    -m recent --set \
                              --name knocks_$TAG \
                    -j DROP
  $IPTABLES -A ${1} -p tcp    --syn --dport $KNOCKPORT \
                    -m    recent --set \
                              --name knocks_$TAG \
                    -j DROP
  
  
########################################################################
# Reset chain: remove all knocks  
  $IPTABLES -A RESETKNOCKS_$TAG -m recent --remove \
                                          --name knocks_$TAG \
                           -j DROP
  
  
########################################################################

# Check sum of all sequences. If not equal, do not reset, because since SECUREPORT may be 
# equal to KNOCKPORT. Hence this chain may be traversed when knocking. It should not
# be reset in the middle of a knock sequence.  
  $IPTABLES -A CHECKKNOCKS_$TAG -m recent !  --rcheck \
                                             --seconds $[KNOCKWINDOW*4] \
                                             --hitcount  $SEQSUM \
                                             --name knocks_$TAG \
                                -j RETURN
                           
  
# Fourth knock sequence
# Check count < hits   
  $IPTABLES -A CHECKKNOCKS_$TAG -p tcp --dport $SECUREPORT \
                                -m recent ! --rcheck \
                                            --seconds $KNOCKWINDOW \
                                            --hitcount $SEQUENCE4 \
                                            --name knocks_$TAG \
                                -j RESETKNOCKS_$TAG # Check count >= hits+1
  $IPTABLES -A CHECKKNOCKS_$TAG -p tcp --dport $SECUREPORT \
                                -m recent   --rcheck \
                                            --seconds $KNOCKWINDOW \
                                            --hitcount $[SEQUENCE4+1] \
                                            --name knocks_$TAG \
                                -j RESETKNOCKS_$TAG
                           
                           

# Fourth+Third knock sequence
  $IPTABLES -A CHECKKNOCKS_$TAG -p tcp --dport $SECUREPORT \
                                -m recent ! --rcheck \
                                            --seconds $[2*KNOCKWINDOW] \
                                            --hitcount $[SEQUENCE4+SEQUENCE3] \
                                            --name knocks_$TAG \
                           -j RESETKNOCKS_$TAG 
  $IPTABLES -A CHECKKNOCKS_$TAG -p tcp --dport $SECUREPORT \
                                -m recent   --rcheck \
                                           --seconds $[2*KNOCKWINDOW] \
                                            --hitcount $[SEQUENCE4+SEQUENCE3+1] \
                                            --name knocks_$TAG \
                                -j RESETKNOCKS_$TAG
                           
                            
# Third+second knock sequences  
  $IPTABLES -A CHECKKNOCKS_$TAG -p tcp --dport $SECUREPORT \
                                -m recent ! --rcheck \
                                           --seconds $[3*KNOCKWINDOW] \
                                            --hitcount $[SEQUENCE4+SEQUENCE3+SEQUENCE2] \
                                            --name knocks_$TAG \
                           -j RESETKNOCKS_$TAG
  $IPTABLES -A CHECKKNOCKS_$TAG -p tcp --dport $SECUREPORT \
                                -m recent   --rcheck \
                                            --seconds $[3*KNOCKWINDOW] \
                                            --hitcount $[SEQUENCE4+SEQUENCE3+SEQUENCE2+1] \
                                            --name knocks_$TAG \
                           -j RESETKNOCKS_$TAG

# OK! We've received the knocks! Clear up the mess
  $IPTABLES -A CHECKKNOCKS_$TAG -m recent   --remove \
                                            --name knocks_$TAG \
                                -j ACCEPT


                               
  echo "#############################################################"
  echo "                 OPEN SESAMY INSTALLED                       "
  echo "#############################################################"

}

The function is called in a firewall script (e.g. rc.firewall) using an input chain as input:

portKnockListener INPUT

The function can be added to more than one input chain.

The function uses the ipchain matching (-m) criterion ‘recent’. This criterion checks whether current host has been noticed before. The matching is narrowed down by using the –hitcount and –seconds extensions, to implement the sequences and time window behaviour. Refer to the iptables man pages under linux for a good explanation of these matching criteria. Note: ipchains behaves somewhat weird. When a knock port is forwarded using prerouting the original port should be defined as the KNOCKPORT and not the forwarded one (as I would have expected).

For example, when I preroute port 443 to port 22 like

# drop all traffic to port 22 on external interface
# redirect port 443 on external interface to port 22
$IPTABLES -A PREROUTING -t nat -i $INTERNETIF -p tcp --dport 22\
-j DROP
$IPTABLES -A PREROUTING -t nat -i $INTERNETIF -p tcp --dport 443\
-j DNAT --to $INTERIP:22

it is necessary to set KNOCKPORT to 443 and SECUREPORT to 22

The Port-knock tools

Open Sesamy: Windows, TCP Syn based

Open Sesamy tool offers a Windows based tool that sends TCP SYN packets. For this, it needs WinPcap needs to be installed. WinPcap is used to send raw TCP packets without using the Windows TCP/IP stack (when using the stack, the stack would wait for the TCP connection to set up; this is not what we want; we just want to spit out a few TCP SYN packets). Refer to the download section for the tool.

OpenSesamy

Following fields can be filled:

Ip Address
The address or name of the host to be knocked
Port
The knock port (KNOCKPORT in the script)
Sequence
Sequence of knocks as a string of 4 digits. Each digit (value 1-9) represents a number of knocks.
Window
Timing window in milliseconds. 4000 represents a 4 second window
Devices
The network interfaces available on this PC are listed here. You should select the network interface that should be used to send the knocks to.
Mac
The MAC address of the interface selected is filled in here. Under WinNT this does not work. Unfortunatelly you have to fill in the MAC by hand than.
Knock
Start knocking
Info
Print available network interface info
About
Version information
Exit
Does what the button says…

When a file knocksettings.txt is present, these settings are read from this file.
Note: storing these settings in a file means compromising security, since these settings should be kept secret!

Following settings should be defined in the file, each on a new line:

  • server
  • port
  • sequence
  • window
  • interface index (0, 1, etc)
  • mac address

An example

192.16.1.1
22
1234
3000
1
00:0E:35:0E:77:B0

PortKnocker: Windows/Linux, UDP based, commandline tool

A commandline tool called PortKnocker is available as well. This tool sends UDP packets. Since UDP is a connection-less protocol, it is possible to use standard sockets to spit out UDP packets. So we use the Windows/Linux kernel. No need for WinPcap. The commandline version may come in handy, because it may be used in a start-up script calling PortKnocker, sleeping a second and than call the e.g. the SSH client.

Usage 1:

PortKnocker server port sequence window
server
The address or name of the host to be knocked
port
The knock port (KNOCKPORT in the script)
sequence
Sequence of knocks as a string of 4 digits. Each digit (value 1-9) represents a
number of knocks.
window
Timing window in milliseconds. 4000 represents a 4 second window

Usage 2:

PortKnocker

A file called knocksettings.txt is expected to be present defining the settings.Note: storing these settings in a file means compromising security, since these settings should be kept secret!. The file should contain the settings described above, each setting on a new line.

An example

192.168.1.1
22
1234
3000

Note: the same file may be used that is used for the OpenSesamy tool.

Usage 3:

PortKnocker fileName
filename
Name of the settings file

Basically, this is the same as option 2. However, now the filename can be specified.

Downloads

Note: Open Sesamy is quite outdated and probably needs upgrading….