Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2343521
  • 博文数量: 535
  • 博客积分: 8689
  • 博客等级: 中将
  • 技术积分: 7066
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-26 10:00
文章分类

全部博文(535)

文章存档

2024年(4)

2023年(4)

2022年(16)

2014年(90)

2013年(76)

2012年(125)

2011年(184)

2010年(37)

分类: LINUX

2011-02-17 19:58:44





深入理解postfix



postfix 可以在内存有限的系统上执行,而不会影响其它服务的效能,这是因为 postfix 提供的内存管理功能非常有弹性,可以依据各种需求加以调整。

每封邮件用量限制

当 postfix 处理邮件时,必须将邮件暂存于邮件队列中,其中 maildrop 和 incoming 队列使用硬盘,而 active 和 deferred 则使用内存,每封暂存在队列中的邮件耗用多少内存是由邮件数据结构来决定,幸运的是这个数据结构的字段大小是可以微调的,透过这些微调就能决定 postfix 的最大内存用量了!

line_length_limit = 2048 从客户端接收待寄邮件时,每行最多 2 KB

header_size_limit = 102400 每封邮件的标头大小不得超过 100 KB

extract_recipient_limit = 10240     每封邮件的收信人字段不得超过 10 KB

message_size_limit = 10240000 每封邮件(包含信封)的大小,不得超过 10 MB

queue_minfree = 当内存剩下多少 Bytes 时,才可以处理下一封邮件,预设是没有限制。

bounce_size_limit = 50000 警告信的大小限制为 50 KB。

假设通通使用默认值,也就是所有参数都不设置,那么处理一封邮件须耗用 10.05 MB,再加上 postfix 模块程序的大小,总共约 20 MB,这也就是 postfix 运行的最小需求了!

邮件数量限制

当前述用量限制设置完毕后,接着我们还可以针对邮件队列一次要处理多少邮件作出限制,把每封邮件内存用量乘上邮件数量,就可以算出所需的内存总量,当内存足够时,我们当然希望尽可能多处理几封邮件来增进 postfix 的效能。

qmgr_message_recipient_limit = 1000   这个参数之前介绍过了,除了用来控制 dead 清单的大小外,也控制着处理中的邮件收信人总量,两者的预设限制都是 1000。

qmgr_message_active_limit = 1000    最多同时处理 1000 封邮件。

duplicate_filter_limit = 1000 在进行收信人过滤时,要快取多少已通过过滤的清单,这个功能是用来提高过滤效能,预设要快取 1000 个不同收信人

时间限制

postfix 某些模块在运作时,会依照设定档的要求读取外挂程序或是执行 shell 命令,有些则是会读取外部档案。如果无限制的让 postfix 等待外部命令执行完毕或等待外部档案读取完毕,将会因为这些外部程序的设计不当或 I/O 冲突,而导致 postfix 无法运作,因此就需要设定等候时间限制,超过此时间限制 postfix 将径行处理下一个程序。

举例来说:当 local agent 将邮件分到使用者信箱时,会透过 proxymap 模块读取 alias 数据库,接着根据 alias 设定读取 :include: 档案,最后读取 .forward 档案,前述动作中如果其中一个因为系统 I/O 忙碌无法于时间限制内读取档案,local agent 就会直接跳过进行下一个处理动作。

command_time_limit = 1000s    等候外部命令或 I/O 的时间不可超过 16 分钟。

service_time_limit =    这个参数的目的是允许不同 service 采用不同时间限制,因此它会取代前述参数的设定,其中 service 就是 master.cf 中的第一个字段。

档案锁定

当 local agent 要将信件分到使用者信箱时,有时候使用者正透过 POP3 读取信箱,因此信箱被锁定无法开启,这种情况发生时,local agent 必须等候一段时间重新尝试读取档案,但也不能一直等下去,所以必须要有一些限制。

postfix 支持两种的档案锁定机制:一、使用系统函式 fcntl( ) 或 flock( ),二、使用 local file,postfix 将根据操作系统的不同,选择其中一种或两种并用。有关档案锁定机制在这里不予讨论,有兴趣的读者可以从「专业 Linux 程序设计」(Wrox 出版,碁峯翻译经销)一书一窥究竟。

