
about
firewall primer details knock lab download implementations documentation FAQ images resources contact ![]() ![]()
The port knocking Perl prototype is licensed under the GPL license.
GPL License
![]() |
Details of Port Knocking MechanismPerl prototype: v0.30
2004-Nov-14 18:59 | ...more new Net::Pcap support added to sniff packets directly ...more
Once you've perused the firewall primer, learn about the details of port knocking here. Ideas about how to use port knocking in simple situations are presented, as well as an outline of how to use encryption to avoid eavesdropping.
Knock LengthFor encrypted knocks with key "password" and Blowfish cipher. no IV
with IVIV = 36574210
knock lengthThe number of ports in the port knock will depend on
When other parameters are held constant, the increasing the amount of information increases the knock length. Encrypting the knock also increases the knock length, particularly when an initialization vector (IV) is used. The only way to shorten the knock is to increase the number of ports used to encode the knock. The fundamentals of constructing the knock are described in the application section. Here, I illustrate how increasing the number of encoding ports affects the knock. port spanLet's use the following knock format knock = CLIENT,PORT,FLAG0,CHECKSUM where CLIENT=10.3.2.1, PORT=3306, FLAG0=5. The CHECKSUM, which is automatically generated, has a value of 11 for these data. The CLIENT is an IP address which is stored as 4 integers in the range 0-255 (char). The PORT is an integer in the range 0-65,535 and is stored as 2 chars. Both FLAG0 and CHECKSUM are stored as chars. Thus, the knock data is made up of 8 chars. knock = 10 3 2 1 12 234 5 11 Once encrypted (see the application section for details), the knock grows to 16 chars, knock = 108 185 168 63 196 17 74 93 117 149 61 122 9 212 227 212 Since the values are already chars, encoding them into a range of 256 ports (port span) is simple. If the range is given by { p(i), i=0..255 }, then the encoded knock is knock = p(108) p(185) p(168) ... p(212) where p(i) is some function that computes the ith port in the port span. The encoded knock will contain the same number of elements, 16, as the original knock before encoding. The encoding in this case is nothing more than a simple mapping. However, if the number of ports in the port span is not 256, then a little more work has to be done to perform the encoding. The reward is, however, a shorter knock if the port span has more than 256 ports. For the method outlined below, the port span must contain 2^N ports. Practically, the largest span size is 2^15 = 32,768, since you cannot allocate all your ports for port knocking if you are going to bind some of them to applications. encoding knocks in a large spanLet's take a port span with 2^10=1,024 ports. p(i) = 1000+i, i=0..1024 First, the data in the knock (108, 185, 168, ..., 212) is expressed in binary representation. Note that each value is zero-padded to 8 bits. knock = 01101100 10111001 10101000 00111111 11000100 00010001 01001010 01011101 01110101 10010101 00111101 01111010 00001001 11010100 11100011 11010100 Next, the elements of this representation are concatenated and split into N=10 bit binary numbers. knock = 0110110010 1110011010 1000001111 1111000100 0001000101 0010100101 1101011101 0110010101 0011110101 1110100000 1001110101 0011100011 11010100 Each binary value is converted back to decimal. We now have 13 integers, instead of 16. knock = 434 922 527 964 69 165 861 405 245 928 629 227 212 Finally, these values are mapped onto the port span knock = 434 1922 1527 1964 1069 1165 1861 1405 1245 1928 1629 1227 1212 The effect of allocating 1,024 ports as knock listeners was a 20% savings (3/16) in the length of the knock. The largest savings are realized when a 32,768 port span is used. Here is an example of a non-contiguous 2^15=32,768 span portspan = 1024-5000,6000-25000,26000-35789 The encoding into this larger span is done in the same manner, except that the concatenated binary representation is split into 15 bit elements. knock = 011011001011100 110101000001111 111100010000010 001010010100101 110101110101100 101010011110101 111010000010011 101010011100011 11010100 The split yields 9 values, which when converted to decimal give knock = 13916 27151 30850 5285 27564 21749 29715 21731 212 When these values are mapped onto the 32,768 port span, the port knock sequence is knock = 15939 30173 33872 7308 30586 23772 32737 23754 1236 The benefit of using a large port span is clear - a shorter port knock is generated. The tables in the side panel show the length of an encrypted port knock for a given number of data fields in the knock, length of span and initialization vector use. decoding from a large port spanDecoding a knock encoded in a large port span is a process which is nearly the reverse of the encoding procedure described above. There is one small difference, however. It has to do with how the padding of the last binary element is handled. Consider the process of decoding these knock values, from a knock encoded into a 2^14=16,386 port span. Using the knock data from the examples above, the encoded knock is knock = 6958 6787 16144 4426 5981 6483 13800 2516 14581 0 Representing these 10 values as 14-bit binaries, knock = 01101100101110 01101010000011 11111100010000 01000101001010 01011101011101 01100101010011 11010111101000 00100111010100 11100011110101 0 We are going to concatenate these numbers and split them into 8-bit binary numbers. This step requires that the total number of digits is a multiple of 8. However, we have 9*14+1 = 127 numbers. To make a multiple of 8, we need to zero-pad the last value to a length of 2. knock = 01101100101110 01101010000011 11111100010000 01000101001010 01011101011101 01100101010011 11010111101000 00100111010100 11100011110101 00 Now this can be split into 8-bit values knock = 01101100 10111001 10101000 00111111 11000100 00010001 01001010 01011101 01110101 10010101 00111101 01111010 00001001 11010100 11100011 11010100 And converted to binary, to get the original encrypted knock represented by chars. knock = 108 185 168 63 196 17 74 93 117 149 61 122 9 212 227 212 decoding in perlThe code in the knockdaemon to decode the incoming port knock is given below. The ports on which the client knocks are stored in @data and the $portmap HASHREF is used to map between the port and its ordinality in the port span. # cardinality of the sequence element in the port span my @d1 = map { $portmap->{$_} } @data; # binary representation my @d2 = map { dec2bin($_) } @d1; # compute length of padded binary representation, with last element unpadded my $padlength = $CONF{lognumports} * (@d2-1) + length($d2[-1]); my $padlength_fill = $padlength % 8; # pad binary represention of first N-1 elements in sequence to $CONF{lognumports} digits my @d3 = map { sprintf("%0$CONF{lognumports}s",$_) } @d2[0..@d2-2]; if($padlength_fill) { # pad last element to padlength_fill my $padlength_last = 8 - $padlength_fill + length($d2[-1]); push(@d3,sprintf("%0${padlength_last}s",$d2[-1])); } else { push(@d3,$d2[-1]); } my $binlength = length(join("",@d3)); # split binary representation into 8-bit fields my @d4 = join("",@d3) =~ /(.{1,8})/g; # convert to decimal my @d5 = map { bin2dec($_) } @d4; return @d5; last updated 2010-Oct-17 10:16
|