近年来,用同一台主机来搭建多个网域,已经蔚然成风。举个实例来说,oreillynet.com和onlamp.com其实位于同一台主机,但是从外界
的观点来看,它们似乎分别位于两台完全不同的主机上。一个系统通常有一个最具代表性的网域名称,称为正式网域,除此之外的其他网域,则被视为虚拟网域。每
个虚拟网域都可以提供自己的网络与邮件服务,且外界看不出正式网域与虚拟网域的差别。
postfix如何投递虚拟网域的邮件,决定了你需要哪些技术。有两个重要因素影响你的postfix如何支持多个虚拟网域:
网域之间要有单独的命名空间吗?比方说,写给info@oreilly.com和info@ora.com这两个地址的邮件,是放在同一个邮箱还是各自单独的邮箱?对于使用相同邮箱的情况,我们称之为共享网域;而另一种情况则称为独立网域。
每位用户都需要系统账户吗?我们将区别“系统账户”与“虚拟账户”的不同。前者是真正的unix账户,可用来登录服务器系统;后者纯粹用于辨识邮箱,不能登录系统,在/etc/passwd里也没有对应记录。
我们将探讨postfix对于虚拟网域邮件的四种处理方式:
共享网域搭配系统账户
独立网域搭配系统账户
独立网域搭配虚拟账户
虚拟网域搭配非postfix控制管理的特殊格式邮箱
应
该挑选哪一种技术,主要决定因素是你所使用的POP/IMAP server。如果你的POP/IMAP
server不能辨别虚拟网域,那么,很可能所有邮件地址需要系统账户。某些POP/IMAP
servers天生就是为了支持多重网域而设计,而且邮件是存放在本地文件系统的某个特定目录结构下,还有些POP/IMAP
server使用自己专属的邮箱格式。对于posfix不支持的邮箱格式,postfix可使用LMTP将邮件交给POP/IMAP server。
不管采用哪一种技术,你的正式网域的DNS是怎么设定的,所有虚拟网域的DNS都必须“依样画葫芦”。
共享网域搭配系统账户
最
简单的虚拟网域模式,是每位用户都可以收到每个网域的邮件。就用户的感受而言,就好像同一个邮箱有多个地址一样。这种模式的设定方法最简单,只要将所有虚
拟网域名称都列在mydestination参数,并像平常一样为每一位用户都创建自己的系统账户,他们就可以收到写给任何网域的邮件。
这种模式
使用LOCAL
MDA来执行投递操作,因此,正式网域该有的功能,虚拟网域同样一应俱全,所有网域共享同一个别名文件,每位用户都可以创建自己的.forward文件。
举例来说,假设我们希望oreillynet.com网域的邮件服务器兼任ora.com与oreilly.com这两个网域的邮件交换站。第一步是设定
那两个虚拟网域的DNS,将它们的mx都指向此服务器;第二步是修改此服务器的mydestination参数,完成修改之后,记得要让postfix重
新读取其配置文件,让你所做的改变生效;用户现在可以收到寄给mydestination所列的任一网域的邮件。外界写给info@ora.com或
info@oreilly.com的邮件,都会被投递到同一个系统账户的邮箱。
独立网域搭配系统账户
如果每个虚拟网域都
要有自己的命名空间,设定方法就稍微复杂些。在独立网域模式下,写给info@ora.com的邮件不应该被放在
info@oreilly.com的邮箱中。在这种情况下,虚拟网域不应该被列在mydestination参数中,而应该被列在
virtual_alias_domains参数中;你必须为每一个邮件地址分别创建对应的系统账户。每一个系统账户的名称都必须独一无二,但是不要求一
定要与邮件地址的人名部分相同,因为我们可以另外准备一个查询表来定义两者之间的对应关系。若要区别账户所属网域,同时又要避免账户名称重复,最简单的方
法是将网域名称当成账户名称的一部分。一种可行的命名法则,是使用类似info.ora.com和info.oreilly.com这样的名称来创建系统
账户。不过,某些系统平台的账户名称被限制在8个字符以下,如果你的平台不支持长名称,就不能使用这种命名法则。
在postfix知道它应该收下哪些网域的邮件,而你也为每一个地址都准备好对应的系统账户之后,下一步就是将virtual_ailas_maps指向虚拟别名表:
virtual_alias_maps = hash:/etc/postfix/virtual_alias
此查询表定义了每一个虚拟网域邮件地址所对应的实际邮件地址。
每当你修改虚拟别名表后,别忘了使用postmap将该文件转换成postfix可直接查询的格式:
postmap virtual_alias
如果helene和frank能够登录服务器系统,直接从服务器寄信出去,你可能还需要另外准备一个规范映射表,好让他们寄出去的邮件的寄件人地址被改写成正确的地址。例如:
canoniacl_maps = hash:/etc/postfix/canonical
再次提醒,规范映射表也必须经过postmap的转换
独立网域搭配虚拟账户
前
两种模式最大的缺点,就是每一个邮件地址都必须在服务器上有对应的系统账户。虽然事前的设定过程不难,但是事后维护工作却很麻烦。尤其当虚拟网域的数量增
加时,系统账户的维护工作更是苦不堪言。此外,从系统安全的角度来看,如果绝大部分用户都只是利用服务器来收信而已,实在没有必要赋予他们能够登录系统的
能力。比较务实的做法,应该是要求postfix将邮件投递到本地系统上的一个虚拟邮箱目录,在此目录下,每一个虚拟邮件都有自己的邮箱文件,而用户可通
过支持虚拟邮箱的POP/IMAP server来取信。虚拟邮箱与一般邮箱的差别之处,在于邮件文件与系统账户之间不要求存在一比一的对应关系。
使用虚拟邮箱模式时,你必须在virtual_mailbox_domains参数列出每一个虚拟网域的名称:
virtual_mailbox_domains = ora.com, oreilly.com
如果你有许多虚拟网域,不妨将它们列在一个文件,然后将virtual_mailbox_domains指向该文件:
virtual_mailbox_domains = /etc/postfix/virtual_domains
/etc/postfix/virtual_domains文件的每一行,各包含一个虚拟网域的名称。
每
当postfix收到写给virtual_mailbox_domains所列的虚拟网域的邮件时,就交由virtual
MDA执行投递操作。virtual的实质是local
MDA的“小型版本”,它以一种安全而且高效率的程序来进行投递,其代价是牺牲了本地别名文件、forward文件、MLM饿支持。不过,这不是什么大缺
点,因为我们仍可使用virtual_alias_maps参数来达到同样的效果。
设定虚拟邮箱时,你应该妥善安排邮件目录的结构,使其符合
POP/IMAP server的预期要求。支持虚拟邮箱的POP/IMAP
server,多半假设所有虚拟邮箱都位于某一个基础目录下,在此目录下,每一个虚拟网域都有一个与其网域名称同名的子目录。因此,如果有两个虚拟网域,
则它们的虚拟邮箱应该分别被放在两个子目录下;
定义虚拟邮箱基础目录的参数是virtual_mailbox_base,你必须给出完整的目录路径;
virtual_mailbox_base = /var/vmail
virtual_mailbox_maps
参数定义虚拟邮箱查询表的位置;此查询表描述每一位虚拟邮箱用户的邮件地址以及对应的邮箱文件的相对路径文件名。邮箱文件的格式可以是mbox或
maildir。如果你选择maildir格式,邮箱文件名末端必须加一个“/"符合。
info@ora.com ora.com/info
info@oreilly.com oreilly.com/info
完成上述设定后,外界写到info@ora.com和info@oreilly.com的邮件,就不会存放在同一个邮箱了。
邮箱文件的拥有权
Unix
系统上的每一个文件都有主人,虚拟邮箱文件也不例外--虽然虚拟邮箱的“用户”没有系统账户。因此,用户如何访问邮箱文件,决定呢邮箱文件拥有权的归属。
通常,POP/IMAP
server的运行权限继承于某个专属的系统虚账户,并假设其权限足以访问所有邮箱文件。因此,邮箱文件的拥有者应该是POP/IMAP
server所有的那个虚账户。但是,如果必要的话,postfix也容许你自己决定文件的拥有者。你可以让每个邮箱文件都有自己的拥有者或是让同网域的
所有邮箱文件都同属于一个拥有者,但不同网域的邮箱分属不同的拥有者。
virtual_uid_maps于virtual_gid_maps参数
决定了postfix的virtual
MDA投递邮件到虚拟邮箱时,应该继承的系统账户。假设所有虚拟邮箱都属于同一个账户,则你可以使用static映射方式,直接指定virtual所要继
承的UID与GID;
virtual_uid_maps = static:1003
virtual_gid_maps = static:1005
这
会使得virtual MDA以UID 1003、GID
1005的身份来访问任何邮箱文件。如果你希望virtual以不同的UID身份来访问不同的邮箱文件,你必须另外准备一个查询表,定义各个虚拟邮箱地址
与UID之间的对应关系,然后将virtual_uid_maps指向 此查询表;
virtual_uid_maps = hash:/etc/postfix/virtual_uids
如果大部分的虚拟邮箱文件属于固定的拥有者,但也有某些是属于不同的UID,你可以混合使用static与查询表:
virtual_uid_maps = hash:/etc/postfix/virtual_uids static:1003
virtual_gid_maps参数的用法与virtual_uid_maps完全相同。
定
义邮箱文件与拥有者对应关系的/etc/postfix/virtual_uids文件,其索引键是邮箱文件所属的邮件地址,而对应值是邮箱文件拥有者的
UID(或GID)。举例来说,如果我们希望ora.com网域的所有邮箱都属于同一个UID,而oreilly.com的邮箱属于另一个UID。
虚拟别名
即
使是虚拟网域,postfix也能将其邮件投递到本地邮箱,或是转寄到其他站点。既然所有类型的收件地址都会被检查是否为虚拟别名,所以,只要把转寄地址
放在virtual_alias_maps所指的文件即可。请确定virtual_alias_maps参数指向一个虚拟别名表:
virtual_alias_maps = hash:/etc/postfix/virtual_alias
/etc/postfix/virtual_alias文件包含了要被转寄到他处的虚拟地址:
kdent@oreilly.com kyle.dent@onlamp.com
不
要将同一个网域同时列在virtual_mailbox_domains和virtual_alias_domains中。对于同时含有邮箱与别名的虚拟
网域,请使用virtual_mailbox_domains。如果所有地址都是别名,请使用virtual_alias_domains。
无限别名地址
无
论是虚拟别名还是虚拟邮箱,它们的查询表都可以含有一个“无限别名地址”--只有网域部分没有人名部分的邮件地址。无限别名地址所对应的邮箱(如果是虚拟
邮箱的话)或转寄地址(如果是虚拟别名的话),用来承接外界寄到该网域的不明用户的邮件。无限别名地址应该谨慎使用,因为它们一定会收到大量垃圾邮件。发
送垃圾邮件者常用“字典攻击法”来滥发垃圾邮件,所以你的邮件服务器会时常收到寄信给不明用户的要求。如果设定了无限别名地址,等于是让这些发送垃圾邮件
者有机会塞爆你的邮箱。
无限别名虚拟邮箱
第一步是找出一个邮箱来承接所有寄给不明用户的邮件。你可以使用现有的邮箱,或是另外创建一个新邮箱。决定好邮箱之后,在virtual_mailbox_maps所指的查询表增加一笔无限别名地址记录;
@ora.com ora.com/service
无限别名虚拟别名
无限别名虚拟别名的设定步骤,很类似无限别名虚拟邮箱。第一步,先选定一个邮箱地址来接收所有寄到不明别名等邮件,然后在virtual_alias_maps所指的查询表定义无限别名所对应的地址:
@ora.com customer.service@onlamp.com
除非你的系统没有任何虚拟邮箱,否则不应该设置无限别名虚拟别名。因为postfix会先展开虚拟别名,然后才检查虚拟邮箱;如果你设置了无限别名虚拟别名,它将拦截掉所有的邮件,包括原本应该投递到虚拟邮箱的邮件。
在设置了无限别名的情况下,如果还希望虚拟邮箱能够收到邮件,唯一办法是将虚拟别名展开成虚拟邮箱地址。举例来说,假设下面是虚拟邮箱查询表的内容:
info@ora.com ora.com/info
info@oreilly.com oreilly.com/info
那么,含有无限别名的虚拟别名表,应该要含有上述虚拟邮箱的别名地址:
info@ora.com info@ora.com
info@oreilly.com info@oreilly.com
kdent@oreilly.com kyle.dent@onlamp.com
@ora.com customer.service@onlamp.com
如此一来,寄到info@oreilly.com的邮件,就不至于被@ora.com无限别名拦截掉了。
虚拟网域搭配特殊格式的邮箱
我们要讨论的最后一种操作模式,是在一个使用特殊邮箱格式的系统上假设虚拟网域。在这类系统上,postfix本身不做投递工作,而是使用LMTP协议将邮件托付给知道如何访问特殊邮箱的程序。
因为postfix必须先收下邮件后才转交给LMTP server,所以postfix必须知道它要收下哪些虚拟网域名称的邮件。请将这些网域的名称列于virtual_mailbox_domains参数:
virtual_mailbox_domains = ora.com, oreilly.com
你还必须逐一列出每一个邮件地址,这样postfix才能够知道哪些收件地址是有效的,并拒收不明用户的邮件。请将virual_mailbox_maps参数指向有效地址查询表:
virtual_mailbox_maps = hash:/etc/postfix/virtual
因为postfix只需要知道地址的有效性而不参与投递工作,所以/etc/postfix/virtual查询表只有索引键的部分有意义,对应值的部分没有作用。然而,查询表的格式不容许我们省略对应值,所以仍必须随便填入数据;
为
了让postfix能将虚拟网域的邮件交给POP/IMAP
server,我们还必须在main.cf的virtual_transport参数中指定正确的传送方法,也就是LMTP
server的socket是何种形式。假设LMTP server与postfix都位于同一台机器,而且LMTP
server使用unix-domain
socket,其文件位置是/var/imap/socket/lmtp,则virtual_transport应该这样设定:
virtual_transport = lmtp:unix:/var/imap/socket/lmtp
现在,每当postfix收到寄给virtual_mailbox_domains所列的任一网域的邮件,都会通过LMTP协议交给同机器上的POP/IMAP server来执行投递操作。
投递到外部程序
先
前说过,virtual
MDA不能处理系统别名文件与个人的.forward文件。虽然使用virtual_alias_maps可弥补虚拟网域的地址别名问题,但
是.forward文件的一项重要功能--传递邮件内容给外部程序,还没解决。这表示虚拟网域的地址没有自动回信功能,也不能假设邮递列表管理系统。本节
将示范如何利用postfix的其他机制,让寄到虚拟地址的邮件也可以传给外部程序。第一个例子示范如何投递邮件到一个自动回复程序,第二个例子以
majordomo MLM来做示范。
自动回信程序的作用,主要是在没有任何人员接入操作的情况下,自动处理外来邮件、储存或处理来信信息,然后回信给原寄信人。回信程序可以是简单的脚步,也可以是以C或任何语言写成的复杂程序。
假设我们要提供一个供客户请求信息的服务,只要客户寄信到特定地址,就回复一封含有请求信息的回信。我们不希望使用人工处理这种千篇一律的机械工作,所以,最好的办法是写一个自动回复程序。
将虚拟网域的邮件传给自动回信程序
虚拟网域的邮件不能通过.forward机制传给外部程序,因此,若想让自动回信程序能收到虚拟地址的邮件,我们必须在master.cf中增加一个能投递邮件到外部程序的特殊MDA,然后使用传输表将特定地址的邮件交给这个特殊的MDA处理。
许多自动回信程序一次只能处理一封来信,而且一次只能回一封信。对于每一种MDA,都有一个限制收件人数量的mda_destination_recipient_limit参数,其中的mda是MDA在master.cf里的服务名称。
自动回信程序的设计
如
果你想设计自己的自动回信程序,有些重要考虑事项必须注意。首先,同时也可能是最重要的事项,就是程序的数据来源是网络--一种不可信赖的数据源。千万别
假设你要处理的数据一定会是什么样子,除了它们被可以安排成能征服你的系统之外。无论任何情况,都不应该调用shell来处理不可信的外来数据,让外界有
机会夺取你的系统的访问权。
另一个要考虑的事项,是礼节教养问题。想像一下,如果自动回信程序的回信对象是一个含有几千人的邮箱列表,将客户请求
的信息泄漏给几千人,或是让几千人收到不相干的邮件,应该都不是你原意见到的事。因此,在实际回信之前,最好先检查寄件人地址是否为owner-list
或list-request之类的形式。此外,还有一些地址恐怕也是你不想回复的,像postmaster、daemon、majordomo等。你的程
序应该将自己的信封地址设成空字符串,以免造成邮件循环。
许多邮件列表会利用precedence:标题栏来注明它自己。它们通常使用bulk之类的值来表示邮件的性质。你的回信程序应该要检查precedence:标题栏的值,如果发现bulk、list或junk之类的字样,就不必回信了。
最后,确定你的程序能记录每封来信的处理状况。一旦postfix将邮件托付给你的程序,你的程序就有检查错误的责任,并为管理员提供可以在事后追查问题的线索。
在虚拟网域假设邮件列表管理系统
第二各例子,我们要示范如何在虚拟网域上设置一个邮件列表。
postfix与MLM之间的连接是通过别名文件:利用别名文件的:include;机制来展开列表,并将管理用途的别名对应到实际地址与MLM管理程序。然而,只有local MDA才会处理系统的别名文件,virtual MDA没有这方面的功能。
虚拟邮件列表的原理,是在本地网域下创建列表的相同版本,这各本地版本仅供系统内部使用,外界用户所用的仍是虚拟地址,他们并部知道本地版本的存在。在决定本地版本的名称时,我们可设法将虚拟名称包含在内,以便容纳同系统上的其他虚拟网域列表。
阅读(1170) | 评论(1) | 转发(0) |