deliver_lock_attempts = 5    档案被锁定时,尝试读取 5 次。

deliver_lock_delay = 1s   每次尝试读取前,先等候一秒钟。

stale_lock_time = 500 当 lock file 存在超过 500s 时,强制删除 lock file 解除其锁定状态。使用 lock file 其实是透过程序设计技巧来仿真档案锁定功能,它必须由程序设计师自行维护锁定状态,万一有粗心的设计者锁定档案后忘记解除,或是程序当掉无法解除锁定,都 会造成档案长期被锁定的假象,所以需要此设定来排除问题。

行程自动回复

当行程或子执行绪因为某些原因当掉,例如:内存不足......等,这个时候 master 将会延迟一段时间后尝试重新启动该行程。当然,如果程序当掉的原因是 main.cf 档案损毁所造成的,就算是不断重复启动也不能恢复正常,因此 postfix 也会将当掉的情形纪录在系统日志里,以便管理员侦错并人工修复。

fork_attempts = 5 行程当掉以后,会尝试重新启动它 5 次!

fork_delay = 1s    每次重新启动前,先等候一秒钟。

transport_retry_time = 60s qmgr 每隔 60 秒尝试驱动 agent 进行分信。



柒、邮件地址改写机制 vs 相关设定档

当 cleanup 模块进行邮件过滤之前,会先依据各种设定文件呼叫 rewrite 模块,进行邮件地址改写,这样做的好处是可以减少标头字段的变化,使得过滤快取(请参考 duplicate_filter_limit 的说明)能更有效率的工作。

邮件地址改写的顺序如下:

将 @hosta,@hostb:user@site 改写成 user@site    postfix 不支持前面那种特殊写法

将 site!user 改写成 user@site 将 UUCP 格式改写为现在使用的地址格式

将 user%domain 改写成 user@domain     将 % 符号去掉

将 user 改写成 user@$myorigin    从 local 寄出的信会缺少网域名称,在此补上

将 user@host 改写成 user@host.$mydomain 将 hostname 改成 FQDN 型式

将 user@site. 改写成 user@site 去掉绝对网域名称后面的小数点

根据各种设定文件改写邮件地址:alias、canonical、virtual。

alias、canonical、virtual 等设定档是为了达成某些特殊功能而设计的,底下说明这些设定文件的功能以及如何启用它们:

别名对应

alias 是 sendmail 最被广泛使用的一项功能,除了用来对应虚拟信箱外,也可以运用在邮递清单或邮件讨论群组上面,由于 postfix 在这部分完全与 sendmail 兼容,因此我们就不再讨论它,详细应用方法请参考 Linux 系管师进阶班讲义 一文。

请在 main.cf 中加入这一行,以便启用 alias:

alias_maps = hash:/etc/aliases

如果您的系统仅支持 dbm 格式的别名,或是透过 NIS 服务器查询别名,请使用底下的参数:

alias_maps = dbm:/etc/aliases, nis:mail.aliases

全名对应

这个设定档用来建立使用者全名与账号的关系,例如:

[email]shane@mail.spps.tp.edu.tw[/email] [email]shane.lee@mail.spps.tp.edu.tw[/email]

如果网域名称,已经设定在 $myorigin、$mydestination 或 $inet_interfaces 中就可以省略不写,直接使用底下的语法:

shane shane.lee

此外这个设定档还有一个用途,就是当网域迁移时,可以将信件对应到新的网域名称,例如:

@mail.spps.tp.edu.tw @tp.edu.tw

当本机是 mail gateway 时,透过底下的设定可以得知哪些使用者是位于哪一台邮件主机上,分信时会分给该主机,而非分到本机的 /var/spool/mail 中:

shane @stu.spps.tp.edu.tw(账号相同时)

shane [email]s60101@stu.spps.tp.edu.tw[/email](账号不同时)

当设定档输入完成后,必须先将它杂凑成数据库文件,以 btree 为例(与 sendmail 兼容,但效能较差,建议改用 hash):

postmap btree:/etc/postfix/canonical (档名可随个人喜好更改)

接着在 main.cf 中加入底下这一行:

canonical_maps = btree:/etc/postfix/canonical

