$acl_c_spamscore
variable. This is the main variable in the configuration program, all the other behavior of the MTA depends on its value. acl_check_sender: warn set acl_c_spamscore = 0 [...] accept
$acl_c_bouncemessage
, in which messages are added about the results of all checks. It is necessary for high-quality debugging of the MTA. You will immediately see in the server log what checks were not passed and how many points were scored, and admins reading mail failures at the other end of the wire will be able to understand why the SMTP session was broken and correct the error (yeah, dreaming; 95% of them, alas , only scratches turnip). However, there are so few false positives with a properly configured filtering system (I have only one over the last year) that I use this variable only for my own convenience when debugging.acl_check_sender
section (the phase of the SMTP session, coming after the transfer “MAIL FROM: <email@address.any>”): acl_check_sender: [...] warn set acl_c_spamscore = 0 drop hosts = +blacklisted_hosts message = Connection closed. IP [$sender_host_address] is listed in Blacklist. [...] accept
IP varchar(15)
and Timestamp int(11)
, where the ip-address and the time it is added to the database are stored in the unix_time format (in this format, it is convenient to carry out operations seconds):SELECT IP FROM antispam.blacklist WHERE IP='1.1.1.1' limit 1"
. hostlist blacklisted_hosts = ${lookup mysql {SELECT IP FROM antispam.blacklist \ WHERE IP='$sender_host_address' limit 1} \ }
+blacklisted_hosts
in access lists.hide mysql_servers = 127.0.0.1/antispam/mta/mtapass
directive hide mysql_servers = 127.0.0.1/antispam/mta/mtapass
at the very beginning of the config, which contains the parameters for connecting to the database. warn !condition = ${lookup{$sender_address_domain}wildlsearch{/CONFIG_PREFIX/\ additional/trusted_zones}{1}{0}} set acl_c_spamscore = ${eval:$acl_c_spamscore+20} set acl_c_bouncemessage = $acl_c_bouncemessage Suspicious e-mail address;
^.*\\.ru\$ ^.*\\.ua\$ ^.*\\.by\$ ^.*\\.com\$ ^.*\\.org\$ ^.*\\.net\$ ^.*\\.edu\$
#-----------------------------DNS Records verify------------------------------------ warn !verify = reverse_host_lookup set acl_c_spamscore = ${eval:$acl_c_spamscore+30} set acl_c_bouncemessage = $acl_c_bouncemessage Reverse host lookup failed;
warn condition = ${if eq {$acl_c_reverse_zone}{}} set acl_c_spamscore = ${eval:$acl_c_spamscore+50} set acl_c_bouncemessage = $acl_c_bouncemessage No DNS PTR record found;
#-----------------------------------------------------------------------------------
$acl_c_reverse_zone
variable appeared here, which contains the result (the DNS value of the PTR of the node) of the following test: set acl_c_reverse_zone = ${escape:${lookup dnsdb{ptr=$sender_host_address}}}
acl_smtp_connect
, which is more correct) or when checking the HELO argument in acl_check_helo
where$acl_c_spamscore
. The difference is small. You can generally use the construction everywhere: warn condition = ${if eq {${escape:${lookup dnsdb{ptr=$sender_host_address}}}}\ {}}
#-----------------------------Dynamic IP pools processing--------------------------- warn condition = ${lookup {$acl_c_reverse_zone}wildlsearch{CONFIG_PREFIX/\ additional/dynamic_pools}{1}{0}\ } set acl_c_spamscore = ${eval:$acl_c_spamscore+70} set acl_c_bouncemessage = $acl_c_bouncemessage Suspected PTR DNS record \ points to dynamic IP pool;
#-----------------------------------------------------------------------------------
^.*([0-9]+).([0-9]+).([0-9]+).([0-9]+).* ^.*host.([0-9]+).* ^.*dynamic.* ^.*dial.* ^.*ppp.* ^.*pptp.* ^.*broadband.* ^.*dhcp.*
#---------------------------Geographical DNS zone processing------------------------ warn !condition = ${lookup {$sender_host_name}wildlsearch{/CONFIG_PREFIX/\ additional/trusted_zones}{1}{0}} set acl_c_spamscore = ${eval:$acl_c_spamscore+20} set acl_c_bouncemessage = $acl_c_bouncemessage Untrusted domain zone;
#------------------------------------------------------------------------------------------ #-------------------Huge DSL & DialUp ISP's DNS zone processing--------------------- warn condition = ${lookup {$sender_host_name}wildlsearch{CONFIG_PREFIX/\ additional/spamvertised_isp}{1}{0}} set acl_c_spamscore = ${eval:$acl_c_spamscore+40} set acl_c_bouncemessage = $acl_c_bouncemessage Spamvertised ISP DNS zone;
#-----------------------------------------------------------------------------------
^.*comcast\\.net ^.*pppoe\\.mtu-net\\.ru ^.*qwerty\\.ru ^.*ono\\.com ^.*virtua\\.com\\.br
#----------------------------Handler for impossible HELO's------------------------- warn condition = ${if or {\ {match{$sender_helo_name}{localhost}}\ {match{$sender_helo_name}{mail.hornsnhoofs.com}}\ {match{$sender_helo_name}{^127\\.0\\.0\\.([0-9]+)}}\ }{1}{0}\ } set acl_c_spamscore = ${eval:$acl_c_spamscore+60} set acl_c_bouncemessage = $acl_c_bouncemessage HELO $sender_helo_name is forged;
#---------------------------------------------------------------------------------- #------------------------------Handler for wrong HELO's---------------------------- warn !condition = ${if or {\ {match{$sender_helo_name}{^.+\\.((?i)[az]+)\$}}\ [...] }{1}{0}\ } set acl_c_spamscore = ${eval:$acl_c_spamscore+20} set acl_c_bouncemessage = $acl_c_bouncemessage HELO name is not \ Fully Qualified Domain Name;
#---------------------------------------------------------------------------------- #--------------------------Handler for forged HELO arguments----------------------- warn !condition = ${if or {\ {eq{$sender_helo_name}{$sender_host_name}}\ }\ } set acl_c_spamscore = ${eval:$acl_c_spamscore+20} set acl_c_bouncemessage = $acl_c_bouncemessage HELO not equals Hostname;
#---------------------------------------------------------------------------------- #------------------------Handler for suspicious HELO arguments--------------------- warn !condition = ${lookup {$sender_helo_name}wildlsearch{/CONFIG_PREFIX/\ additional/trusted_zones}{1}{0}} set acl_c_spamscore = ${eval:$acl_c_spamscore+20} set acl_c_bouncemessage = $acl_c_bouncemessage Suspicious HELO argument;
#----------------------------------------------------------------------------------
#-------------------------------DNSBL processing section--------------------------- warn dnslists = sbl.spamhaus.org set acl_c_spamscore = ${eval:$acl_c_spamscore+60} set acl_c_bouncemessage = $acl_c_bouncemessage Listed in DNSBL $dnslist_domain; warn dnslists = bl.spamcop.net set acl_c_spamscore = ${eval:$acl_c_spamscore+60} set acl_c_bouncemessage = $acl_c_bouncemessage Listed in DNSBL $dnslist_domain; warn dnslists = dnsbl.sorbs.net set acl_c_spamscore = ${eval:$acl_c_spamscore+60} set acl_c_bouncemessage = $acl_c_bouncemessage Listed in DNSBL $dnslist_domain; warn dnslists = dul.ru set acl_c_spamscore = ${eval:$acl_c_spamscore+60} set acl_c_bouncemessage = $acl_c_bouncemessage Listed in DNSBL $dnslist_domain;
#----------------------------------------------------------------------------------- warn !verify = sender/callout=3m,defer_ok set acl_c_spamscore = ${eval:$acl_c_spamscore+60} set acl_c_bouncemessage = $acl_c_bouncemessage Cannot complete sender verify;
accept condition = ${if >{$acl_c_spamscore}{145}}
accept delay = ${eval:$acl_c_spamscore/2}s
acl_check_rcpt: [...] #------Spamtraps check------- warn condition = ${lookup {$local_part@$domain}lsearch{/CONFIG_PREFIX/\ additional/spamtraps}{1}{0}} set acl_c_spamscore = ${eval:$acl_c_spamscore+50} set acl_c_bouncemessage = $acl_c_bouncemessage Spamtrap hit;
#----------------------------
spamtrap@hornsnhoofs.com honeypot@hornsnhoofs.com
#---------------------------Blacklist Processing Section------------------------ drop !senders = : !condition = ${if <{$acl_c_spamscore}{150}} message = Connection closed. Spamscore threshold (150 points) reached. \ Spamscore is $acl_c_spamscore! \ Warning: IP [$sender_host_address] added to Blacklist. \ Details: $acl_c_bouncemessage condition = ${lookup mysql \ {\ insert into antispam.blacklist (IP,Timestamp)\ values ('${sender_host_address}',${tod_epoch});\ }\ }
#-------------------------------------------------------------------------------
#!/bin/bash echo "delete from blacklist where Timestamp < `echo "\`date +%s\`-604800" | bc`;" | /usr/local/bin/mysql -u mta -pmtapass antispam echo "optimize table blacklist" | /usr/local/bin/mysql -u mta -pmtapass antispam
deny condition = ${if >{$acl_c_spamscore}{100}} condition = ${if ={$acl_c_validrcpt}{1}} message = Message rejected. Spamscore threshold (100 points) reached. \ Spamscore is $acl_c_spamscore! Details: acl_c_bouncemessage
accept condition = ${if <{$acl_c_spamscore}{70}} condition = ${if ={$acl_c_validrcpt}{1}}
$acl_c_validrcpt
) exists. #--------------------------Greylist Processing Section-------------------------- defer condition = ${if ={$acl_c_validrcpt}{1}} condition = ${lookup mysql \ {\ select Source from antispam.greylist where \ Source='$sender_host_address' \ and Timestamp > ${eval:$tod_epoch-1740} limit 1\ }{1}{0}\ } message = Message deferred. Try again later. You was been already greylisted. accept condition = ${lookup {$acl_c_reverse_zone}wildlsearch{CONFIG_PREFIX/\ additional/dynamic_pools}{1}{0}} condition = ${if ={$acl_c_validrcpt}{1}} condition = ${lookup mysql \ {\ select Source from antispam.greylist where \ Source='$sender_host_address' \ and grey_hash = '${md5:${lc:$sender_address\ $local_part@$domain}}' \ and Timestamp < ${eval:$tod_epoch-1740} limit 1 \ }{1}{0}\ } condition = ${lookup mysql \ {\ delete from antispam.greylist where \ Source='$sender_host_address' \ and grey_hash = '${md5:${lc:$sender_address\ $local_part@$domain}}' \ }\ } accept !condition = ${lookup {$acl_c_reverse_zone}wildlsearch{CONFIG_PREFIX/\ additional/dynamic_pools}{1}{0}} condition = ${if ={$acl_c_validrcpt}{1}} condition = ${lookup mysql \ {\ select Source from antispam.greylist where \ Source='$sender_host_address' \ and grey_hash = '${md5:${lc:$sender_address\ $local_part@$domain}}' \ and Timestamp < ${eval:$tod_epoch-1740} limit 1 \ }{1}{0}\ } condition = ${lookup mysql \ {\ insert into antispam.whitelist (IP, Timestamp) \ values ('$sender_host_address',$tod_epoch) \ }{1}{1}\ } condition = ${lookup mysql \ {\ delete from antispam.greylist where \ Source='$sender_host_address' \ and grey_hash = '${md5:${lc:$sender_address\ $local_part@$domain}}' \ }\ } defer condition = ${if ={$acl_c_validrcpt}{1}} condition = ${if >={$acl_c_spamscore}{70}} condition = ${lookup mysql \ {\ insert into antispam.greylist (Source,grey_hash,Timestamp) \ values ('$sender_host_address',\ '${md5:${lc:$sender_address$local_part@$domain}}',\ ${tod_epoch}); \ }\ } message = Message deferred. Spamscore is $acl_c_spamscore! Try again later. \ Greylisting in progress. Details: $acl_c_bouncemessage #-----------------------------------------------------------------------------
Source varchar(15)
, grey_hash varchar(32)
, Timestamp int(11)
. The Source field contains the sender's ip address, grey_hash the md5 hash from the sender and recipient addresses, and Timestamp the time to add the record in unix_time format. In addition to it, greylisting also requires a whitelist table, which allows you to add the addresses of nodes that have passed greylisting there. The whitelist table format completely repeats that for the blacklist table described above. deny message = Message rejected. No such user here. Relaying denied. $acl_c_support set acl_c_spamscore = ${eval:$acl_c_spamscore+5} set acl_c_bouncemessage = $acl_c_bouncemessage RCPT Fail; delay = ${eval:$acl_c_spamscore/2}s
deny ip from any to any
, it only affects the SMTP session.Source: https://habr.com/ru/post/133215/
All Articles