Found at: http://http://wizzy.org.za//article/articleprint/20/-1/2/ |
Blocking spam |
I have to rewrite my spam-filtering systems every six months. This is my latest attempt, using greylisting with the exim MTA in addition to HELO checking and tests on known spammers.
Other useful resources are :-
/sbin/chkconfig mysqld on /etc/rc.d/init.d/mysqld start mysqladmin -u root password 'SecRet' |
mysqladmin -u root -p create exim mysql -u root -p mysql> grant all on exim.* to exim@localhost identified by 'exim%worD'; mysql> flush privileges; mysql> quit; mysql -u exim -p exim mysql> CREATE TABLE greylist ( relay_ip char(15) NOT NULL, sender char(100) NOT NULL, recipient char(25) NOT NULL, block_expires datetime NOT NULL, PRIMARY KEY (relay_ip, sender, recipient) ); mysql> quit; |
acl_smtp_rcpt = check_recipient
# are they in the database already ?
GREYLIST_TEST = SELECT CASE \
WHEN now() - block_expires > 0 THEN 2 \
ELSE 1 \
END \
FROM greylist \
WHERE relay_ip = '$ {quote_mysql:$sender_host_address}' \
AND sender = '$ {quote_mysql:$sender_address}' \
AND recipient = '$ {quote_mysql:$local_part}'
# add them in, with 25 minute block
GREYLIST_ADD = INSERT INTO greylist (relay_ip, sender, recipient, block_expires) \
VALUES ( '$ {quote_mysql:$sender_host_address}', \
'$ {quote_mysql:$sender_address}', \
'$ {quote_mysql:$local_part}', \
DATE_ADD(now(), INTERVAL 25 MINUTE) \
)
# keep the entry fresh.
GREYLIST_UPDATE = UPDATE greylist SET \
block_expires = DATE_SUB(now(), INTERVAL 8 HOUR) \
WHERE relay_ip = '$ {quote_mysql:$sender_host_address}' \
AND sender = '$ {quote_mysql:$sender_address}' \
AND recipient = '$ {quote_mysql:$local_part}'
hide mysql_servers = localhost/exim/exim/exim%worD
|
check_recipient:
# deny addresses with funny letters and shell escapes
deny local_parts = ^.*[@%!/|] : ^\.
# accept locally generated emails
accept hosts = :
# accept anyone who can authenticate
accept authenticated = *
# accept null senders - bounced bounces or address verification
accept senders = : postmaster
domains = +local_domains : +relay_domains
# No HELO/EHLO
deny condition = $ {if eq{$sender_helo_name}{}{yes}{no}}
message = Polite hosts say HELO first\n\
Please see RFC 2821 section 4.1.1.1
log_message = Bad HELO: Empty HELO
# drop messages without at least one dot in the HELO hostname
drop message = HELO/EHLO must contain a Fully Qualified Domain Name
condition = $ {if match{$sender_helo_name} \
{\N^[^.].*\.[^.]+$\N} \
{no}{yes} \
}
# surprising number of spammers spoof my own address
drop message = HELO/EHLO invalid
condition = $ {if match{$sender_helo_name} \
{your.hostname.org.za} \
{yes}{no} \
}
# and IP
deny condition = $ {if eq{$sender_helo_name}{$interface_address}{yes}{no}}
message = Forged HELO: you are not $sender_helo_name
log_message = Forged HELO: is our interface address
# listed as a spammer
deny message = $sender_host_address is listed at \
$dnslist_domain ($dnslist_value: $dnslist_text)
dnslists = sbl-xbl.spamhaus.org
# set a variable marking whether they were in the database
warn set acl_m2 = $ {lookup mysql{GREYLIST_TEST}{$value}{0}}
# new entry in database - defer, and add them
defer message = Greylisted - You have been greylisted. This is part of our standard anti-spam \
measures and your mail system should automatically try again later.
condition = $ {if eq{$acl_m2}{0}{1}}
condition = $ {lookup mysql{GREYLIST_ADD}{yes}{no}}
# they are listed, but it is still too early
defer message = Greylisted - try again in half an hour
condition = $ {if eq{$acl_m2}{1}{1}}
# freshen entry
warn condition = $ {lookup mysql{GREYLIST_UPDATE}{yes}{no}}
# could we deliver a bounce message if needed ?
require verify = sender
# we relay for our friends only
accept domains = +relay_domains
deny message = relay not permitted
|
#! /bin/sh # purge items from database on two conditions :- # between 6 and 8 hours old (Greylisted address did not retry) # 28 days old (stale) /usr/bin/mysql --user=exim --password='exim%worD' exim << END_SQL DELETE FROM greylist WHERE now() > DATE_ADD(block_expires, INTERVAL 6 HOUR) AND now() < DATE_ADD(block_expires, INTERVAL 8 HOUR); DELETE FROM greylist WHERE now() > DATE_ADD(block_expires, INTERVAL 35 DAY); END_SQL |