linus2k

君子常当当的博客

  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  41 随笔 :: 1 文章 :: 21 评论 :: 0 Trackbacks
构建MTA层邮件防火墙

不请自来的邮件,我们叫垃圾邮件,垃圾邮件的危害:
占用系统资源,包括硬盘空间和带宽
干扰合法邮件的递送
以第三方名义转发的垃圾邮件,会使宿主收到大量的退信和进入黑名单

MTA层邮件防火墙的特点
在垃圾邮件进入队列前,进行阻挡,把对系统的影响减少到最低限度
技术手段简单,效率高
只能阻挡特征比较明显的垃圾邮件
缺少容错性,要结合MDA层信件过滤技术,如:procmail,maildrop等

MTA层邮件防火墙机制
MTA层邮件防火墙基于UBE检查,通过对SMTP对话不同层面的逐一控制,从而起到阻挡垃圾邮件的目的,而阻挡作用是双向性的,如果你想发垃圾邮件的话,要赶快拆除防火墙,以下是防火墙不同层面的描述:
SMTP                     UBE                        功能
SERVER and CLIENT  smtpd_client_restrictions      连接的客户端主机名/地址控制
HELO                  smtpd_helo_restrictions      接洽控制
MAIL FROM            smtpd_sender_restrictions    发件人地址控制
RCPT TO              smtpd_recipient_restrictions  收件人地址控制
DATA                  smtpd_data_restrictions      DATA控制
SUBJECT              header_checks                信头过滤
正文                    body_checks                  正文内容检查

如何构建防火墙
方法一:在main.cf文件中编写规则
方法二:编制对照表
方法三:实时黑名单(RBL)

测试方法
postfix提供了一个参数,让你用来测试新限制条件:
  soft_bounce = yes
设定yes时,原本应该退信的动作,会改为将邮件放回队列,等待下次递送.在一段等待时间(1000s),让你有充足的时间来调整参数,然后重新发送.
再有就是打开日志功能,观测日志变化.

注意:
在测试时,如果服务器运行在本机上,不要使用telnet方式测试,telnet是以登陆本服务器上操作的方式,测试client是不起作用的.要运行客户端邮件程序来测试.
单独测试每一项规则,才知道因果关系.

编写main.cf文件
编写规则时,不一定要将规则分别设定给不同的参数下,可以集中在同一个参数下,任何限制条件都可以用于任何过滤规则,让你更加灵活地安排限制条件.

规则语法
规则是由permit_或reject_开头,不需要额外的自变量.permit是允许之意,reject是拒绝之意.而内容检查需要在对照表里使用正则表达式.

允许规则
permit_naked_ip_address
RFC要求客户端的HELO命令包含的ip地址放在方括号内,可以用此参数取消该限制。

permit_mynetworks
如果客户端的ip地址符合\$mynetworks参数定义的范围则接受该客户端的连接请求,并转发该邮件。

permit_auth_destination
permit_sasl_authenticated
仅仅中继通过SMTP认证的客户端邮件,以及接收本postfix为最后一站的邮件.SASL认证使用的选项.

DNS限制规则
DNS限制条件确认客户端所在的网络以及信封上的邮件地址,是否有可查验的DNS信息.
reject_unknown_client
当客户端接入后,即可获取其ip地址,postfix通过DNS查找客户端IP地址的PTR记录,不成功,立即拒绝服务.如果成功查出PTR记录,得出主机名称,再用此主机名称向DNS查相对应的IP地址,与先前所得的ip地址比较,相符后返回ok.
拒绝返回码:450.

reject_unknown_hostname
如果HELO命令提供的主机名称,没有A记录,也没有MX记录的,拒绝服务.拒绝返回码:450.

reject_unknown_recipient_domain
如果RCPT TO命令提供的收件人地址,其网域部分查不出有效的A或MX记录,拒绝服务.拒绝返回码:450.

reject_unknown_sender_domain
如果MAIL FROM命令提供的寄件人地址,其网域部分查不出有效的A或MX记录,拒绝服务.拒绝,返回错误代码为450.
MAIL FROM地址是退信通知的收件地址,捏造MAIL FROM地址是垃圾邮件发送者常用的伎俩.

常用的限制规则
reject_non_fqdn_hostname
reject_non_fqdn_recipient
reject_non_fqdn_sender
客户端提供的邮件地址不是完整形式(FQDN),拒绝服务.拒绝返回码:504.

reject_invalid_hostname
如果HELO命令所带的主机名参数不符合语法规范则,拒绝客户机的连接请求。拒绝返回码:501。

reject_unauth_pipelining
拒绝不经批准的流水线操作,pipeling是一种加速处理大宗邮件的技术.

reject_unauth_destination
如果收件地址不位于辖域,如relay_domains及其子域,$inet_interfaces、$mydestination
或$virtual_maps、$virtual_alias_maps等等,拒绝返回码:554.

编制访问表(access map)
涉及运用资料核对方式来验证的,使用对照表是一个好办法.access文件是进出postfix辖域的通行证,里面可以是ip地址,邮件地址,主机名,域名,等等,对应值是处理动作OK或REJECT等.access文件的范例:

#access list
sina.com      reject
tom.com          ok
192.168.0.2      reject
alange          reject
abc@example.com      reject
def@          reject

.......

记得每一次改动后,都要运行postmap来建数据库:
#postmap /etc/postfix/access