如果只想对应收信人字段则将该行,取代成:

recipient_canonical_maps = hash:/etc/postfix/recipient_canonical

如果只想对应寄信人字段则将该行,取代成:

sender_canonical_maps = hash:/etc/postfix/sender_canonical

虚拟对应

虚拟对应仅能作用在信封里的收信人字段,而不会去改写邮件标头,与全名对应相比较,虚拟对应的功能只能算是半套。虚拟对应一般应用在两种场合:一、将收信人字段中的全名改成账号名称,二、虚拟网域对应。想启用虚拟对应,请在 main.cf 中加入底下这一行:

virtual_maps = btree:/etc/postfix/virtual

至于虚拟对应的设定方式与全名对应相同,请自行参考前面小节的介绍。

使用者迁移

当使用者已经不再使用此信箱,而改用其它服务器提供的信箱时,并无法通知所有的亲朋好友,因此仍然会有不知情的寄信人寄信过来,这些邮件到底该如何处理呢?

首先使用者可以在自己的家目录里,建立 .forward 档透过这个档案将邮件转寄到新的信箱,管理员也可以透过 alias 别名对应帮该名使用者转信。虽然这样做很人性化,但也有两个缺点:一、转信会增加 postfix 处理邮件的负担,导致效能降低,二、亲朋好友并不知道要把信寄去哪里才对,所以不断地麻烦我们!

另一种处理的方法是不要替已经搬走的使用者转信,而直接告诉对方该寄去哪里才对,如果管理员也不清楚新的邮件地址,直接告诉对方不要再寄信过来也可以,使用这个功能请在 main.cf 加入:

relocated_maps = hash:/etc/postfix/relocated

/etc/postfix/relocated 的设定范例如下:

shane 使用者 shane 已经不再使用此信箱了,请将信寄到 tp.edu.tw 主机,新账号是 sean!

在提示讯息中,我们不使用 @ 符号([email]sean@tp.edu.tw[/email])是为了避免被信箱收集者卖给广告商。

邮件绕送路由

transport_maps 允许我们直接将符合条件的邮件,透过特定的方式,传送到特定的主机,而不需要依靠 DNS MX 纪录,譬如前面已经介绍过的延迟传送机制外(给拨接用户使用的),要启用 transport 功能,请在 main.cf 加入:

transport_maps = hash:/etc/postfix/transport

底下是 transport 设定文件的应用范例,意思是要将寄给 @spps.tp.edu.tw 网域的信件,传送到 172.16.1.6 这台主机的 8025 port:

spps.tp.edu.tw smtp:[172.16.1.6]:8025

应用场合

优秀的管理员明白各种设定档各有职司,就算功能可以互相取代,也不应该混合着用,例如:用全名对应机制作别名对应,用别名对应机制作虚拟对应......这样作恐怕没有人可以厘清其逻辑关系,将来要如何维护呢?

到底什么情况下要用哪一种机制来实作呢?笔者给大家的建议是:

将寄信人账号对应成全名 sender_canonical_maps = hash:/etc/postfix/sender_fullname

将收信人全名对应成账号 virtual_maps = hash:/etc/postfix/recipient_loginname

网域名称迁移    canonical_maps = hash:/etc/postfix/domain_canonical

使用者迁移 relocated_maps = hash:/etc/postfix/relocated

将寄给本机账号的信件分到其它服务器 canonical_maps = hash:/etc/postfix/individual_user

将寄给虚拟网域的邮件转给真实存在的网域 virtual_maps = hash:/etc/postfix/virtual_domain

让使用者登入后能改用虚拟信箱寄信    smtpd_sender_login_maps = hash:/etc/postfix/unaliases

将寄给虚拟信箱的邮件转给真实存在的使用者    alias_maps = hash:/etc/aliases

将邮件导向某台邮件过滤或扫毒主机    transport_maps = hash:/etc/postfix/transport



捌、SpamAssassin

SpamAssassin 是一套用来协助过滤垃圾邮件的程序,它会针对信件中特定的比对样式给予不同的分数,当分数超过指定的值后,该封邮件就会被当作垃圾邮件处理,处理方式依据设定的不同,会在信件标头或邮件主旨字段加入警告讯息。

