postfix 最被人称道的地方在于配置文件的可读性很高 (当然是跟 sendmail 比 ),而在主要配置文件 main.cf 中,需要自行定义的东西并不多,而且这些参数就算不去定义,依照默认值也可以运作:

☛ 由本機寄出的郵件要使用哪個網域名稱

在 sendmail 中,这个功能称为域伪装,也就是说可以和主机名不同,例如:本机名称为 mail.spps.tp.edu.tw,而寄出的邮件其寄信人字段则可以使用 spps.tp.edu.tw。 ( 须配合 DNS MX 日志使用 )

myorigin=spps.tp.edu.tw

不使用简略名称时,设置如下:

myorigin=mail.spps.tp.edu.tw

由于主机名和域名会被反复引用在不同设置值,为了简化设置,通常是定义为变量:

myhostname = mail.spps.tp.edu.tw
mydomain = spps.tp.edu.tw

#myorigin=$mydomain
myorigin=$myhostname (省略时,视同此设定)

当然以上变量也可以省略不定义,这种情况下 postfix 将使用 gethostname() 函数获取系统设置。 如果是将 myorigin 省略,则视同为设定 $myhostname。

另外,如果本地是某个域的 mail gateway,也就是说域内的所有邮件服务器,都必须把它们的邮件送到本地来处理,这种情形可以使用 masquerade_domains 让 postfix 自动缺省寄信人字段中的邮件主机名,例如:

masquerade_domains = $mydomain

假设$mydomain 是 spps.tp.edu.tw,则无论信件是来自 stu.spps.tp.edu.tw 或 mail.spps.tp.edu.tw 都将会被改写成 spps.tp.edu.tw。

如果你有某些账户不想要让 mail gateway 改写发件人栏段,可以设置底下的参数 ( 默认不启用 ):

masquerade_exceptions = root

启用 masquerade_domains 功能只会改写邮件头与信封里的发件人栏段,如果想要将收信人栏位一并改写,可以设置底下的参数:

masquerade_classes = envelope_sender, envelope_recipient, header_sender, header_recipient

注意:这样做将使得 mail gateway 无法寄信给下属邮件服务器,因为收信人字段 @ 后面的邮件域名会被改写成 mail gateway 自己。

☛ 要接收来自哪些网络界面的邮件

底下参数是用来定义要处理来自哪些网络界面的邮件,当未定义时,默认会处理本机所有网卡 (可以使用 ifconfig 观察 ),如果定义成 localhost ,则只有 loopback 界面会接受邮件,也就是说只接受主控台或 WEB 界面寄出的邮件,不接受 MUA ( outlook express ) 递交的邮件:

inet_interfaces = localhost

设置成 all ,表示接受所有网络界面的邮件,这是默认值:

inet_interfaces = all

设定成 $myhostname,表示要透过 DNS 反查IP,当本机 IP 是由 DHCP 指派,而 DNS 又未被设定成 DDNS,将会出现不可预期的错误!

inet_interfaces = $myhostname

底下范例将会在有 DNS A 记录的 IP 以及 loopback 界面上提供服务,在这里我们可以发现 main.cf 中有许多设定可以设定超过一个值,将它们用逗号区隔开来就行了!( 底下的设置示例不适用于 postfix 本身兼 Proxy/NAT 的场合 )

inet_interfaces = $myhostname, localhost

☛ 哪些域的邮件是给本地的

定义在这里的域将被视为是 local 域,换句话说寄到这些域的邮件,会被接收并分信给本地用户,相当于 sendmail 中的 local-host-name,当不使用 DNS MX 记录时,设置如下:

mydestination = $myhostname localhost.$mydomain

如果有使用 DNS MX 日志,需修改为:

mydestination = $myhostname localhost.$mydomain $mydomian

假设该服务器在 DNS 上有多笔 A 或 CNAME 记录,则须将这些记录也写上去, 例如:

mydestination = $myhostname localhost.$mydomain $mydomian www.$mydomain ftp.$mydomain

☛ 哪些邮件要进行 relay

在 postfix 中针对转信网域作处理的参数有两个,一是用来定义区域网络网段的 mynetworks,另一个是 relay_domains,未被定义在这些参数里的域,系统将拒绝转信!

