knockclient - a port knocking client responsible for sending knocks to
remote firewall where a knockdaemon is listening
# read everything from the configuration file
> knockclient -conf knockclient.conf
# overwrite some parameters
> knockclient -conf knockclient.conf [-remote x.x.x.x] [-client x.x.x.x] [-port n] ...
# produce diagnostic messages
> knockclient -debug
# silent operation
> knockclient -quiet
# do everything, but do not send knocks
> knockclient -test
# brief usage
> knockclient -h
# full man page
> knockclient -man
This is a prototype port knocking client. It is not designed for a
production environment (no formal testing of scalability or throughput has
been done) but as a sandbox for playing with port knocking.
The client accepts input from a configuration file and/or from command-line
parameters, which override any values in the configuration file. The client
encodes the information, as formatted by the -knock option, possibly
encrypts it, as directed by (-cipher -encrypt -key -iv), and maps it onto a
supplied port span (-portspan). The knock is sent either over the network
to -remote or written to a local log file specified by (-logfile -logtofile
The client will try to read configuration files from these locations:
~/.knockclient.conf, BIN/knockclient.conf, BIN/etc/knockclient.conf,
BIN/../etc/knockclient.conf, where BIN is the directory in which this
script resides. The client reads only the first configuration file that it
The configuration file is in an Apache-like format, as understood by the
Config::General module. You must have this module installed. Any parameter
in the configuration file may be specified on the command line. If the
configuration file contains
port = 22
then the same effect can be achieved using
knockclient ... -port 22 ...
For boolean flags like -test and -logtofile, to negate the argument use
-notest and -nologtofile. Any definitions in the configuration file are
overridden by command-line parameters. Thus, if you have port = 22 and test
= yes in the configuration file use -port 23 -notest to override this.
Refer to the configuration file knockclient.conf for more information.
The client can be set to deliver the knocks to a remote host over the
network, or alternatively write to a local (faked) firewall log file. The
latter option facilitates debugging, since it allows you to run the
knockserver and knockclient on the same machine without having to configure
- sending knocks over network
To have the knocks sent over the network, specify the remote IP
remote = x.x.x.x
logtofile = no
You probably want to pause some reasonable amount between knocking on
successive ports in a knock, to allow for network latency. Specify this, in
timeout = 0.5
- sending knocks to local file
To generate a faked local firewall log file, specify
logtofile = yes
logfile = /tmp/portknock.log
The format of the file is defined by the 'fileformat' parameter. For
example, if you want to generate an iptables-style log file,
fileformat = _DATE_ IN=eth0 SRC=_CLIENT_ DST=_REMOTE_ PROT=TCP SPT=_CLIENTPORT_ DPT=_REMOTEPORT_ SYN
You do not need to create a complete line, only one with the sufficient
number of parameters required by knockdaemon.Fields formatted like _FIELD_
will be replaced with actual run-time values. The following fields can be
parsed: DATE, CLIENT, REMOTE, CLIENTPORT and REMOTEPORT.
The knockdaemon must be configured to understand whatever log file format
you wish to use.
- test mode
To force the client to go through the motions of preparing a knock, but not
actually carrying out the final step to send the knock over the network or
write it to a file, use -test on the command line or add
test = yes
to the configuration file.
- quiet mode
To supress output while the script is running, use -quiet or
quiet = yes
To include diagnostic output while the script is runing use -debug or debug
To force a dump of internal parameters at the start of the script, use the
knockclient ... -debug -debug
The knock encodes information such as the client IP, port and anything else
that you would like to communicate to the knockdaemon. If you want the
knockdaemon to adjust firewall rules, then probably one of the fields in
the knock will be a port number.
The knock format is specified using
knock = FIELD1,FIELD2,FIELD3,...
where FIELDn is any of IP, PORT, FLAGm, RAND, THISYEAR, THISDAY, THISHOUR,
THISMINUTE, THISSECOND, CHECKSUM. The port is expected to be in the range
0-65,535 and all other fields need to be in the range 0-255 (if their value
is greater, they are reported mod 256). The values for some fields, like
IP, PORT and FLAGm are specified by you. Other fields like RAND, THISYEAR,
THISDAY, THISHOUR, THISMINUTE, THISSECOND and CHECKSUM have their values
generated automatically. FLAGm can be any of FLAG0, FLAG1, ... and
corresponds to a generic field which you can stuff with a value 0-255. The
parameters are described in detail below.
The knock is just a container for information. It is up to the knockdaemon
to interpret the information and act accordingly. Here are some example
client = 10.1.1.1
port = 22
knock = CLIENT,PORT # 10 1 1 1 22
flag0 = 15
knock = CLIENT,PORT,FLAG0 # 10 1 1 1 22 15
knock = CLIENT,PORT,FLAG0,CHECKSUM # 10 1 1 1 22 15 50
flag1 = 100
knock = CLIENT,FLAG0,PORT,FLAG1 # 10 1 1 1 15 22 100
knock = CHECKSUM,FLAG1,FLAG0,CLIENT # 128 100 15 10 1 1 1
The knock is used to generate a list of values which are subsequently
encrypted and encoded.
If you want the knockdaemon to alter firewall rules, or to use the client's
IP, then you should always embed the IP in the knock. Do not use the source
IP as reported in the firewall log file - this can be easily spoofed. To
set the value of the IP, use
client = x.x.x.x
This field is a special case of FLAGm, named to remind you that it
corresponds to a port, rather than some arbitrary flag. Use this field if
you want the daemon to open/close/modify rules for a particular port.
port = n
Any value in the range 0-65,535 may be assigned to the port variable.
You can embed other values in the range 0-255 in the knock. Use FLAG0,
FLAG1, ... for these.
flag0 = 5
flag1 = 25
To embed a random number in the range 0-255, use this field in the KNOCK
format. Since the number is random, you don't know its value ahead of time
and therefore you don't specify the value it in the configuration file ;)
Today's year, mod 256.
Today's day of the year, mod 256.
Current hour in the month (24*day+hour), mod 256.
Current minute of the day (60*hour+minute), mod 256.
Seconds since epoch, mod 256.
Sum of all other fields, mod 256. You can embed multiple CHECKSUMs in the
knock, but they will evaluate to the same value since the sum is performed
over all non-CHECKSUM fields.
It is strongly suggested that you encrypt the knock. An encrypted knock
will protect you from replay attacks, especially if you embed the client IP
address in the knock.
To encrypt the knock set
encrypt = yes
key = my_secret_phrase
cipher = Blowfish | IDEA | DES | ...
You'll need to install the Crypt::XXX module to use cipher = XXX. If you
want to include an initialization vector (IV), use
iv = yes
The length of the knock is a function of (a) number of fields in the knock,
(b) whether encryption is turned on and (c) whether the initialization
vector is used. If you don't use encryption, then the length of the knock
is the same as the number of fields. For an encrypted knock, the length is
knock length = 16 * iv_yes + 8 * [ int ( knock_fields/8 ) + 1 ]
where iv_yes = 1 if IV is used, and 0 otherwise. For example
fields no IV IV
1- 7 8 24
8-15 16 32
16-23 24 40
... ... ...
The knock, encrypted or not, is mapped onto a span of ports. The span is
portspan = a-b,c,d-e,...
You will need to reserver 2*N ports for the span. Non-contiguous ranges are
supported. The encrypted knock sequence (you are encrypting the knock,
right?) is mapped onto span ports, therefore the larger the value of N the
fewer coding symbols.
The two examples below illustrate the process of mapping the knock onto
Suppose you set
knock = CLIENT,PORT,FLAG0,CHECKSUM
client = 126.96.36.199
port = 22
flag0 = 15
The the list of values used to generate the knock sequence would be
142 103 205 1 22 15 233
where the last value is a checksum (mod 255) of the first 6 values. An
encrypted knock (no IV) looks like this
221 169 50 219 86 117 62 187
This encrypted list is mapped onto ports as specified by 'portspan'. If you
portspan = 745-1000
then the knock port values become
966 914 795 964 831 862 807 932
These are the ports to which the client will attempt to connect.
As an example, consider this 32,768 port span
portspan = 1024-5000,6000-25000,26000-35789
Suppose you want to encode these values. This is the encrypted knock
represented by integers in the range 0-255.
216 58 209 32 67 110 108 193 168 89 231 114 112 202 231 129
First, the integers are expressed as binary and then padded to length 8 and
11011000 111010 11010001 100000 1000011 1101110 1101100 11000001 ...
The concatenated string is then split into groups of N digits
110110000011101 011010001001000 000100001101101 110011011001100 ...
As a last step, these values are converted back to their decimal
27677 13384 2157 26316 3394 26525 25825 19175 129
and mapped onto the port span (e.g. the 27,677th number in the span is
30699 15407 3181 29338 4418 29547 28847 21198 1153
Refer to IANA for port ranges and values
Martin Krzywinski (firstname.lastname@example.org),
Chris Rigby (email@example.com), Thom
- 5 July 2004
v0.24: Port range expanded to 0-65,535. mod 255 bug fixed (Thom Harrison,
firstname.lastname@example.org). Port span range extended
beyond 256 ports to 2^N, N < 16. Knocks are therefore shorter, since the
number of coding symbols is increased.
- 17 April 2004
v0.23.1: Timeout once again works when writing to a local file. I thought
this would make the behaviour more consistent.
- 11 April 2004
v0.22: Port span permits non-contiguous knock ports. IP is replaced by
``client'' in the configuration file to be more consistent with ``remote''.
There is now no delay between knocks when the knock is written to a file.
- 23 February 2004
v0.21: Minor adjustments.
- 20 February 2004
v0.20: Parameters now in external configuration files. Added support for
custom log file format and custom knock format.
- 25 February 2003
v0.10: Initial Perl prototype
(c) 2002-2004 Martin Krzywinski
All rights reserved. This port knocking implementation is free software;
you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation; either version
2 of the License, or (at your option) any later version.
Refer to COPYING in this distribution for the complete GPL license