SpamAssassin 必须结合 MTA 来使用,单独执行并不能发挥其功效,由于该程序是使用 perl 语言开发,因此如果刚开始安装 Linux 操作系统时没有一并安装,事后要补装有一点小麻烦,安装所需的套件如下(省略版次号码,请自行按 TAB 补字,依顺序安装),这些 RPM 档案可以从 RedHat 光盘取得:

perl

perl-Time-HiRes

perl-Digest-HMAC

perl-Net-DNS

spamassassin

安装好之后,请以下列指令启动 spamd:

service spamassassin start

并将该服务设定为开机自动执行:

chkconfig --level 3,5 spamassassin on

请用底下指令,测试程序能否成功执行:

spamc -c < /var/mail/username

假设该使用者信箱已经有至少一封邮件,这时 spamc 程序会将该邮件传送给 spamd(127.0.0.1:783)进行评分,如果执行成功应该会看到 SpamAssassin 的评分,例如:

3.5/5.0

让 postfix 使用 SpamAssassi




深入理解postfix

时间 : 2009-03-14  作者:匿名   编辑:sky 点击:  208 [ 评论 ]

-
-

n 过滤邮件

确定 SpamAssassin 可以正常执行之后,接着设定 /etc/postfix/master.cf,请修改 smtp deamon 服务的设定:

smtp inet ............中间五个字段不用修改............. smtpd -o content_filter=spamfilter:

这一行的意思是要求 smtpd 在进行完邮件过滤后,透过 spamfilter 服务进行邮件全文过滤,因此我们还得定义 spamfilter 这个服务(服务名称可以自行修改):

spamfilter unix - n n - 100 pipe   flags=Rq user=nobody   argv=/usr/sbin/spamc.sh -f ${sender} -- ${recipient}

这里定义 spamfilter 服务使用 unix socket 执行,最多同时进行 100 封信的过滤(如果内存不足请自行修改数量),过滤方式是透过 pipe 模块以 nobody 身分启动 /usr/sbin/spamc.sh ,并且将目前队列中的邮件其数据结构中的 sender 和 recipient 参数读出来,连同 -f 参数传递给 spamc.sh 当作参数。旗号 R 表示要把信封中的寄信人地址,以 Return-Path: 标头插入邮件中。旗号 q 表示参数中的特殊字符要用单引号括住,以避免被当成控制字符处理,在这个例子中用来避免邮件地址中的 @ 符号被当成控制字符。

接着我们还得自己写一支小小的 shell script,底下就是 /usr/sbin/spamc.sh 的内容(这个档案须自己建立,之所以放在 /usr/sbin/ 是因为这个数据夹的权限比较严格,也比较安全):

#!/bin/sh

/usr/bin/spamc -t 30 -e /usr/sbin/sendmail -i "$@"

不要忘记将该程序的档案权限改成 755。pipe 模块传递参数给上面这支程序时,会将整封邮件的内容放在键盘的 input 队列中,所以我们使用 sendmail -i 这道指令将邮件从 input 队列读进来,"$@" 会被 spamc.sh 的参数宏取代,也就是说 "$@" 会变成

-f [email]sender@sender.doma[/email]in -- [email]recipient@recipient.doma[/email]in

这个字符串将当成参数传递给 sendmail 程序,意思是要 sendmail 把参数传递进来的「寄信人地址 -- 收信人地址」写在信封的寄信人字段里。 mail from: 与 rcpt to: 原始参数的取得,是由 smtpd 于建立 SMTP 联机时,将该字符串撷取出来放在邮件队列的数据结构中,当 master 唤醒 spamfilter 服务时,透过 pipe 当白手套,把邮件数据结构中的字符串传递给 spamc.sh 再传递给 sendmail。透过这些程序的接力表演,现在终于可以把这两个参数当作过滤的键值。

附带一提:如果本机没有安装 SpamAssassin,想要透过别台主机安装好的 SpamAssassin,这时候可以修改 spamc.sh:

/usr/bin/spamc -d 172.16.1.6 -p 783 -t 30 -e /usr/sbin/sendmail -i "$@"

