Main | Exim 4 Anti-SPAM Configuration
The default Exim4 configuration is generally pretty good. Below, these are the additional tweaks I've made to the default. It needs more comments, and I'm currently mostly doing this to document things for myself since I'm in the middle of making a replacement Exim4 mail server.
#Main section: av_scanner = clamd:/var/run/clamav/clamd.ctl # # SEE "AVSCANNER PART 2" at the end of acl_check_data for the 2nd part. # Note that this requires exim4_daemon_heavy or an Exim4 daemon patched # with the exiscan_acl patch in order to function
#Reject email that is over the size limit: MESSAGE_SIZE_LIMIT = 10M #Delete frozen messages after a time instead of having them build up: MAIN_TIMEOUT_FROZEN_AFTER = 1d #Set which DNSRBLs to check IP addresses with: CHECK_RCPT_IP_DNSBLS = sbl-xbl.spamhaus.org : bl.spamcop.net : cbl.abuseat.org #Set maximum bounce message size sent to 16K return_size_limit = 16K
# *** # Checks HELO/EHLO line for RFC2821 compatibility # *** # acl_check_helo: # Note: # Underscores in hostnames are auotmatically rejected by Exim4 itself # There's no need to make a HELO check for those. # A remote host can't be localhost or localdomain # Adds a little tarpitting at the same time with a 15 second delay # drop hosts = !+relay_from_hostscondition = ${if match\
{\N^(127\.0\.0\.1|localhost(\.localdomain)?)$\N}\
{yes}{no}}message = $sender_helo_name is an invalid HELO/ELHO\n\
Required to be a valid FQDN as per RFC 2821 log_message = $sender_host_name forged localhost delay = 15s # A remote host using my own HELO is wrong # NOTE: MODIFY FOR MAIL SERVER IP and change domain.tld to proper domain name # drop hosts = !+relay_from_hostscondition = ${if match\
{\N^((\[)?111\.222\.33\.44](\])?|(.*\.)?domain\.tld)$\N}\
{yes}{no}} message = Forged HELO detected and logged. Connection terminated. log_message = $sender_host_name forged our info delay = 15s # Another check on domain names being used in HELO from others # This matches the exact HELO greeting used and compares it to # the other domain names we accept. Unfortunately certain mailers # I currently relay for seem to be using a helo of 'domain.tld', # not an FQDN, so I cannot include +relay_to_domains for this, # making the check somewhat pointless. # dropcondition = ${if match_domain\
{$primary_hostname:+local_domains}\
{true}{false}}#condition = ${if match_domain\
# {$primary_hostname:+local_domains:+relay_to_domains}\
# {true}{false}} message = Forged HELO detected and logged. Connection terminated. log_message = $sender_host_name used our name in HELO/EHLO greeting. delay = 15s # Don't accept an IP address for a HELO greeting # drop hosts = !+relay_from_hosts condition = ${if isip {true}{false}}message = An IP address is unacceptable for a HELO greeting.\n\
HELO greeting must conform to RFC 2821 -- connection terminated. log_message = $sender_host_name used raw IP address in HELO/EHLO greeting delay = 15s # Helo should not be RFC 1918 address # drop hosts = !+relay_from_hostscondition = ${if match\
{\N^(\[)?(10\.[0-9]{1,3}|172\.(1[6-9]|2[0-9]|31)|192\.168)\.[0-9]{1,3}\.[0-9]{1,3}(\])?$\N}\
{yes}{no}} message = RFC 1918 IP address in HELO log_message = $sender_host_name used RFC 1918 reserved IP in HELO delay = 15s # A proper domain will contain at least one period. # A good percentage of spam worms HELO with random characters without a period. # thus obviously not containing a FQDN in the HELO greeting # drop hosts = !+relay_from_hosts condition = ${if match{\\.}{no}{yes}} message = Invalid HELO/EHLO. Should be FQDN per RFC 2821 log_message = $sender_host_name has no . in HELO name delay = 15s # If the HELO DNS check failed, delay the SMTP transaction for a bit # to slow down the scum bags #warn # hosts = !+relay_from_hosts # log_message = delayed 15sec after helo # !verify = helo # delay = 15s
acl_check_mail:
# # A domain absolutely can't be localhost or localdomain # dropcondition = ${if match\
{\N^(localhost|localhost\.localdomain|localdomain)$\N}\
{yes}{no}} message = '$sender_address_domain' an is invalid domain log_message = $sender_host_name tried to use localhost email address delay = 15s # Deny faked Yahoo email addresses # #deny # senders = *@yahoo.com # condition = ${if match {\Nyahoo.com$\N}{no}{yes}} # message = Address rejected -- appears to be faked Yahoo address # log_message = Fake Yahoo from $sender_host_name # delay = 15s # Deny faked Hotmail email addresses # deny senders = *@hotmail.com condition = ${if match {\Nhotmail.com$\N}{no}{yes}} message = Address rejected -- appears to be faked Hotmail address log_message = Fake hotmail from $sender_host_name delay = 15s # Deny faked MSN email addresses # deny senders = *@msn.com condition = ${if match {\N(hotmail|msn).com$\N}{no}{yes}} message = Address rejected -- appears to be faked MSN address log_message = Fake MSN from $sender_host_name delay = 15s # Deny faked AOL email addresses # deny senders = *@aol.com condition = ${if match {\Nmx.aol.com$\N}{no}{yes}} message = Address rejected -- appears to be faked AOL address log_message = Fake AOL from $sender_host_name delay = 15s
acl_check_rcpt:
# GREYLIST, RCPT section (part 1) # Note: requires installing 'greylistd' # # greylistd(8) configuration follows. # This statement has been added by "greylistd-setup-exim4", # and can be removed by running "greylistd-setup-exim4 remove". # Any changes you make here will then be lost. # # Perform greylisting on incoming messages from remote hosts. # We do NOT greylist messages with no envelope sender, because that # would conflict with remote hosts doing callback verifications, and we # might not be able to send mail to such hosts for a while (until the # callback attempt is no longer greylisted, and then some). # # We also check the local whitelist to avoid greylisting mail from # hosts that are expected to forward mail here (such as backup MX hosts, # list servers, etc). # # Because the recipient address has not yet been verified, we do so # now and skip this statement for non-existing recipients. This is # in order to allow for a 550 (reject) response below. If the delivery # happens over a remote transport (such as "smtp"), recipient callout # verification is performed, with the original sender intact. # # NOTE: normal callout verification is NOT being performed anymore because # it was causing issues I did NOT like. The line below was placed after # the 'domains' line in the section below. -- Chris # verify = recipient/callout=20s,use_sender,defer_ok defermessage = $sender_host_address is not yet authorized to deliver \
mail from <$sender_address> to <$local_part@$domain>. \
Please try later. log_message = greylisted. !senders = :!hosts = : +relay_from_hosts : \
${if exists {/etc/greylistd/whitelist-hosts}\
{/etc/greylistd/whitelist-hosts}{}} : \
${if exists {/var/lib/greylistd/whitelist-hosts}\
{/var/lib/greylistd/whitelist-hosts}{}} !authenticated = * !acl = acl_whitelist_local_deny domains = +local_domains : +relay_to_domainscondition = ${readsocket{/var/run/greylistd/socket}\
{--grey \
$sender_host_address \
$sender_address \
$local_part@$domain}\
{5s}{}{false}} # Accept mail to postmaster in any local domain, regardless of the source, # and without verifying the sender. # accept .ifndef CHECK_RCPT_POSTMASTER local_parts = postmaster .else local_parts = CHECK_RCPT_POSTMASTER .endif # Not sure if this latter part is necessary domains = +local_domains : +relay_to_domains # *** # Drop the connection if the envelope sender is empty, but there is # more than one recipient address. Legitimate DSNs are never sent # to more than one address. # *** # drop senders = : postmaster@* condition = $recipients_count message = Legitimate mail bounces are never sent to more than one recipient. log_message = rejected bounce message with multiple recipients delay = 15s # *** # Deny any more recipients if there have been a number of failed # recipients already, and add incremental delay # *** # deny condition = ${if >{2} {yes}{no}} message = Too many bad recipients log_message = $rcpt_fail_count failed recipient attempts delay = ${eval: $rcpt_fail_count * 10}s # Check against classic DNS "black" lists (DNSBLs) which list # sender IP addresses. # warn # message = X-Warning: $sender_host_address is listed at $dnslist_domain ($dnslist_value: $dnslist_text) .ifdef CHECK_RCPT_IP_DNSBLS warn message = X-Warning: $sender_host_address is listed at $dnslist_domain ($dnslist_value: $dnslist_text) log_message = $sender_host_address is listed at $dnslist_domain ($dnslist_value: $dnslist_text) deny dnslists = CHECK_RCPT_IP_DNSBLS message = X-blacklisted-at: $sender_host_address is listed at $dnslist_domain ($dnslist_value: $dnslist_text) log_message = $sender_host_address is listed at $dnslist_domain ($dnslist_value: $dnslist_text) .endif
acl_check_data:
# GREYLIST DATA section (part 2). I found this to be more efficient # if this is in the DATA section rather than RCPT section, since the # HELO and other checks are more efficient at blocking spam than # the greylist is by itself. This can be added properly by installing # the greylist using the command 'greylistd-setup-exim4 -acltype=data'. # Note: requires installing 'greylistd' # # greylistd(8) configuration follows. # This statement has been added by "greylistd-setup-exim4", # and can be removed by running "greylistd-setup-exim4 remove". # Any changes you make here will then be lost. # # Perform greylisting on incoming messages with no envelope sender here. # We did not subject these to greylisting after RCPT TO:, because that # would interfere with remote hosts doing sender callout verifications. # # Because there is no sender address, we supply only two data items: # - The remote host address # - The recipient address (normally, bounces have only one recipient) # # We also check the local whitelist to avoid greylisting mail from # hosts that are expected to forward mail here (such as backup MX hosts, # list servers, etc). # defermessage = $sender_host_address is not yet authorized to deliver \
mail from <$sender_address> to <$recipients>. \
Please try later. log_message = greylisted. senders = :!hosts = : +relay_from_hosts : \
${if exists {/etc/greylistd/whitelist-hosts}\
{/etc/greylistd/whitelist-hosts}{}} : \
${if exists {/var/lib/greylistd/whitelist-hosts}\
{/var/lib/greylistd/whitelist-hosts}{}} !authenticated = * !acl = acl_whitelist_local_denycondition = ${readsocket{/var/run/greylistd/socket}\
{--grey \
$sender_host_address \
$recipients}\
{5s}{}{false}} # *** # Check for existance of certain headers in the message body and reject # the mail if they aren't included [Date, Message-ID] # *** # # Temporarily not checking the existance of the Message-ID header, as # it seems older Outlook MUA's don't include it #deny # condition = ${if !def:h_Message-ID: {1}} # !senders = *@att.net # message = Message SHOULD have Message-ID: but does not -- rejected. # log_message = failed Message-ID header check # Temporarily not checking the Date header, similar reasoning #deny # condition = ${if !def:h_Date: {1}} # message = Message SHOULD have Date: but does not -- rejected # log_message = failed Date header check # # AV_SCANNER PART 2 # # Don't allow file extensions that are hidden to Outlook MUAs deny message = Hiding of file extensions is not allowed! log_message = Dangerous extension (CLSID hidden)regex = ^(?i)Content-Disposition::(.*?)filename=\\s*"+((\{[a-hA-H0-9-]{25,}\})|((.*?)\\s{10,}(.*?)))"+\$
# *** # Do checking of MIME attachments # *** # MIME checking for errors, deny message if attachment is badly malformed deny message = This message contains malformed MIME ($demime_reason) demime = * condition = ${if >{2}{1}{0}} # Block file attachments that have certain extensions that are dangrous deny message = This message contains an attachment of a type we do not accept (.$found_extension) demime = bat:com:exe:pif:prf:scr:vbs:wmf deny message = This message contains a virus or other harmful content ($malware_name). log_message = $sender_host_address tried sending $malware_name demime = * malware = *
May 02, 2007, at 11:30 PM