Chinaunix首页 | 论坛 | 博客
  • 博客访问: 511597
  • 博文数量: 53
  • 博客积分: 2265
  • 博客等级: 大尉
  • 技术积分: 574
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-15 16:50
文章分类

全部博文(53)

文章存档

2019年(1)

2018年(2)

2016年(2)

2015年(1)

2014年(6)

2013年(5)

2012年(7)

2011年(16)

2010年(13)

分类: BSD

2011-09-26 15:16:14

Fighting spam with exim4

This article describes some spam fighting techniques for the MTA (Mail Trading Agent). All examples have been tested on a Debian system, which will make the tips more Debian-centric, but the concepts are general and it would be easy to implement the same hooks on a different distribution.

Many of the settings in this article are based on the assumption that mail from untrustworthy sources or from poorly configured mail hubs should not be accepted. This may be unacceptable for a big company, but if you are in the lucky situation to be able to reject those mails, then this article might be of interest.

Index RCPT Checks

The default Exim4 (Debian) configuration file contains some very useful examples which just need to be enabled or customised. I will name a few of them here. Please note that many of these checks require additional DNS lookups so please be prepared to a slowdown of the SMTP session.

Sender Verification

A very simple way of detecting spam is to verify if the sender's mail address is valid. Exim4 checks only if the given local part accepts mail. This means, for a given address, e.h. "kasperl@example.com", Exim4 checks only if the domain "example.com" is able to accept mail (i.e. has a valid MX record) bot does not check if the address gets accepted by the remote mailer. (This verification is called outcall by Exim4, can consume a lot of resources and is disabled by default.

There are many different types of Sender verifications. If enabled in the access control lists section of the config file, then different kinds of sender verification will be done on the message.

The sender condition in the acl_check_rcpt ACL checks if the e-mail address in the RCPT TO: command is valid, while the header_sender condition in the acl_check_data ACL checks if the header of the mail contains a valid Sender:, Reply-To: or From: line.

acl_check_rcpt:

#...

deny message = Sender verification failed

!verify = sender

acl_check_data:

#...

deny message = No verifiable sender address in message headers !verify = header_sender

If you are using Debian's exim package, then you just need to define the following lines at the top of your exim config file:

CHECK_RCPT_VERIFY_SENDER = yes CHECK_DATA_VERIFY_HEADER_SENDER = yes

If you have split config files, then create a new file, e.g. /etc/exim4/conf.d/main/00_local_options with the above content.

DNS Blacklists

(DNSBL) are a neat way of getting rid of notorious spammers. After a connection on port 25 from a host, the MTA checks one or more servers via a standard DNS query if the connected IP address is listed. The queried RBLS server replies either with a DNS fail (IP address not listed) or with a IP address (IP Address listed). It is safe to reject mails permanently (i.e. with 550 error message) a from listed servers, but a reasonalble error message should be sent as well in order to give the sender a clue why his message has been refused.

DNSBLs are enabled in Exim4 as access control lists. This list should be placed after cheaper tests, in order to reduce network overhead.

acl_check_rcpt:

#...

deny 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)

dnslists = >

If you are using Debian's exim package, then you just need to define the following line:

CHECK_RCPT_IP_DNSBLS = >

There are many blacklist hosts out there. See for example or .

Reverse DNS Verification

An other simple sanity check is the so called DNS verification. The idea is to check the DNS name from the IP address. If there is no DNS name, then the likelyhood that the sending host is a legitimate mail server is very low.

This ACL just warns if Exim4 was unable to determine the sending hosts's name:

acl_check_rcpt:

#...

warn message = X-Host-Lookup-Failed: Reverse DNS lookup failed for $sender_host_address \ (${if eq{$host_lookup_failed}{1}{failed}{deferred}})

condition = ${if and{{def:sender_host_address}{!def:sender_host_name}}\ {yes}{no}}

In a Debian config file this check can be enabled with the following line:

CHECK_RCPT_REVERSE_DNS = yes SpamAssassin

