doormand(8)                    Doorman & Knocker                   doormand(8)

       doormand - The doorman daemon

       doormand [-h] [-v] [-D] [-f config-file]

       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  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

       -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'.

       -f config-file
              Use the specified configuration file.   The  default  configura-
              tion     file    is    named    ""    in    directory
              "/usr/local/etc/doormand", or the  directory  specified  by  the
              configure  "--sysconfdir"  option  when  building  doormand  and

       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.)

       Ready-made  scripts  are  supplied  for  Linux,  FreeBSD,  netBSD,  and

        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 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

       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

       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  )
       before children exit.

FILES the configuration file for doormand. (man 5

       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)  the  process-ID file created by the parent doormand pro-
       cess.  The full pathname is specified by the 'pidfile' record of  door-   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.

       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.

       knock(1), knockcf(5), guestlist(5),

       doormand and knock are an implementation of an original idea by  Martin
       Krzywinski.  See his site at

       Copyright (c) 2003-2005, J.B.Ward

Doorman, V0.81                   Aug 14, 2005                      doormand(8)