首先说明区域网络网段设定,相关参数共有两个:mynetworks_style 和 mynetworks,前者用来宣告区域网络类型,subnet 代表是子网络,这也是预设值,当未作设定时,postfix 将会自行根据 ifconfig 上登记的 IP 和 网络屏蔽作运算,自动求出子网络的范围;如果设定成 class,则是不理会屏蔽,自动信任同一个 class 等级的电脑,如果该服务器使用拨接上网,这样设定将使得同一家 ISP 的拨接用户,都可以利用本服务器转信,这是非常危险的 ( 除非你是 ISP 公司 );设置成 host 则仅该单机可以寄信。

#mynetworks_style = class
#mynetworks_style = subnet
#mynetworks_style = host

mynetworks 用于设置区域网络的 IP 范围,刚才设定的 mynetworks_style 将会被此参数取代,如果省略不设置,则由 mynetworks_style 来决定要 binding 的网卡:

mynetworks = 168.100.189.0/25

mynetworks = 168.100.189.10

除了上面范例,设定成网段或单机外,也可以指定多个网段 ( 多重 NAT 网域时 ),或是使用配置文件 ( 条列式 ),或使用杂凑表 ( makemap hash 或 postmap hash:)。

#mynetworks = 168.100.189.0/28, 127.0.0.0/8
#mynetworks = $config_directory/mynetworks
#mynetworks = hash:/etc/postfix/network_table

有关转信网域设定,以上两个参数就已经足以应付各种需求,但为了与 sendmail 兼容,仍然保留 relay_domains 设定,与 sendmail 不同的是,如果该 relay_domain 在 DNS 上有定义 MX 纪录,将会被 postfix 故意忽略,而当成 mynetworks 来处理,这是为了避免被利用作为广告信回信站台;relay domain 对 sendmail 而言是双向的,但对 postfix 而言则是单向的,只能寄信,而且不代收回信,因此如果要将本地设定成 mail gateway,请使用 mydestination,而不要使用 relay_domains ( 注意:很多介绍 postfix 的文章都犯此错误! ) 建议不要设置此参数,使用预设值「不启用」。

#relay_domains = $mydestination

当本机为某台 mail gateway 的下属服务器时,必须要将所有寄出的信件交给 mail gateway 代转,这时可以设定 relayhost 为该 mail gateway 的 IP。 默认不启用。

#relayhost = $mydomain
#relayhost = mg.spps.tp.edu.tw
#relayhost = [172.16.1.7]

☛ 哪些情况须通知管理员

所谓管理员是指 postmaster 信箱,请修改 alias 设定将 postmaster 对应成管理人员真正使用的信箱,以免警告邮件没人理会堆积在服务器上。

notify_classes参数用来决定哪些情形下须通知管理员,默认值如下:

notify_classes = resource, software

可以使用的参数包含:

bounce 当一般邮件无法交递时,产生警告信给管理员 ( 会附上原始邮件的内文 )。 注意:邮件无法交递时,本来就会寄警告信给发信人,管理员收到的不过是复制版本。
2bounce 当寄给发信人的警告信无法交递时, 产生警告信给管理员。
delay 当对方站台忙碌要求延迟递送时,产生警告信给管理员 ( 不会附上原始邮件 )。
policy 对方寄信的要求因为不符合安全规范已经被回绝 ( 被规则过滤掉 ),此时会产生警告信给管理员。
protocol 通讯协议错误时产生警告信通知管理员,我们比较感兴趣的是对方使用了哪些不合法的 SMTP 命令。
resource 系统资源短缺导致信件无法寄出,例如:硬盘 I/O 错误,此时会产生警告信给管理员。
software 软件安装不全或程序错误造成的问题,产生警告信给管理员。

 

☛ Proxy/NAT 地址

当邮件服务器位于 proxy 或 NAT 防火墙的后方时,此参数用来配置真实 IP,以避免因为 MX 纪录与本机 IP 不同,将该信误判成需 relay 到其它 MX 的邮件;当本机所查询的 DNS 其回复 MX 记录为虚拟 IP 时,此种现象将不会发生,因此在 NAT 虚拟网域中,架设内部专用 DNS 是非常重要的,默认值为 :

proxy_interfaces =

当本机被设定成其它网域的备份 MX 时,如果未设置此参数,邮件会成为服务器间互踢的皮球 ( 去询问其它网域的 DNS 查询 MX 纪录时,查到的必然是真实 IP,即使有架设内部专用 DNS 也没用 )。 设置如下 :

proxy_interfaces = 163.21.166.7

☛ main.cf UCE ( unsolicited commercial email ) 过滤

过去这类的邮件被称为垃圾邮件,比较正式的称呼是 SPAM 邮件,postfix 则称此种邮件为 UCE,有那么一点缩小打击范围的含意,因此使用 UCE 过滤并无法解决其它问题邮件 ( 例如:匿迹邮件、病毒邮件、邮件炸弹 ) 所带来的困扰,请不要期望过高。

尽管如此,与 sendmail 使用 access 来进行存取控管相比较,postfix 的 UCE 过滤显然要精细得多,弹性也比较好,以外挂方式读取过滤规则使得管理员能随时修改设定,并将它模块化,可以说是 postfix 最大的优点。

如前所述,postfix 并不使用复杂的宏语言来进行规则运算,而是采用较为单纯的查表法来控制,但各位可不要小看它,它所支持的查表方式可谓琳琅满目,诸如:字段比对 ( 纯文字文件,字段以逗号或空格或定位点区隔 )、DBM 检索、HASH 杂凑、NIS 查询、RBL 查询…..等,比对规则也可以选择采用正规表示法 ( regexp ) 或是 perl 改良过的正则表示法 ( pcre )。

☛ 邮件标头过滤

标头过滤所过滤的对象,除了邮件信头外,更扩大范围到附加档案的 MIME 标头,使得过滤可以更精确的进行,而不会因规则过于模糊,殃及无辜的邮件。 用过 procmail 的用户要特别注意:附加文件文件名或文件类型是在此过滤,而非在邮件内文过滤。 设置方式如下:

header_checks = regexp:/etc/postfix/header_checks
header_checks = pcre:/etc/postfix/header_checks

在外挂配置文件 header_checks ( 可以改用其它文件名 ) 中,当字符串比对命中时,可以采取各种处理动作,包括:

REJECT 拒收信件。
OK 跳过符合条件的信头不作后续检查,在 sendmail 中一旦 OK 该信件就会被接受,但在 postfix 中,OK 仅用来跳过该标头的后续比对,万一有其它标头被拒绝,该封邮件一样会被拒绝。
IGNORE 从邮件删除该头。
WARN 附加警告讯息。
HOLD 放回队列,等候处理。
DISCARD 直接将邮件丢弃,不回应拒收讯息。
FILTER transport.nexthop 呼叫插件,进行邮件内文剖析过滤。 插件可以是任何一种可执行的文件,例如:shell script。 该程序必须先定义在 master.cf 中,模拟成一个 socket 来执行(由 master 模块负责伺服监听),当需要呼叫它执行时,postfix 中的 clearup 模块会将整封邮件丢到指定的 port 号,master 模块监听到讯息后会执行相对应的过滤程序。

 

header_checks的示例:

/^Subject: Make Money Fast/ REJECT
/^To: friend@public.com(link sends e-mail)/ REJECT

如果未设置此参数,则邮件信头过滤功能将会关闭不启用,这是系统预设值。

☛ 邮件内文过滤

这是用于过滤所有信头过滤没有检查到的邮件内容,设置方式和前面相同:

body_checks = regexp:/etc/postfix/body_checks
body_checks = pcre:/etc/postfix/body_checks

如果未设置此参数,则邮件信头过滤功能将会关闭不启用,这是系统预设值。

☛ 客户端过滤

当用户使用 SMTP 通信协议连上服务器提出寄信请求时,针对用户端输入的指令进行过滤。 在 Linux 系管师进阶班讲义(link is external) 中已经详细论及在 SMTP 连线阶段中出现的各种欺骗服务器的手法, postfix 提供非常详尽的设定可以针对这些问题加以预防。 使用客户端过滤时,必须将smtpd_delay_reject = yes 设置上去,这是系统默认值。 当设定成 no 时,虽然效率较高,但是这样做将会使得 HELO 域伪装、送信人信箱伪装、寄信人信箱伪装 以外的其它过滤功能失效。