In order to set up SpamAssassin, you need to set the spamd_address option in the main configuration. The following configuration is suitable for most hosts where SpamAssassin runs on the same host as Exim4.

spamd_address = 127.0.0.1 783

The next thing is to set up an ACL for spam:

acl_check_data:

#...

warn message = X-Spam-Score: $spam_score ($spam_bar)

spam = nobody:true warn message = X-Spam-Report: $spam_report

condition = ${if >{$spam_score_int}{5}{1}{0}} spam = nobody:true

This example does not reject spam messages, but flags them. This way the user can decide what to do with the spam, e.g. he or she can use the appropriate filter mechanism of his or her mail user agent.

Address Rewriting

With address rewriting it is possible accept mail for a local part with a fixed first hald and an arbitrary second. This is useful when untrustworthy sites requires a registration and you don't want to generate a new alias just for that site. With the following configuration as many one-time mails can be used as desired.

begin routers

#...

suffix_rewrite:

driver = redirect allow_defer

allow_fail

skip_syntax_errors

data = }

 local_part_suffix = "+*" retry_use_local_part

  retry_use_local_part

The effect of this router is that everything after a + character is removed from the local part and Exim4 tries to route the resulting address again.

Note that Exim4 supports the local_part_suffix and local_part_suffix_optional options for the same goal, but I find the above way more flexible.

SPF—Sender Policy Framework

(see also the article on ) is an experimental which aims to address sending of forged e-mail addresses. It gives domain owners the possibility to specify the hosts that are allowed to send mails for that domain. To some extend this approach bastardises the concept of SMTP, but I think it is a fair approach to limit spam. And the best of it is that it is a true opt-in approach: nobody is forced to use SPF nor to publish an SPF record in its DNS. And you can enable SPF checks without publishing one yourself.

This configuration is taken as-is from Debian's config file (Debian users have just to set the CHECK_RCPT_SPF macro):

acl_check_rcpt:

 #...

# Use spfquery to perform a pair of SPF checks (for details, see
# )
# # This is quite costly in terms of DNS lookups (~6 lookups per mail). Do not
# enable if that's an issue. Also note that if you enable this, you must
# install "libmail-spf-query-perl" which provides the spfquery command.
# Missing libmail-spf-query-perl will trigger the "Unexpected error in
# SPF check" warning.
deny message = [SPF] $sender_host_address is not allowed to send mail from \ ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}}. \ Please see
log_message = SPF check failed.
condition = ${run{/usr/bin/spfquery --ip \"$sender_host_address\" \ --mail-from \"$sender_address\" --helo \"$sender_helo_name\"} \ {no}{${if eq {$runrc}{1}{yes}{no}}}}


defer message = Temporary DNS error while checking SPF record. Try again later.
condition = ${if eq {$runrc}{5}{yes}{no}}

warn message = Received-SPF: ${if eq {$runrc}{0}{pass}{${if eq {$runrc}{2}{softfail}\ { ${if eq {$runrc}{3}{neutral}{${if eq {$runrc}{4}{unknown}\ {${if eq {$runrc}{6}{none}{error}}}}}}}}}}
condition = ${if <={$runrc}{6}{yes}{no}}

warn log_message = Unexpected error in SPF check.
condition = ${if >{$runrc}{6}{yes}{no}}
# Support for best-guess (see http://www.openspf.org/developers-guide.html)

warn message = X-SPF-Guess: ${run{/usr/bin/spfquery --ip \"$sender_host_address\" \ --mail-from \"$sender_address\" \ --helo \"$sender_helo_name\" --guess true}\ {pass}{${if eq {$runrc}{2}{softfail}{${if eq {$runrc}{3}{neutral}{${if eq {$runrc}{4}{unknown}\ {${if eq {$runrc}{6}{none}{error}}}}}}}}}}
condition = ${if <={$runrc}{6}{yes}{no}}

defer message = Temporary DNS error while checking SPF record. Try again later.
condition = ${if eq {$runrc}{5}{yes}{no}} Links

describes similar techniques as this page. explains the setup of Exim4 with SpamAssassin in more detail.

阅读(1294) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~