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)