Copyright (c) 2004, Judd Vinet [email protected]
This is a port-knocking server/client. Port-knocking is a method where a server can sniff one of its interfaces for a special "knock" sequence of port-hits. When detected, it will run a specified event bound to that port knock sequence. These port-hits need not be on open ports, since we use libpcap to sniff the raw interface traffic.
To build knockd, make sure you have libpcap and the autoconf tools installed. Then run the following:
$ autoreconf -fi
$ ./configure --prefix=/usr/local
$ make
$ sudo make install
The example below could be used to run a strict (DENY policy) firewall that can only be accessed after a successful knock sequence.
- Client sends four TCP SYN packets to Server, at the following ports: 38281, 29374, 4921, 54918
- Server detects this and runs an iptables command to open port 22 to Client.
- Client connects to Server via SSH and does whatever it needs to do.
- Client sends four more TCP SYN packets to Server: 37281, 8529, 40127, 10100
- Server detects this and runs another iptables command to close port 22 to Client.
Traditional knock approach does not protect the system from MITM attack. If the attacker sniffs the traffic and sends the same packet sequence to knockd, he gains access to the system. To avoid this we can change the port sequence after predefined number of seconds, pretty much like Google Authentcator does. However, even in this case, there is a chance, that the attacker will send the same knocks sequence soon after the valid user sent it and thus will gain access to the system. To completely avoid this MITM threat we have to make a random port sequence dependent not only on time of the packets sent, but also on source ip address of the sender. The example below shows the section of knockd config file, that provides exactly this scenario:
otp = AAgR%XXx30O$#, 45, 20000, on, tcp, udp, tcp
in this section
- AAgR%XXx30O$# is a seed which is used to generate one time port numbers sequence
- 45 is otp_change_time. The time in secs of how often we change our dynamic port numbers
- 20000 is a ports range starting point (unsigned short). This is a starting point of 256 numbers area, used for random port numbers generation. Usually is bigger then 1000. Each port number is generated by an algorythm in the range of 0-255 and then added to this number. So, in this examples a random port numbers within a range of 20000-20255 will be generated each time.
- on is ip_protection flag (boolean on/off). It specifies if we need additional ports generated based on mix of the key and the sender ip address to validate sender. Only in rear cases where the sender can't know for sure it's public IP address or if internet provider has several public IP addresses which are used on round-robin basis for providing internet access to its customers, this flag should be set to off. In these rear cases only time-based port generation might be used, which is less secure, but better than nothing.
- tcp, udp, tcp - protocol sequence. These are the protocols used for every generated port sequence. The number of protocol names defines the number of port numbers derived from the seed. If ip_protection flag is set to on, additional random port numbers are generated based on src ip of a sender. The number and types of these additional ports are the same as the primary ones. In this examples 3 additional port numbers will be generated resulting in total 6 port numbers seqence of these protocols: tcp, udp, tcp, tcp, udp, tcp
A simple bash script knockd.sh is included as a knocking client to illustrate the whole processs To build knockd openssl should be installed. Usually "-lssl -lm" linker options is enough to build knockd
The accompanying knock client is very basic. If you want to do more advanced knocks (eg, setting specific tcp flags) then you should take look at hping, sendip or packit.
Here are some other implementations of port-knocking: