谈谈本地邮件用户和虚拟邮件用户关系
在邮件系统中使用虚拟用户后,需要考虑如何处理邮件服务器所在主机的本地用户和邮件服务器自身的虚拟用户之间的关系。1、分析本地用户和虚拟用户对邮件的需求情况
本地用户可以分为两类。一是系统用户,比如bin、daemon、mail、news、postmaster等等。另一类是普通用户。
这两类用户对邮件的需求是不一样的。系统用户一般是接收来自程序的错误或日志等信息的邮件。由于系统用户没有自身的邮箱,通常是通过系统的别名表将邮件转发到一个管理员账号上。一般情况下这个管理员账号是本地上的一个用户账号,如root、serial0。普通用户可能有两种的邮件需求,能够在本地发送或是阅读邮件,也能够在其他计算机上使用邮件客户端利用邮件主机上的smtp/imap/pop服务进行邮件收发。
虚拟用户的邮件需求,就是通过smtp/imap/pop进行邮件收发,不会涉及在本地的发送阅读问题。
2、本地用户和虚拟用户关系主要有两个问题
第一、用户身份验证问题。本地用户和虚拟用户的用户信息保存位置不同。邮件主机的本地用户信息保存在/etc/passwd中,而虚拟用户信息则保存在数据库文件、数据库服务器或目录服务器等。在进行口令验证时(SMTP/IMAP/POP验证),如何从两个不同的位置取得用户名和口令这是一个问题;第二、本地用户和虚拟用户的邮件路由问题,即本地用户和虚拟用户的邮件投递问题。
下面分别讨论这两个问题。这里的实验环境是:postfix+courier-imap+cyrus-sasl+pam-mysql+mysl,虚拟用户信息保存在mysql中。
3、用户身份验证问题:
3.1、smtp口令验证:
使用cyrus-sasl的saslauthd进行SMTP口令验证。saslauthd支持在一次验证中使用多种验证机制。针对本地用户,使用shadow验证机制对/etc/shadow进行验证。针对虚拟用户,使用pam验证机制,由pam-mysql完成对mysql中虚拟用户信息的验证。
在/etc/init.d/saslauthd启动脚本中,默认使用了shadow机制:
[root@hpe45 sysconfig]# more /etc/init.d/saslauthd
...
MECH=shadow
FLAGS=
if [ -f /etc/sysconfig/saslauthd ] ; then
. /etc/sysconfig/saslauthd
fi
...
在/etc/sysconfig/saslauthd中加入pam机制:
[root@hpe45 sysconfig]# more /etc/sysconfig/saslauthd
MECH=pam
在/usr/lib/sasl2/smtpd.conf中指明smtp验证使用saslauthd:
[root@hpe45 sysconfig]# more /usr/lib/sasl2/smtpd.conf
pwcheck_method: saslauthd
mech_list: plain login
在postfix中打开smtp验证参数即可。
3.2、IMAP/POP身份验证问题
IMAP/pop验证除了验证用户和密码外,一般还会涉及到用户目录和邮箱路径的取得,特别是虚拟用户。courier-imap的authdaemon支持一次验证中使用多处用户信息。对虚拟用户,使用authmysqlrc,对mysql中的用户信息验证。对本地用户,使用pam对/etc/passwd进行验证。
在/usr/lib/courier-imap/etc/authdaemonrc中使用以下:
[root@hpe45 etc]# more /usr/lib/courier-imap/etc/authdaemonrc
authmodulelist="authmysql authpam"
在/usr/lib/courier-imap/etc/authmysqlrc中设定虚拟用户相关项:
在/etc/pam.d/imap和/etc/pam.d/pop3中对系统用户验证:
[root@hpe45 pam.d]# more imap
#%PAM-1.0
auth required pam_stack.so service=system-auth
account required pam_stack.so service=system-auth
注:由于courier-imap支持的是Maildir风格的邮箱目录,因此postfix中要打开$home_mailbox=Maildir/参数,邮件会投递到/home/username/Maildir下,courier-imap能到用户目录下取信。
以上设置后,本地用户和虚拟用户都可以由imap/pop取信。
4、邮件的路由问题
postfix对于来自本地发出的邮件与来自网络smtp的邮件,处理方法是不一样的。来自本地用户发出的邮件被sendmail投入maildrop队列,再由pickup程序送入cleanup进程。而来自网络的邮件,则由smtpd接收后送入cleanup进程。详图见http://www.postfix.org/receiving.html。
cleanup进程后,邮件被放入incoming和active队列。然后,qmgr进程处理邮件,根据默认的transport规则或是用户定义的transport表,将邮件发向不同的邮件投递代理,如本地投递代理、虚拟投递代理、smtp客户端(发向其他域)以及一些外部的MDA,如procmail。
邮件投递代理收到邮件后,将邮件投递到用户邮箱中。
4.1、使用本地投递代理和虚拟投递代理情况下的邮件路由
本地用户使用本地投递代理,虚拟用户使用虚拟投递代理。在这种情况下,邮件路由的做法:
实验中/etc/postfix/main.cf部分设置:
myhostname = hpe45.fz.fj.zz
mydomain = fz.fj.zz
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain
virtual_transport = virtual
virtual_mailbox_domains = fz.fj.zz
virtual_mailbox_base = /var/spool/smail3k
virtual_mailbox_maps = mysql:/etc/postfix/smail3k.cf
#virtual_mailbox_maps = hash:/etc/postfix/smail3k
virtual_uid_maps = static:12346
virtual_gid_maps = static:12
virtual_minimum_uid = 1001
local_transport = local
4.1.2、让本地用户和虚拟用户分属不同的邮件域。
本地用户使用主机名的邮件地址形式,如serial0@hpe45.fz.fj.zz。虚拟用户使用域名的邮件地址形式,如tom@fz.fj.zz。
将上面的myorigin值改为
myorigin=hpe45.fz.fj.zz或myorigin=$myhostname
当本地用户在本地向bin等系统用户发送邮件时,会被自动加上收件人和发件人都会自动加上@hpe45.fz.fj.zz的后缀,比如serial0
mail向bin时,会被改为serial0@hpe45.fz.fj.zz和bin@hpe45.fz.fj.zz,然后此信被转到本地投递代理。本地投递代理查别名表,再转向root,再次进入maildrop-pickup-cleanup,root又被改为root@hpe45.fz.fj.zz,再次转到本地投递代理,最后投递。
本地普通用户和虚拟用户相互之间的投递,也可以使用。
4.1.2、让本地用户和虚拟用户同属一个邮件域。
同属一个域,即本地用户邮件地址为serial0@fz.fj.zz,虚拟用户的邮件地址为tom@fz.fj.zz。可以使用transport表控制两类用户的邮件路由。使用transport表,将发向本地用户的邮件交给本地投递代理处理,将发向虚拟用户的邮件交虚拟投递代理处理。
生成/etc/postfix/hpe45fzfjzz,作为transport的表,将本地用户专门列出指定由local处理,其余都认为是虚拟用户指向virtual
[root@hpe45 postfix]# more /etc/postfix/hpe45fzfjzz
serial0@fz.fj.zz local:
fz.fj.zz virtual:
并用postmap后成相应的hpe45fzfjzz.db。
在/etc/postfix/main.cf中加入transport_map:
#local_transport = local
#transport_maps = hash:/etc/postfix/hpe45fzfjzz
以上设置只考虑了本地的普通用户。对于系统用户,默认情况下的别名表是由本地投递代理使用的,而本地投递代理的动作是在邮件路由之后才发生的。因此,当程序向系统用户发送邮件时,postfix在qmgr阶段处理时会发现在虚拟域中找不到这些用户,从而无法投递。
这种情况下,处理的办法一个是将系统用户名也加入到transport表中
postmaster@fz.fj.zz local:
root@fz.fj.zz local:
serial0@fz.fj.zz local:
fz.fj.zz virtual:
这样本地发给postmaster的邮件,经过maildrop-pickup-cleanup-incoming-active-qmgr-local会发到本地投递代理。本地投递代理查别名表,将此信转向root,即以本地方式发向postfix,又经过maildrop-pickup-cleanup-incoming-active-qmgr-local,然后投入root邮件箱中。
由此可见,如果在上面的transport中少了root@fz.fj.zz,则邮件还是无法到达。如果不写全postmaster@fz.fj.zz,root@fz.fj.zz,只写postmaster,root,邮件也是无法投递。
还有一办法是将系统用户别名表,用virtual_alias_maps指出,让别名转化在进入postfix后在cleanup处发生,这样就省了在本地投递域再处理。
在/etc/postfix/main.cf中加入:
virtual_alias_maps = hash:/etc/postfix/aliases
这样,以本地用户test发向bin用户的邮件,进入maildrop-pickup-cleanup,cleanup会查aliases.db将bin@fz.fj.zz转向root@fz.fj.zz,然后cleanup-incoming-active-qmgr-local,投在root邮箱。
因此在transport表中,要有“root@fz.fj.zz local:”记录。当然了,我们也可以在aliase加入“root:serial0”。这样,在transport表中就不需要用root记录了。