Chris Johnson cjohnson-qmail@palomine.net What's tarpitting? It's the practice of inserting a small sleep in an SMTP session for each RCPT TO after some set number of RCPT TOs. The idea is to thwart spammers who would hand your SMTP server a single message with a long list of RCPT TOs. If a spammer were to attempt to use your server to relay a message with, say, 10,000 recipients, and you inserted a five-second delay for each recipient after the fiftieth, the spammer would be "tarpitted" and would likely assume that his connection had stalled and give up. The subject originally came up in a discussion on the qmail mailing list of ways to run an open relay safely (I didn't suggest it, and I don't do that kind of thing), but it could also be useful in keeping your own dial-up customers from using you as a spam relay. This patch will allow qmail-smtpd to do tarpitting. There are two control files involved: control/tarpitcount and control/tarpitdelay. tarpitcount is the number of RCPT TOs you accept before you start tarpitting, and tarpitdelay is the number of seconds of delay to introduce after each subsequent RCPT TO. tarpitcount defaults to 0 (which means no tarpitting), and tarpitdelay defaults to 5. You can override both tarpitcount and tarpitdelay by setting TARPITCOUNT and TARPITDELAY in qmail-smtpd's environment (with tcpserver). If you used the earlier version of this patch, note that this version no longer uses the NOTARPIT environment variable; set TARPITCOUNT to 0 to achieve the same effect. --- qmail-smtpd.c.orig Mon Jun 15 06:53:16 1998 +++ qmail-smtpd.c Wed Mar 10 10:55:13 1999 @@ -96,6 +96,8 @@ int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; +int tarpitcount = 0; +int tarpitdelay = 5; void setup() { @@ -110,6 +112,15 @@ if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control(); if (timeout <= 0) timeout = 1; + if (control_readint(&tarpitcount,"control/tarpitcount") == -1) die_control(); + if (tarpitcount < 0) tarpitcount = 0; + x = env_get("TARPITCOUNT"); + if (x) { scan_ulong(x,&u); tarpitcount = u; }; + if (control_readint(&tarpitdelay,"control/tarpitdelay") == -1) die_control(); + if (tarpitdelay < 0) tarpitdelay = 0; + x = env_get("TARPITDELAY"); + if (x) { scan_ulong(x,&u); tarpitdelay = u; }; + if (rcpthosts_init() == -1) die_control(); bmfok = control_readfile(&bmf,"control/badmailfrom",0); @@ -221,6 +232,7 @@ int flagbarf; /* defined if seenmail */ stralloc mailfrom = {0}; stralloc rcptto = {0}; +int rcptcount; void smtp_helo(arg) char *arg; { @@ -245,6 +257,7 @@ if (!stralloc_copys(&rcptto,"")) die_nomem(); if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); if (!stralloc_0(&mailfrom)) die_nomem(); + rcptcount = 0; out("250 ok\r\n"); } void smtp_rcpt(arg) char *arg; { @@ -261,6 +274,7 @@ if (!stralloc_cats(&rcptto,"T")) die_nomem(); if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); + if (tarpitcount && ++rcptcount >= tarpitcount) while (sleep(tarpitdelay)); out("250 ok\r\n"); }