
|
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
![]() |
DocumentationPerl prototype: v0.30
2004-Nov-14 18:59 | ...more new Net::Pcap support added to sniff packets directly ...more
The manpages for the Perl implementation of port knocking are available here.
NAMEknockdaemon - a port knocking server responsible for monitoring and responding to incoming knocks generated by knockclient
SYNOPSIS
# use a given configuration file (default knockdaemon.conf) > knockdaemon -conf mydaemonknock.conf
# produce diagnostic messages > knockdaemon -debug
# silent operation > knockdaemon -quiet
# do everything, but do not respond to knocks in any way > knockdaemon -test
# brief usage > knockdaemon -h
# full man page > knockdaemon -man
DESCRIPTIONThis is a prototype port knocking server. It is not designed for a production environment but as a sandbox for playing with the port knocking method. The daemon has two modes of operation. The mode determines how the daemon detects knocks. At all times, the server maintains a port queue for each remote IP address and attempts to interpret (decode, decrypt) the port numbers into as information. Upon successful receipt of a knock, the server carries out actions, defined in an external configuration file. The server may respond immediately, or delay its response.
File ModeThe daemon monitors the firewall log file for signs of knocks.
runmode = file
Network ModeThe daemon uses pcaplib to monitor the network interface directly. When this mode is activated, the daemon does not use a firewall log file. This means that you do not need to log connections to the ports in the knock span.
runmode = network
OPTIONS
Configuration FileThe server will try to read configuration files from these locations: ~/.knockdaemon.conf, BIN/knockdaemon.conf, BIN/etc/knockdaemon.conf, BIN/../etc/knockdaemon.conf, where BIN is the directory in which this script resides. The server reads only the first configuration file that it finds. The configuration file is in an Apache-like format, as understood by the Config::General module. You must have this module installed. Refer to the configuration file to learn about the supported parameters.
File Mode OperationThe server continually monitors the local firewall log file using File::Tail. Specify the log file using
logfile = /var/log/firewall fileinterval = 0.5 Each new line in the log file is parsed for certain key fields which are used by the server. The maximum amount of time in seconds between checking the file is specified by fileinterval. For example, the server needs to know what the port is that is being knocked on. Specify the format of the log file using
uselogformat = FORMAT and define the format in a <logformat> block.
<logformat FORMAT> required = REGEXP interface = REGEXP protocol = REGEXP ipserver = REGEXP ipclient = REGEXP port = REGEXP </logformat> The block contains a list of named regular expressions which are applied to each line. If you specify a regular expression with a 'required' field, then this regex must match the line before the line is processed. If the required regex does not match, the line will not be processed by the server. The 'required' field can be useful in reducing the parsing effort expended by the server when combined with --log-prefix option in IPTABLES (see RECIPES). For all other regexps, if matched, their first capture field is associated with the regexp name. Thus, you may have
port = DPT=([0-9]+) and this would match the line
... DPT=883 ... and assign 883 to the key 'port'. You can define multiple log formats - use separate blocks - and then only adjust the 'uselogformat' parameter. For example,
<logformat iptables> ... </logformat>
<logformat ipchains> ... </logformat>
<logformat mydebugformat> ... </logformat>
#uselogformat = iptables #uselogformat = ipchains uselogformat = mydebugformat Consider using the network mode, described below. The file mode is less secure because the knocks may be reconstructed by a third party from the firewall log file.
Network Mode OperationWhen operating in network mode, the daemon listens to the network interface specified by
interface = lo Packets are captured using Net::Pcap up to
snapshotsize = 1500 bytes each. Each packet is tested using a specific filter set by
useethfilter = tcplo which is subsequently defined in a <ethfilter> block. For example,
<ethfilter tcplo> proto = IP_PROTO_TCP flags = SYN dest_ip = 127.0.0.1 </ethfilter> This filter will accept only TCP packets with their SYN flag set destined to 127.0.0.1 (the loopback address). You can have as many filters defined as you wish, and select the one to use with ``useethfilter''. Refer to man page of the NetPacket modules for a full list of packet properties you can use in the filter. In general, a property is desribed either by a binary value (e.g. flags) or by a string (e.g. dest_ip). These two types are tested by ANDing the value of a symbol (e.g. flags & SYN) or testing with a regular expression (e.g. dest_ip =~ /xxx.xxx.xxx.xxx/), respectively. The network mode is preferable to file mode, since the knocks are not stored in any file.
Knock FormatYou must teach the server what to expect in a knock. The knock format is specified in the identical way as in the client's configuration file. Namely,
knock = FIELD1,FIELD2,FIELD3,... where the fields are the same as in for the client. See knockclient for details.
ResponsesThe job of the server is to respond to incoming knocks. After a knock has been detected, and successfully interpreted (decoded and possibly decrypted), the server may carry out some combination of (a) immediate response or (b) delayed response. Responses are defined in the <actions> block in the configuration file. There are two types of subblocks: <action> defines the condition which needs to be satisfied before the action is carried out. The <action> block also defines a possible delay and the name of the action itself. The name of the action is associated with a system call in a <template> block. For example, if you wanted the server to execute ``/bin/myprog'' when it received a knock on port 22.
<actions>
<action> condition = PORT == 22 template = exec_myprog use = yes </action>
<template exec_myprog> system = "/bin/myprog" </template>
</actions> All action blocks are parsed and blocks with satisfied conditions are evaluated. This means you can have multiple responses the to same knock. In the example below /bin/myprog is executed immediately, and then again after 5 minutes. Scheduling is done using Schedule::At.
<actions>
<action> condition = PORT == 22 template = exec_myprog use = yes </action>
<action> condition = PORT == 22 template = exec_myprog delay = 5 # minutes use = yes </action>
<template exec_myprog> system = "/bin/myprog" </template>
</actions> To pass values from the data in the knock to the system call, use the field names as appear in the knock format.
<template exec_myprog> system = "/bin/myprog FLAG0 FLAG1" </template>
<template iptables_open> system = "/sbin/iptables -D INPUT -p tcp -s IP/32 -d 0/0 --dport PORT --syn -j ACCEPT" </template> The value for IP and PORT will be substituted into the command before its execution.
Maintaining StateIt's possible to maintain state between knock receipts using a state template. The variable that holds the state can be optionally stored to a local cache file, to make the state persistent across instances of the knockdaemon. The state variable is a hash which is keyed by any combination of knock parameters, such as IP, PORT, FLAG0, etc. Parameters such as TIME, THISYEAR, THISDAY, THISMONTH, etc, are also supported. The state variable is modified by a template defined as
<template NAME> state = OP(state(KEY1,KEY2,...)) </template>
where
<template incr_num_visits> state = state(IP,visits,num)++ </template> will increase the value of the state variable keyed by the IP, ``visits'' and ``num''. Fields like IP will be interpolated to their current value (in this case, the client's IP parsed from the knock). The value assigned to the ``state'' parameter in the template must be formatted in such a way that after it is parsed, as described below, it can be passed to ``eval''. The string
state(KEY1,KEY2,KEY3,...)++ is first parsed by replacing all keywords like IP, TIME, etc with their values. For example
state(IP,visits,num)++ -> state(10.1.1.1,visits,num)++ Next, the string is adjusted so that it looks like a hash reference,
state(10.1.1.1,visits,num)++ -> $STATE->{10.1.1.1}{visits}{num}++
This expression is passed to eval. The state is modified immediately. Any value of 'delay' defined in the action template does not affect how state is altered.
State Recipes
Port MappingThe server will monitor only those ports which are within the knocking port span.
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.
EncryptionIt is strongly suggested that you encrypt the knock. An encrypted knock will help to protect you from replay attacks, especially if you embed the client IP address in the knock and use one time knocks (see above). To process an encrypted knock,
encrypt = yes key = my_secret_phrase cipher = Blowfish | IDEA | DES | ... You'll need to install the Crypt::XXX module to use cipher = XXX. If the incoming knock has an initialization vector (IV), use
iv = yes These settings must be matched by those in the client's configuration file.
RECIPES
Reducing log file parsing effortIPTABLES support a --log-prefix option which is used to prepend a given string to each log file line triggered by a certain rule. To avoid the daemon's parsing of all log file lines, and limit it to look only at the lines associated with your knock ports (e.g. PORTm-PORTn). First, set the prefix to some unique string for the range of ports you will be using.
iptables -A INPUT -p tcp --dport PORTm:PORTn -j LOG --log-prefix "portknock" Now add the appropriate 'required' regular expression to the logformat block in knockdaemon.conf.
<logformat FORMAT> required = portknock ... </logformat> If your knock ports are not continuous (see knockdaemon.conf) such as
portspan = 600-699,800-898,900,968-1023 you will need to patch iptables to support the -mport directive. The current release of IPTABLES (1.2.9 02-nov-2003) only supports --dport which requires that the port range be continuous. To perform the patch, install the patch-o-matic base package (www.netfilter.org) and answer ``yes'' to include the ``mport'' patch (not to be confused with the ``multiport'' patch). Once you've patched IPTABLES the command for including a prefix to non-contiguous ports is
iptables -A INPUT -p tcp -mport --ports 600:699,800:898,900,968:1023 -j LOG --log-prefix "portknock" This recipe was suggested by Sean (siegex@identityflux.com)
Reducing time between opening and closing a portSean (siegex@identityflux.com) suggested this method for ensuring that a port can be closed shortly after it is opened. With this rule, the time between opening and closing the desired port can be very small, say 30sec to a 1min, just enough time for the person to connect. Because a state has been established once connected, removing the rule that opened up the port will have no effect on the newly established connection, or any established connection for that matter.
iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
Keeping your knocks shortBy allocating 32,768 ports in the port span, your knocks will be as short as possible. The client maps a sequence of integers in the range 0-255 onto a sequence of ports. The larger the number of ports, the shorter the mapped sequence. If you use a 32,768 port span, such as
portspan = 1024-5000,6000-25000,26000-35789 then a 16 port knock with a 256 port span will be 9 ports long. The total length of the port span must be a power of 2 and cannot exceed 32,768.
AUTHORSMartin Krzywinski (martink@bcgsc.ca), Chris Rigby (kai@chaos.gen.nz), Thom Harrison (thom@cox.net), Stephan Muller (smuller@chronox.de)
SEE ALSOknockclient, www.portknocking.org
HISTORY
COPYRIGHT(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 last updated 2003-Jul-26 00:27
|