客户端过滤可使用的过滤功能,包括:

reject_unknown_client 客户端之 IP 或 Domain name 无法从 DNS 查询验证时,拒绝连接。
permit_mynetworks 符合$mynetworks定义的用户端允许连接。
reject_rbl_client 从 SPAM 数据库站台验证客户端域名,符合时拒绝连接,当这种情况发生时,postfix 将会依照 default_rbl_reply 的设定回复相关讯息,也可以依照 rbl_reply_maps 的设定根据不同客户端给予不同讯息,事实上我们根本不需要设置此两个参数(除非想将讯息改成中文)。 这个参数必须放在最后面,当成过滤政策。
reject_rhsbl_client 同上,使用另一种 SPAM 数据库站台。 这个参数必须放在最后面,当成过滤政策。
check_client_access 根据 access 设置过滤访问权限,与 sendmail 中的 access 数据库兼容。 可以省略参数名称,直接写文件名,例如:hash:/etc/postfix/access。
permit 允许连接,设定在过滤规则的最后面,表示未被之前的规则拒绝的用户端一律允许连接,也就是采用黑名单政策。
defer 延迟连接,设定在过滤规则的最后面,表示未被之前的规则拒绝或接受的客户端,必须在稍后重新接受检验,也就是采用拖延政策。
reject 拒绝连接,设定在过滤规则的最后面,表示未被之前的规则接受的客户端一律拒绝连接,也就是采用白名单政策。
warn_if_reject 被拒绝时产生警告讯息,这是用来测试过滤规则用的。
reject_unauth_pipelining 当客户端持续一直传送 SMTP 命令时,拒绝其连接,这可以防止某些软件一次寄送大量邮件。

 

使用客户端过滤跟稍后会介绍的各种 SMTP 过滤,可以把规则依照前后顺序编排成一组规则链 ( 写成一行,中间用逗号隔开或从逗号后面分行 ),由于组合出来的过滤功能并非单独运作的,因此顺序非常重要!

smtpd_client_restrictions = reject_rbl_client dialup.ecenter.idv.tw(台湾免费的 SPAM 数据库:挡拨接发广告信)

smtpd_client_restrictions = reject_rbl_client relays.ordb.org(国外免费的 SPAM 数据库 :挡开放转信的服务器)

smtpd_client_restrictions = reject_rbl_client spam.ecenter.idv.tw(台湾免费的 SPAM 资料库:挡寄广告信的信箱)

smtpd_client_restrictions = hash:/etc/postfix/access, reject(采用白名单政策)

smtpd_client_restrictions = permit_mynetworks,reject_unknown_client。

