doormand(8) Doorman & Knocker doormand(8) NAME doormand - The doorman daemon SYNOPSIS doormand [-h] [-v] [-D] [-f config-file] DESCRIPTION The doorman daemon "guards the door" of a host running TCP servers, admitting only recognized parties. (The current implementation of the doorman can only protect TCP services.) It allows a server which is not intended for general public access to run with most (or even all) of it's TCP ports closed to the outside world. A server may thus be made invisible to a cracker's portscans; attacks can be mounted on such a host only if it's existence is known by other means. Moreover, any vulnerability in a specific program is made much more difficult to exploit, as the the firewall simply drops packets from parties the doorman does not recognize. The doorman watches all packets arriving at a specified interface on a specified UDP port. When a valid packet from knock is detected (see 'conditions' below), doormand runs the first of two shell scripts, as configured in doormand.cf. It is the responsiblity of these scripts to manipulate the firewall rules to allow a TCP connection from the origi- nating IP address. There is one script to add rules, and one to delete rules. The first call to the 'add' script sets a broad firewall rule; open to one desti- nation port, but from any source port at the originating IP address. The second call to that script sets a narrow rule; open to only one one source port at the originating IP address. Between the knock and a connection on the requested port, the doorman will wait for a configurable number of seconds. If none is made within that time, the 'delete' script is run to re-close the firewall. If a connection is made, the source port of that connection is noted; the 'add' script is run to narrow the firewall hole, and then the 'delete' script is run to delete the first, broader, rule. The sequence of calls to the scripts, if all goes well, is this: a valid 'knock packet' received... *--> add broad rule wait... a TCP connection allowed by the broad rule is made... *--> add narrow rule (we now know the source port) *--> delete broad role (don't need it anymore) the client & server converse; eventually, the client goes away... *--> delete narrow rule No reply is made to a knock; success is apparent to the client only when it discovers that a connection to the requested service can be made. OPTIONS -h 'help'; print a message explaining the options and quit. -v 'version'; print the version number and quit. -D Run in "Debug" mode. Doormand will not daemonize, and remain attached to the console; file ownership and permission checks are skipped, and logging is done to stdout. -X Do a hex dump of all UDP packets received on the listening port, including the data-link header. Use of '-X' is not usually nec- essary; only used for debugging if the doorman ignores all knocks. See 'man 5 doormand.cf'. -f config-file Use the specified configuration file. The default configura- tion file is named "doormand.cf" in directory "/usr/local/etc/doormand", or the directory specified by the configure "--sysconfdir" option when building doormand and knock. CONDITIONS A knock packet contains 4 space-delimited ASCII strings: portnumber, groupname, a "random" decimal number called a "tag", and an MD5 hash formatted as a hexadecimal number of 32 characters. The knock client creates this hash from the the group's shared secret, salted with the first 3 fields. The doorman performs the same MD5 operation, and checks that the two hashes are identical. If they are, the knock client must know the secret, and is let in. Therefore, in order for a knock to succeed, the following conditions must be met: 1. the groupid must be in the doorman's 'guestlist' file 2. the secret must match that in the guestlist record for that group 3. the IP address of the client machine's interface must match one of the addresses in the guestlist record. 4. the service requested must be in the guestlist record 5. the tag must not be "stale"; that is, it must not have already been used on a successful knock. (The doorman keeps a hashed table of information about successful knocks.) SCRIPTS Ready-made scripts are supplied for Linux, FreeBSD, netBSD, and OpenBSD: ipchains_add & ipchains_delete ... Linux 2.2 'ipchains' iptables_add & iptables_delete ... Linux 2.4+ 'iptables' ipf_add & ipf_delete ... netBSD 'ipf' ipfw_add & ipfw_delete ... FreeBSD 'ipfw' pfctl_add & pfctl_delete ... OpenBSD 'pf' The 'firewall-add' and 'firewall-del' records in doormand.cf specify which set of these scripts will be executed. For other firewall types, scripts must be supplied by the administra- tor. Both 'add' and 'delete' scripts are invoked with this parameter list : $1 $2 $3 $4 $5 interface-name src-ip src-port dest-ip dest-port When adding or deleting "broad" rules, the value of $3, the src-port parameter, will be set to a single '0' character. Add & delete scripts may check for a zero value to determine the firewall command to be issued. Both scripts must return a status by writing a string to stdout. A nor- mal return is indicated by single ascii '0' (0x30) character. Errors encountered while running the script should be indicated by returning a non-zero integer (perhaps 'errno', but '-1' will do), fol- lowed by a numeric severity level: EMERG 0 ALERT 1 CRIT 2 ERROR 3 WARNING 4 NOTICE 5 INFO 6 DEBUG 7 Severity values of 0..3 will cause the forked doormand process for that connection to log the event and exit. Levels 4..7 will cause the event to be logged, but processing will continue. The message written to the logfile will also contain whatever text is written after the severity level; this may be extra information on the nature of the error, if so desired by the script writer. An example error return: -1 3 Permission denied SIGNALS SIGHUP may be used force the parent doormand process to re-read it's configuration and guest-list files. Any children preparing new, or monitoring established connections will continue to use old configura- tion data. SIGTERM, SIGSTOP, SIGQUIT, and SIGINT may be used to shut the doornman down in an orderly fashion. Any children processing connections will exit, after removing any firewall rules for which they are responsible. There may be a delay of up to "connection_delay_2" (man doormand.cf ) before children exit. FILES doormand.cf: the configuration file for doormand. (man 5 doormand.cf) guestlist: the list of guest (or group) names containing a secret for authentication, and information about which services they may connect to, and from what IP addresses. (man 5 guestlist) doormand.pid: the process-ID file created by the parent doormand pro- cess. The full pathname is specified by the 'pidfile' record of door- mand.cf. Doormand will refuse to run if this file already exists; it must be removed manually after a program crash. A hash archive: a file containing information on previous successful knocks. In the current implementation, this file should not be shared with other doorman processes. If the 'hash-archive-size' configuration parameter is changed to a smaller value, some stored knocks may be lost due to hash collisions upon insertion into the new table. The archive stores the 128-bit MD5 hash contained in the knock, and the time, as GMT, that the successful knock was received. The size of the archive should be made as large as possible without consuming an inconvenient amount of memory and disk space. This is to reduce the number of hash collisions; in the event of a collision where the two MD5 hashes match exactly, the doorman assumes a "replay" attack, logs a warning message, and refuses entry. However, in the event of a collision where the MD5 hashes do not match, the new knock simply over-writes the old. A firewall-add script. A firewall-delete script. CAVEAT Three vulnerabilites of this approach spring immediately to mind. The first is that the guest "secrets" must exist as plaintext in the guestlist file, and may also exist (plaintext again!) in the client's .knockcf or knock.cfg file. These secrets must therefore NEVER corre- spond to ANY passwords ANYWHERE ELSE. Note also that coredumps from doormand crashes will also contain all guest-list secrets in plaintext. Second, it is still possible for a cracker, connected to the same client machine as a legitimate user (L.U.), and able to sniff L.U.'s traffic, to 'slip in' before L.U. (This problem is mitigated somewhat by the fact that the attacker would still have to authenticate. Hoewever, he might briefly be able to launch attacks against vulnerabilities in the server at that port.) Third, the doorman runs with root permissions. It is therefore possi- ble that the doorman itself may be attacked, in hopes of exploiting a buffer overflow or similar bug. The doorman does present a formidable barrier to a cracker, but not an impenetrable one. SEE ALSO knock(1), knockcf(5), guestlist(5), doormand.cf(5) ACKNOWLEDGEMENT doormand and knock are an implementation of an original idea by Martin Krzywinski. See his site at http://www.portknocking.org COPYRIGHT Copyright (c) 2003-2005, J.B.Ward <bward2@users.sourceforge.net> Doorman, V0.81 Aug 14, 2005 doormand(8)