响应动作解释:
响应动作码为:OK,通过当前过滤规则的检查,继续检查下一组过滤规则.
响应动作码为UNNO,没有明确结果,所有规则结果都是DUNNO,默认收下邮件.
响应动作码为:REJECT,立即拒绝.
响应动作码为EFER,婉拒请求,客户端被告知稍后再试
响应动作码为:FILTER,将邮件转交给指定的内容过滤器.
响应动作码为:HOLD,将邮件放在保留队列,直到删除或释放给MDA处理.
响应动作码为ISCARD,收下邮件后立刻丢弃,慎重使用,暗自丢掉邮件是不道德的行为.

使用访问表
编辑main.cf文件,添加:
smtpd_client_restrictions = check_client_access    hash:/etc/postfix/access
                              check_helo_access     hash:/etc/postfix/access
                              check_recipient_access  hash:/etc/postfix/access
                              check_sender_access    hash:/etc/postfix/access

把所有匹配项:client_access ,helo_access, recipient_access, sender_access集中在一个access文件里,容易管理和操作,这样的限制是全方位的.
匹配规则:
设定了网址的,其所有子网都包含进去;
设定用户名为条件的,用户名匹配,即使域名不相同也是匹配;
完整邮件地址的要全匹配.

内容检查
内容检查是通过对邮件内容,包括标题和正文进行审核,是阻隔垃圾邮件最直接的手段,Postfix提供了四个检查邮件内容的参数:

参数                        功能
header_checks              检查标题
mime_header_checks       检查标题的MIME相关字段
nested_header_checks      检查夹带附件的标题
body_checks                检查邮件的正文

如何进行内容检查
内容检查的主要手段是使用正则表达式来寻找敏感字符(不区分大小写),检索特征放置在/.../之间,然后是要进行的动作.首先:
设定使用的正则表达式类型
regexp: Postfix的标准正则表达式语法
pcre: Perl兼容的语法

使用下列命令来查出可用的类型:
#postconf -m

修改文件main.cf,使得postfix支持内容检查,添加:

header_checks = regexp:/etc/postfix/checks
body_checks  = pcre:/etc/postfix/checks
body_checks_size_limit = 51200
#限制检查长度,是减轻系统负担的好策略,默认检查50k.

内容检查的响应动作
响应动作为:REJECT ,如果模式匹配成功,立即拒收邮件,并且将message-text内容传给客户端
响应动作为:WARN ,模拟拒收动作,不会真的拒收,只将message-text内容记录在日志文件中,并停止对比后续模式,方便测试之用.
响应动作为:IGNORE,删除符合模式的标题字段或整行文字.常用来删除包含内部网络信息,小心使用.
响应动作为:FILTER transport:nexthop,先将邮件排入队列,然后转交给指定的外部过滤程序.
响应动作为:HOLD,将邮件放在保留队列,直到删除或释放给MDA处理.
响应动作为:DISCARD,收下邮件后立刻丢弃,慎重使用,暗自丢掉邮件是不道德的行为.但另一方面,对付顽固不化的分子,退信,反而加大系统的负荷,干脆丢掉.

编写内容检查表
只要发现字段符合某正则表达式,整个对比过程就立刻结束,并执行对应的动作.如下是建立checks文件,这里的checks表同时使用在检查标题和正文的,既然是过滤关键字,就不论出现在那里了,维护管理起来会方便许多,范例:

#checks list
/abc/                              reject
/中文测试/                        reject
/^Subject: make money fast/     REJECT
/^To: friend@public\.com/        REJECT

.......

内容检查表不需用postmap命令来生成数据库,直接使用即可,但可以用postmap来测试规则,如下:
#postmap -fq "abc" regexp:/etc/postfix/checks
reject

整个文件来测试:
#postmap -fq - pcre:/etc/postfix/checks < inputfile

除了使用正则表达式以外,还能使用简单的条件判断,如:取反,多条件判断等,个人认为,不宜使用条件判断,编辑复杂的规则,还不如直接了当的找出关键字.详细信息参考手册: man regexp_table或 man pcre_table.

实时黑名单(RBL)
实时黑名单(Real-Time Blacklist ,RBL)是一种专为抵制垃圾邮件而设计的网络服务.让SMTP服务器通过DNS系统实时查询客户端是否为垃圾源.具体使用要联系服务提供商.选项有下:
reject_rbl_client rblprovider.domain
reject_rhsbl_client rblprovider.domain
reject_rhsbl_sender rblprovider.domain

实例:
main.cf文件(节选)
#SASL
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated permit_auth_destination reject
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous

smtpd_recipient_restrictions =
#PERMIT:
permit_naked_ip_address
permit_mynetworks
#DNS:
#reject_unknown_client
#reject_unknown_hostname
#reject_unknown_recipient_domain
#reject_unknown_sender_domain
#REJECT:
#reject_non_fqdn_hostname
reject_non_fqdn_recipient
reject_non_fqdn_sender
reject_invalid_hostname
reject_unauth_pipelining
reject_unauth_destination
#ACCESS:
check_client_access    hash:/etc/postfix/access
check_helo_access     hash:/etc/postfix/access
check_recipient_access  hash:/etc/postfix/access
check_sender_access    hash:/etc/postfix/access

#CHECKS:
header_checks = regexp:/etc/postfix/checks
body_checks  = regexp:/etc/postfix/checks
body_checks_size_limit = 51200

此文件要注意格式,属于smtpd\_recipient\_restrictions参数项,前面要有空格.checks不属于这参数项,而是main.cf的参数,所以前面不能有空格.

刚刚研究邮件系统,参考了<<postfix 权威指南>>一书,并稍稍做了一些实验,写下这篇的心得,欢迎指教
posted on 2009-06-25 15:07 君子常当当 阅读(404) 评论(0)  编辑 收藏 引用 所属分类: 邮件技术纪念记忆力衰退
只有注册用户登录后才能发表评论。