smtpd_client_restrictions = permit_mynetworks,hash:/etc/postfix/client_checks,reject_unknown_client,reject_unauth_pipelining。( 取得石牌國小垃圾信阻擋清單(link is external)(每日更新)

☛ 是否要求使用 HELO 命令

当启用此功能时,将要求客户端进行连线时须先传送 HELO 字串,稍后我们可以根据 HELO 字串传回来的域名进行过滤,由于某些寄信程序不会传送 HELO 命令,这样做有可能会使得这些客户端程序无法正常寄信。 默认值是 :

smtpd_helo_required = no

☛ HELO 命令过滤

用于过滤 HELO 命令后面的域名是否允许其连接,能够使用的过滤功能,包括:

reject_invalid_hostname 域名字符串不符合文法时,拒绝其连线。
reject_unknown_hostname 域名无法从 DNS 查到 A 或 MX 记录时,拒绝其连接。
reject_non_fqdn_hostname 域名不是完整 FQDN 格式时,拒绝其连接。
check_helo_access 根据 access 设置过滤访问权限。
其它 permit、defer、reject、warn_if_reject、reject_unauth_pipelining 請參考前面的說明。

 

配置示例 :

smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname

☛ 信封标头字段过滤

此功能用来过滤邮件的信封标头是否符合 RFC 821 之规定,默认是不启用此过滤。 因为目前最多人使用的 MUA 是 outlook express,它会使用许多额外的头头来进行邮件控制,例如:大家熟知的要求回复功能,如果启用此参数将使得这些信件被拒绝无法寄出。

strict_rfc821_envelopes = yes

☛ 寄信人过滤

此功能并非过滤邮件标头里的寄信人栏段,而是过滤 mail from: 命令后面的字串,默认值是不过滤,但由于广告信寄信程序为了能顺利寄信,经常会伪造此字串,建议应该启用。

可以使用的选项包括 :

reject_unknown_sender_domain 寄信人的域名无法从 DNS 查询验证时,拒绝连接。
reject_rhsbl_sender 寄信人信箱如果被纪录在 SPAM 数据库站台,就拒绝他连线。
check_sender_access 根据 access 设置过滤访问权限。
reject_non_fqdn_sender 寄信人的域名不是完整 FQDN 格式时,拒绝其连接。
reject_sender_login_mismatch 寄信人信箱与登入的帐号不吻合时,拒绝其连线。 须配合 SASL 用户认证机制使用 ( SMTP AUTH )。 配合 smtpd_sender_login_maps 指定的对应表,可以让登录帐号与使用的信箱作对应,例如:shane 帐号可以用 webmaster 信箱寄信。
其它 permit、defer、reject、warn_if_reject、reject_unauth_pipelining 请参考前面的说明。

 

设置示范如下 :

smtpd_sender_restrictions = reject_rhsbl_sender dsn.rfc-ignorant.org(國外免費的 SPAM 資料庫:擋寄廣告信的信箱)
smtpd_sender_restrictions = hash:/etc/postfix/access, reject_unknown_sender_domain
smtpd_sender_restrictions = permit_sasl_authenticated,reject_unknown_sender_domain,reject_non_fqdn_sender

☛ 收信人过滤

此功能并非过滤邮件头中的收信人栏段,而是过滤 rcpt to: 命令后面的字串,默认值是不过滤,但由于广告信寄信程序为了能顺利寄信,经常会伪造此字串,建议应该启用。

可以使用的选项包括 :

permit_auth_destination 收信人域符合 $relay_domains、$mydestination、$inet_interfaces、$vitual_alias_domains、$virtual_mailbox_domains 的定义时,接受连接。
reject_unauth_destination 收信人网域不符合上述设定时,拒绝连线。
permit_mx_backup 当从 DNS 上查到本机为收信人域的备份 MX 时,接受连接。 使用此功能有安全漏洞,可以配合 permit_mx_backup_networks = 172.16.0.0/16 来检查主要 MX 是否在该网段内,来加强过滤功能 ( 避免被不信任的域设定为转信 MX )。
check_relay_domains 允许代收要给relay_domians的信件。
check_recipient_access 根据 access 设置过滤访问权限。
check_recipient_maps 当收信人网域不符合 permit_auth_destination 之要求,或是收信人信箱不符合 $local_recipient_maps、$virtual_alias_maps、$virtual_mailbox_maps、$relay_recipient_maps 的定义时,拒绝连线。 此参数可以放在收信人过滤规则的最后面,当作过滤政策。
reject_unknown_recipient_domain 收信人的域名无法从 DNS 查询验证时,拒绝连接。
reject_rhsbl_recipient 收信人信箱如果被纪录在 SPAM 数据库站台,就拒绝他连线。
reject_non_fqdn_recipient 收信人的域名不是完整 FQDN 格式时,拒绝其连接。
其它 permit、defer、reject、warn_if_reject、reject_unauth_pipelining 请参考前面的说明。

 

设置示范如下:

smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination,reject_non_fqdn_recipient

☛ ETRN 命令过滤

用来过滤哪些域或哪些客户端,可以使用 ETRN 命令。 ETRN 命令用来一次处理大量邮件,当某个用户端使用 ETRN 时,有时候会影响到其它用户寄信的效能,通常只有拨接用户、帮拨接用户转信的 mail gateway、邮件讨论群组(mailing list)或电子报发行站台,需要使用此功能。 postfix 的默认值是所有客户端都可以使用 ETRN 命令。

能使用的特殊参数只有 check_etrn_access,其余与端过滤参数相同,请自行查阅前文。 设置示范如下:

smtpd_etrn_restrictions = permit_mynetworks, hash:/etc/postfix/etrn_access, reject