John Levine's greydaemon
On this page: • Introduction • License • Status/Warranty • Documentation • Pre-requisites • Download • Installation • Setup / Configuration • Compatibility • Security • Programming Notes • Archives
Introduction
This package extends netqmail with John Levine's greylisting daemon. Subject to the environment variable GREYIP being set, greylist checks are made for incoming SMTP connections prior to accepting messages.
'Full' greylisting is implemented, meaning that the connecting IP address, envelope sender and envelope recipient form the triplet that is checked.
greydaemon is used by qmail-smtpd to carry out these checks; qmail-smtpd communicates with greydaemon using UDP. greydaemon itself is written in Perl.
qmail-logmsg is a pre-requisite of this package, along with Perl.
Also note that although this package comes with the 'glue' for it to be used with netqmail there is no reason why greydaemon couldn't be used with other MTAs, subject to appropriate 'glue' being added for the relevant MTA. Ask me or John about this if it's relevant to you.
License
The greydaemon [Perl] program is subject to a 'BSD' style license: Please see the greydaemon program itself - the text of the license is included there.
Status / Warranty
No warranty, express or implied is given - USE THIS SOFTWARE ENTIRELY AT YOUR OWN RISK. You will need to satisfy yourself as to the suitability of this software before deploying it in a production environment.
Documentation
The documentation for this package consists of this web page and the included man pages (the qmail-smtpd man page is an updated version of the original):
- greydaemon(8)
- qmail-smtpd(8) - see the 'Greylisting' section.
Pre-requisites
This package is for netqmail 1.06 patched with qmail-logmsg. Perl is required - that's what greydaemon is written in.
Download
The current release, version 1.15, is available in plaintext or gzipped (.gz).
Installation
Proceed as follows:
- Unpack the patch if you've downloaded a compressed version.
- Patch your qmail source: Enter your
netqmail-1.06source directory (already patched with qmail-logmsg) and type,patch < path_to_the_patch/nq106-grey-v1.15.patch
which should apply the patch. If this fails, you will need to patch the failed parts by hand. If you're basing your installation on a Life with qmail (LWQ) style setup, you'd apply the patch then continue with
make setup checkin section 2.5.5. - You can now compile qmail and install as normal.
- You will need to setup a new 'service' to run
greydaemon, and adjust yourqmail-smtpdsetup, see the Setup/Configuration section below. - I'd appreciate your report on whether you could compile qmail successfully with this patch so that I can update the Compatibility section below - please email grey-compat@acrconsulting.co.uk with details of your system (esp. OS & CPU) - just
cat systypefrom within your qmail source directory after compilation is enough if you're in a hurry.
Setup / Configuration
Summary:
- Setup a 'service' for
greydaemon. - Enable greylisting in
qmail-smtpd
If you're comfortable with qmail, daemontools etc. you can probably just skim-read this section; if you need a bit more detail, then this section should provide it...
In detail:
Setting up greydaemon as a 'service':
- You need to run
greydaemon- it runs as a daemon. It listens for UDP requests. - Assuming you have daemontools installed (as in LWQ), you can create a 'service' as follows (the example paths here follow those of LWQ esp. section 2.8.22, please adjust them for your own installation if necessary):
- Create a user
greyd(for example) for greydaemon to run as. - Create supervise directories for
greydaemon[/log],mkdir -p /var/qmail/supervise/greydaemon/log
- Change into the
supervise/greydaemondirectory,cd /var/qmail/supervise/greydaemon
- Create the save directory you've just specified and set its ownership to that of the username
greydaemonwill run as,mkdir -p save
chown greyd save
- Create a whitelist if you are using one (called
greywhitein this example). You may like to use this whitelist as a starting point (it includes some instructions). - Create the
runfile,#!/bin/sh
exec /var/qmail/bin/greydaemon -m 2 -g 24 -t 30 -u greyd -w greywhite 127.0.0.1 save/savefile 2>&1
- Create the
log/runfile,#!/bin/sh
exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t /var/log/greydaemon
- Make the
runandlog/runfiles executable,chmod +x run log/run
- Create the log directory you've just specified,
mkdir -p /var/log/greydaemon
chown qmaill /var/log/greydaemon
- Link the
supervise/greydaemondirectory into/service:ln -s /var/qmail/supervise/greydaemon /service
- Check
greydaemonandgreydaemon/logare running:svstat /service/greydaemon /service/greydaemon/log
which should give a result like,/service/greydaemon: up (pid 16646) 100 seconds
/service/greydaemon/log: up (pid 16831) 100 seconds
If either service shows 'up' for only a second or two, you need to check that you've followed these instructions carefully, you can also get a clue looking at thereadproctitleps entry.
Enabling greylisting in qmail-smtpd:
Greylisting is enabled using the GREYIP environment variable. This specifies the IP address and/or port on which greydaemon is listening. Specifying an empty string, GREYIP="" disables greylisting; setting GREYIP=":" causes qmail-smtpd to use the default IP address and port for greylisting; or you can specify the IP address where greydaemon is listening before the : and/or the port it's listening on after the :, so for example GREYIP="192.168.10.10:19191".
- Assuming you've setup your qmail-smtpd service with tcpserver and the
-xoption (as in LWQ), you just need to update the cdb file referenced by this-xoption. The source for this file is typically/etc/tcp.smtp. For example,127.:allow,RELAYCLIENT=""
192.168.:allow,RELAYCLIENT=""
:allow,GREYIP=":"
which would perform greylisting on all addresses except the loopback address and 192.168.x.y addresses. - If you've setup
greydaemonon a non-default address (perhaps you're runninggreydaemonon a separate machine), you'll also need to specify the address it's listening on - adjust the above to includeGREYIP="192.168.5.5:", for example. - Finally, don't forget to update the cdb file corresponding to the source file you've just edited. If you have a LWQ setup that's,
qmailctl cdb
otherwise (assuming/etc/tcp.smtp,/etc/tcp.smtp.cdb),tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
- Alternatively (and particularly if you're not using the
-xoption totcpserver) you can enable greylisting for all SMTP connections by settingGREYIPin the environment in whichqmail-smtpdis started - for example your startup script might now contain the lineexec env GREYIP=":" /usr/local/bin/tcpserver ...
Compatibility
Please let me know if you successfully install greydaemon on systems not listed below (see the end of the installation section on this page).
Compatibility with qmail, netqmail: The greydaemon patch should apply cleanly to the following:
- netqmail 1.05 patched with qmail-logmsg version 1.1, 1.2 or 1.3.
- netqmail 1.06 patched with qmail-logmsg version 1.1, 1.2 or 1.3.
Compatibility with Unix / Linux: Successful compilations have been reported on the following:
Linux:
- Centos 5.3 / i386 (Systype: linux-2.6.18-128.1.10.el5pae-:i386-:-:ppro-:-)
- Fedora 8 / i386 (Systype: linux-2.6.26.8-57.fc8-:i386-:-:ppro-:-)
Unix:
- OpenBSD 4.0 / Sparc64 (Systype: openbsd-4.0-custom#1-:openbsd.sparc64-:-:sparc64-:-)
As discussed below under programming notes, the UDP/socket code is the same as that in qmail-verify which will make patching with it relatively straightforward.
Security
Here are some notes relating to security with this package, these notes are unlikely to be exhaustive:
This package deliberately splits the greylisting functionality such that the actual greylisting part runs as a separate daemon, greydaemon, with qmail-smtpd using UDP to communicate with it. Changes to qmail-smtpd are minimal and very similar to those used by qmail-verify.
Once greydaemon has started listening it changes its effective UID/GID if the -u option has been used.
Programming Notes
I've tried to ensure that the changes to qmail-smtpd.c are minimal and have re-used code employed in qmail-verify to maximise commonality between these packages and make it relatively straightforward to patch both patches to an instance of netqmail.
The request to greydaemon is sent when the connection gets to the DATA stage, with the various recipients being included in the request packet. If there are very many recipients and/or these recipients have particularly long addresses, the maximum packet size may be exceeded, in which case the request is truncated. It should still however include some recipients. See the note on MAXGREYDATASIZE below.
Where greylisting occurs, qmail-smtpd logs only the first recipient as greylisted - but all recipients will be logged by greydaemon in this situation.
A few values are specified with #define at the top of grey.h:
MAXGREYDATASIZE specifies the largest amount of data to put in a UDP packet; the actual packet will be slightly larger. The default setup sends UDP queries to localhost, so packet fragmentation shouldn't be a problem. Alternatively, having a separate greylisting server may cause UDP fragmentation for larger queries. If you dislike this, you could convert the code to use TCP or lower the max. packet size; 1470 is likely to be fragmentation-safe, but this will reduce the amount of recipient addresses that can be checked.
DEFAULTGREYPORT specifies the default port that greydaemon will listen on; this can be overridden by GREYIP at run time.
DEFAULTGREYIP specifies the default IP address that greydaemon will listen on; this can be overridden by GREYIP at run time.
GREYTIMEOUT specifies the timeout within which a response would be expected from greydaemon. In the case of a timeout connections are accepted. To change this behaviour alter the if (r == 0) line in greycheck() in grey.c to return 0.
Archives
The only other public releases were versions 1.12 and 1.14:
In v1.14 there was a memory leak with the declaration of chkpacket in grey.c missing a static prefix (thank you to Manvendra Bhangui).
In v1.12 the code parsing the GREYIP value only worked by accident(!) - scan_ip_port() and grey_init() were faulty (thank you to Manvendra Bhangui).
This page last updated: AR, 1st July 2013.

