TCP Knocking

Ganhawk's Project Page (for other projects)

Introduction                                 Description                                Download                                   Installation and Usage

This is a system I implemented just for fun some time ago. Although the code is functional and provides a mechanism similar to port knocking, I did not implement the second phase and hence it is weaker than I want it to be. I may implement the missing pieces if there is interest.
   - Ganesh <>


Often a secure system needs a port open so that only authorized persons can access a particular service and also the service should not exposed to attackers and worms that may use vulnerabilities that exist in the listening server. Port knocking is designed to be used as a complementary service to the existing authentication mechanism. But one of the biggest problems with port knocking is manipulating the firewall with timeouts. When the correct knock sequence is sent, the firewall is modified for couple of seconds. Having the firewall open automatically for a time period will make any system administrator uncomfortable. TCP knocking attempts to solve the problem by incorporating the knock into the TCP handshake. Tcp knocking is similar to port knocking, but instead sending UDP packets with secret ports, the TCP handshake packets must include secrete codes. It is at least as secure as port knocking and it can be made secure with more hardening.

Modified TCP handshake:

In normal TCP handshake, the client sends the syn packet and chooses a random initial sequence number. The server responds with a packet that has both syn and ack flags set, choosing a random
The modified TCP handshake uses the empty fields in the header. The server does not respond to connection requests without a special code generated along with the syn packet.  The server also encrypts the ISN in the ack packet (2) and the final packet of the three-way handshake must have the correct acknowledgment for the servers ISN. The system is further protected from brute-force attacks by closing the connection if the first attempt for the third packet does not have the expected acknowledgment sequence.  Also, rather than use conventional encryption techniques like HMAC for verification, this system uses a file with random numbers  as the key. This is because of the limited unused space available in the TCP/IP header which makes HMAC very weak. By using a shared file, the length of the key can be much greater than traditional systems and even though some parts of the key can be revealed by attacks, the server can protect itself from replay attacks.

The handshake:

1) Syn

The syn packet does not use the 32 bit acknowledgment field in the TCP header as it the the first packet to initiate the connection.  Further the 16 bit IPID can be used to transmit information. In the current implementation only the 32 bit acknowledgment field is used. Currently the 32 bit ack is derived from a 64 KB file which contains random numbers. The ISN and the source IP address along with the random numbers are used to generate this value.

2) Syn/Ack
The ISN is encrypted using the random numbers from the 64 KB file using the destination IP address as well as a 16 bit random number used as IPID. I do not have code for this part yet.

3) Ack
The client decrypts the syn number from the encrypted syn, the key file, the 16 bit IPID and its own IP address and sends the ack packet. The server closes all connections from the client for couple of minutes if it sends a wrong ack value.  Part of the security relies on the fact that the ISN generated by Linux 2.6 is fairly random.


I have implemented only the first part, which is the server expecting secret code along with the first syn packet from the client. Hence it is very possible to brute-force the server. Also the system is designed with the second phase in mind, which is the encrypted Initial Sequence Number in the ack packet and closing the connection if the correct ack is not sent on the first try. I do not have an implementation for that yet. The security will be increased greatly when the second phase is incorporated. Also the ability to detect brute-force attacks can be added to this system.

But the current system can be used for protecting the server from worms and random scanning. The use-case is similar to port knocking but it does not use the ugly system of opening the firewall for a couple of seconds. Vanilla port knocking is susceptible to brute-force attacks as well. Besides, inserting a kernel module to just ssh into your server will increase your mad sysadmin points :)



   /kernel - Files for the client and server kernel modules. Edit the Makefile and point it to the source directory of the running kernel and type make. This has to be done on both server and client if they are running different versions of the kernel.
   /iptables - This contains the extension module for iptables. Again edit the makefile and point it to the iptables source and do 'make'
   /support - Type make for the key_gen. The keygen will generate the key file that has to be copied to both the client and the server. A sample firewall script is provided for the server.

    On the server:
            insmod tcpknock-server.ko
        It looks for the key file in /etc/port_protector.dat. Optionally you can point the key file using
           insmod tcpknock-server.ko file_name="full/path/to/keyfile"

2)     Configure the iptables firewall as follows:
        The firewall must allow only established connections and reject all other packets.
        Before the other rules pass the syn packet through tcpknock module. See for example in the support directory.

    On the client:
       insmod tcpknock-client.ko
       The following parameters can be specified
             nat_ip="ip address"
             target_port="port number"
       The nat_ip is used to specify the IP address from which the server will be receiving the packet from (the source IP in the packet)
       The target port is the port for which the modification will be applied. I did not want to filter by IP address as I have more than 1 server to SSH into. The default port is 22. In the future the client will also be made as a netfilter module with separate extension for iptables. Once that is in place, this option will be removed.