From owner-freebsd-isp Fri May 30 13:30:36 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id NAA06395 for isp-outgoing; Fri, 30 May 1997 13:30:36 -0700 (PDT) Received: from wlk.com (news.wlk.com [192.86.83.250]) by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id NAA06385 for ; Fri, 30 May 1997 13:30:31 -0700 (PDT) Received: from SMTPdaemon by wlk.com (smail3.2) with SMTPL id m0wXYJY-0009t5C; Fri, 30 May 1997 15:30:20 -0500 (CDT) Received: from critter.dk.tfs.com (localhost [127.0.0.1]) by critter.dk.tfs.com (8.8.5/8.8.5) with ESMTP id WAA01060 for ; Fri, 30 May 1997 22:26:35 +0200 (CEST) To: isp@freebsd.org Subject: stopping mailspam without tears... From: Poul-Henning Kamp Date: Fri, 30 May 1997 22:26:34 +0200 Message-ID: <1057.865023994@critter.dk.tfs.com> Sender: owner-isp@freebsd.org X-Loop: FreeBSD.org Precedence: bulk A local ISP here had the problem that they were being used as a relay for various mail-spammers. Here is a summary of the solution I am implementing. The reason I think it is interesting is that it doesn't involve sendmail.cf :-) Life is too short for sendmail.cf. If anybody has the time to work on this to make it a suitable option in /etc/sysconfig for freebsd... nudge, nudge, wink, wink! Poul-Henning Cookbook: --------- Make a directory /var/spool/mqueue_in, set owner, group & modes right. Start sendmail with -bd -O QueueDirectory=/var/spool/mqueue_in -O DeliveryMode=q this makes sendmail store all incomming mail in your new directory instead of delivering it. Start another sendmail with -q5m or similar. Now write a small script in a language of your choice, which looks at the qf* and df* files in /var/spool/mqueue_in and if you like the contents, you move them to /var/spool/mqueue for delivery. The format of the qf* files are descibed in Appendix B in src/usr.sbin/sendmail/doc/op/op.me TADA! Yes, I know all the drawbacks of this scheme, but I can make checks this way that none of the sendmail patches I have seen yet allows me to do. You can check all recipients all header lines and envelope information, and you even have access to the message itself, at the same time! Emails from spammers will just be /dev/nulled. I include my (Tcl!) script here for all to work from #!/usr/bin/tclsh # # ---------------------------------------------------------------------------- # "THE BEER-WARE LICENSE" (Revision 42): # wrote this file. As long as you retain this notice you # can do whatever you want with this stuff. If we meet some day, and you think # this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp # ---------------------------------------------------------------------------- # # $Id$ # set spool_in /var/spool/mqueue_in set spool_out /var/spool/mqueue set spool_spam /var/tmp/spam set spool_problem /var/spool/mqueue_problem ################# proc Process {id qf df} { global spool_in spool_out spool_spam spool_problem set f [open $qf] if {![file size $qf]} { if {[file mtime $qf] + 600 < [clock seconds]} { puts "$id Stale zero size queue file" MoveTo $id $spool_problem } return } set rcount 0 set triggers 0 while {[gets $f a] >= 0} { # We can risk seing anything in these, so be carefull if {[regexp {^HSubject: } "$a"]} continue if {[regexp {^HX} "$a"]} continue # Count recipients if {[regexp {^R} "$a"]} {incr rcount} # Look for telltale signs if {[regexp {^HReceived.*000\.000\.000\.000} "$a"]} {incr triggers} if {[regexp {@savetrees\.com} "$a"]} {incr triggers} if {[regexp {@fun\.com} "$a"]} {incr triggers} if {[regexp {@public\.com} "$a"]} {incr triggers} if {[regexp {@mary-world\.com} "$a"]} {incr triggers} if {[regexp {Received: from "Cyber-Bomber"} "$a"]} {incr triggers} if {[regexp {Received: .*sallynet\.com} "$a"]} {incr triggers} if {[regexp {Received: .*marynet\.com} "$a"]} {incr triggers} if {[regexp {earthlink\.net} "$a"]} {incr triggers} } close $f puts "$id $rcount $triggers" if {$rcount > 10 && $trigger} {MoveTo $id $spool_spam} MoveTo $id $spool_out } ################# proc MoveTo {id where} { global spool_in puts "moving $id to $where" exec sh -c "mv $spool_in/??$id $where" } ################# while 1 { set list [glob -nocomplain $spool_in/qf*] if {![llength $list]} { exec sleep 30 } else { foreach i $list { puts "doing $i" regsub "$spool_in/qf(.*)" $i {\1} b if {[file exists $spool_in/tf$b]} continue if {![file exists $spool_in/qf$b]} continue if {![file exists $spool_in/df$b]} continue set error [catch "Process $b $spool_in/qf$b $spool_in/df$b" ret] if {$error} { puts "ERROR ON ID $b MOVED TO PROBLEM" puts "$error" puts "$ret" MoveTo $b $spool_problem } } exec sleep 10 } } -- Poul-Henning Kamp | phk@FreeBSD.ORG FreeBSD Core-team. http://www.freebsd.org/~phk | phk@login.dknet.dk Private mailbox. whois: [PHK] | phk@tfs.com TRW Financial Systems, Inc. Future will arrive by its own means, progress not so.