使用这个方法前,请先确认从本机到过滤主机之间的防火墙已经放行 783 port。

删除可疑的垃圾邮件

SapmAssassin 发现垃圾邮件的可疑对象时,会加入一个邮件标头,至于要不要把信删除,则不关它的事。我们可以透过 header_checks 机制(前参照第肆章 UCE 过滤的说明)把具有 SPAM 标头的邮件删除,然而这样做是有风险的,万一有些普通信件因为长得太像垃圾信而被标示为   SPAM,那就会一起被删除!

如果你真的想删除可疑邮件,请修改 main.cf 设置下列参数:

header_checks = pcre:/etc/postfix/header-checks

找到 /etc/postfix/header-checks 档案,如果档案不存在请自己建立,加入底下这一行:

/^X-Spam-Flag: Yes/ DISCARD

垃圾邮件经验学习法

SpamAssassin 判断一个档案是否为垃圾邮件,是透过邮件特征比对 hits 比率(原理有点像 proxy server),也就是说必须使用一段时间后,才能从经验中学习到哪些邮件内容反复不断出现,而要学会哪些邮件是垃圾邮件,最有效的方法是透过一个垃圾信 箱来学习,首先我们建立一个没人使用的信箱,接着以此信箱为名义在 news server 上发表测试文章。

等几天后,很快的就有一大堆垃圾信涌入该信箱,现在我们只要把信喂给 SpamAssassin 就行了,底下是透过 alias 来喂信:

fakeuser: "| /usr/bin/spamassassin -r -w fakeuser"

上面这个范例中,指令参数 -r 的意思是要 SpamAssassin 把所有邮件的寄信人信箱当成垃圾信的样板,从此以后符合此样板的邮件都会被认为是垃圾信。-w fakeuser 是一个非必要参数,SpamAssassin 将会以 fakeuser 信箱的名义寄警告信给对方,但是因为对方使用伪装过的信箱,因此也没有人会收到警告信,寄了也是白寄,建议不要使用此功能。

除了透过 alias 可以喂信给 SpamAssassin 外,我们也可以利用 .forward 来喂信,请在 fakeuser 的家目录建立此档案,档案内容如下:

| /usr/bin/spamassassin -r -w fakeuser

决定 SPAM 过滤门坎

SpamAssassin 根据邮件比对的得分高低,来决定该邮件是否为垃圾信,默认值是 5 分,建议修改为 9 分。请修改 /etc/mail/spamassassin/local.cf:

required_hits 9.0

白名单与黑名单

SapmAssassin 维护一个邮件数据库,该数据库将透过自动学习机制来增减邮件的分数,分数高于门坎的称之为黑名单,分数低于门坎的称之为白名单,一旦某种特征的邮件被评为 黑名单,以后该信箱寄出的邮件都会被认为是垃圾邮件,虽然自动学习机制对于主动发现垃圾邮件很有用,但难免也有误判的时候,这个时候我们可以透过以下命令 来调整:

/usr/bin/spamassassin -W < message 将该邮件加入白名单

/usr/bin/spamassassin --add-to-blacklist < message     将该邮件加入黑名单

/usr/bin/spamassassin -R < message     将该邮件移出白名单

/usr/bin/spamassassin --add-addr-to-whitelist=mailbox    将该信箱加入白名单

/usr/bin/spamassassin --add-addr-to-blacklist=mailbox 将该信箱加入黑名单

/usr/bin/spamassassin --remove-addr-from-whitelist=mailbox     将该信箱移出白名单

当某个信箱被误判为垃圾邮件,这时我们可以直接将该信箱加入白名单,例如:

/usr/bin/spamassassin --add-addr-to-whitelist=shane@mail.spps.tp.edu.tw

该信箱一旦加入白名单后,只能以手动方式移出或重新加入黑名单。如果要把具有某种特征的邮件加入白名单(例如:校内邮件讨论群组、校园电子报、网站更新通 知......等,这类邮件经常被视为垃圾邮件),请先将该封邮件另存成纯文字文件,接着将该信喂给 SapmAssassin 即可,请使用底下指令:

/usr/bin/spamassassin -W < myletter.eml


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

chinaunix网友2011-03-05 16:48:27

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com