4月 052010
 

这个是讨论使用了虚拟邮件用户后,主机上的本地用户的邮件收发问题。
不同的MTA,不同的imap/pop,不同的WEB界面对处理虚拟用户和主机本地用户,有不同的做法。我只是使用了postfix,而且只使用了本地投递代理处理本地用户,虚拟用户用虚拟用户投递代理处理这种方法。当然,做虚拟用户还有别的办法,日后有时间再考虑考虑。imap/pop用courier-imap。虚拟用户信息在mysql。还用了pam-mysql做pam。

  在邮件系统中使用虚拟用户后,需要考虑如何处理邮件服务器所在主机的本地用户和件服务器自身的虚拟用户之间的关系。

一、分析本地用户和虚拟用户对邮件的需求情况。
  本地用户可以分为两类。一是系统用户,比如bin、daemon、mail、news、postmaster等等。另一类是普通用户。
  这两类用户对邮件的需求是不一样的。系统用户一般是接收来自程序的错误或日志等信息的邮件。由于系统用户没有自身的邮箱,通常是通过系统的别名表将邮件转发到一个管理员账号上。一般情况下这个管理员账号是本地上的一个用户账号,如root、local。普通用户可能有两种的邮件需求,能够在本地发送或是阅读邮件,也能够在其他计算机上使用邮件客户端利用邮件主机上的smtp/imap/pop服务进行邮件收发。
  虚拟用户的邮件需求,就是通过smtp/imap/pop进行邮件收发,不会涉及在本地的发送阅读问题。

二、本地用户和虚拟用户关系主要有两个问题

1、用户身份验证问题。本地用户和虚拟用户的用户信息保存位置不同。邮件主机的本地用户信息保存在/etc/passwd中,而虚拟用户信息则保存在数据库文件、数据库服务器或目录服务器等。在进行口令验证时(SMTP/IMAP/POP验证),如何从两个不同的位置取得用户名和口令这是一个问题;第二、本地用户和虚拟用户的邮件路由问题,即本地用户和虚拟用户的邮件投递问题。

  下面分别讨论这两个问题。这里的实验环境是:postfix+courier-imap+cyrus-sasl+pam-mysql+mysl,虚拟用户信息保存在mysql中。

三、用户身份验证问题:

1、smtp口令验证:

  使用cyrus-sasl的saslauthd进行SMTP口令验证。saslauthd支持在一次验证中使用多种验证机制。针对本地用户,使用shadow验证机制对/etc/shadow进行验证。针对虚拟用户,使用pam验证机制,由pam-mysql完成对mysql中虚拟用户信息的验证。

  在/etc/init.d/saslauthd启动脚本中,默认使用了shadow机制:
# more /etc/init.d/saslauthd

MECH=shadow
FLAGS=
if [ -f /etc/sysconfig/saslauthd ] ; then
. /etc/sysconfig/saslauthd
fi

  在/etc/sysconfig/saslauthd中加入pam机制:
# more /etc/sysconfig/saslauthd
MECH=pam

  在/usr/lib/sasl2/smtpd.conf中指明smtp验证使用saslauthd:
# more /usr/lib/sasl2/smtpd.conf
pwcheck_method: saslauthd
mech_list: plain login

  在postfix中打开smtp验证参数即可。

2、IMAP/POP身份验证问题

  IMAP/pop验证除了验证用户和密码外,一般还会涉及到用户目录和邮箱路径的取得,特别是虚拟用户。courier-imap的authdaemon支持一次验证中使用多处用户信息。对虚拟用户,使用authmysqlrc,对mysql中的用户信息验证。对本地用户,使用pam对/etc/passwd进行验证。

  在/usr/lib/courier-imap/etc/authdaemonrc中使用以下:
# more /usr/lib/courier-imap/etc/authdaemonrc
authmodulelist=”authmysql authpam”

  在/usr/lib/courier-imap/etc/authmysqlrc中设定虚拟用户相关项:

  在/etc/pam.d/imap和/etc/pam.d/pop3中对系统用户验证:
# 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取信。    

四、邮件的路由问题

  postfix对于来自本地发出的邮件与来自网络smtp的邮件,处理方法是不一样的。来自本地用户发出的邮件被sendmail投入maildrop队列,再由pickup程序送入cleanup进程。而来自网络的邮件,则由smtpd接收后送入cleanup进程。
  cleanup进程后,邮件被放入incoming和active队列。然后,qmgr进程处理邮件,根据默认的transport规则或是用户定义的transport表,将邮件发向不同的邮件投递代理,如本地投递代理、虚拟投递代理、smtp客户端(发向其他域)以及一些外部的MDA,如procmail。
  邮件投递代理收到邮件后,将邮件投递到用户邮箱中。

1、使用本地投递代理和虚拟投递代理情况下的邮件路由

  本地用户使用本地投递代理,虚拟用户使用虚拟投递代理。在这种情况下,邮件路由的做法:

  实验中/etc/postfix/main.cf部分设置:

  myhostname = mail.extmail.org
  mydomain = extmail.org
  myorigin = $mydomain
  mydestination = $myhostname, localhost.$mydomain

  virtual_transport = virtual
  virtual_mailbox_domains = extmail.org
  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

2、让本地用户和虚拟用户分属不同的邮件域。

  本地用户使用主机名的邮件地址形式,如[email protected]。虚拟用户使用域名的邮件地址形式,如[email protected]

  将上面的myorigin值改为
  myorigin=mail.extmail.org或myorigin=$myhostname

  当本地用户在本地向bin等系统用户发送邮件时,会被自动加上收件人和发件人都会自动加上@mail.extmail.org的后缀,比如local mail向bin时,会被改为[email protected][email protected],然后此信被转到本地投递代理。本地投递代理查别名表,再转向root,再次进入maildrop-pickup-cleanup,root又被改为[email protected],再次转到本地投递代理,最后投递。

  本地普通用户和虚拟用户相互之间的投递,也可以使用。

3、让本地用户和虚拟用户同属一个邮件域。

  同属一个域,即本地用户邮件地址为[email protected],虚拟用户的邮件地址为[email protected]。可以使用transport表控制两类用户的邮件路由。使用transport表,将发向本地用户的邮件交给本地投递代理处理,将发向虚拟用户的邮件交虚拟投递代理处理。

  生成/etc/postfix/local,作为transport的表,将本地用户专门列出指定由local处理,其余都认为是虚拟用户指向virtual
# more /etc/postfix/local
[email protected] local:
extmail.org virtual:
  并用postmap后成相应的local.db。

  在/etc/postfix/main.cf中加入transport_map:
#local_transport = local
#transport_maps = hash:/etc/postfix/local

  以上设置只考虑了本地的普通用户。对于系统用户,默认情况下的别名表是由本地投递代理使用的,而本地投递代理的动作是在邮件路由之后才发生的。因此,当程序向系统用户发送邮件时,postfix在qmgr阶段处理时会发现在虚拟域中找不到这些用户,从而无法投递。

  这种情况下,处理的办法一个是将系统用户名也加入到transport表中
[email protected] local:
[email protected] local:
[email protected] local:
extmail.org virtual:
  这样本地发给postmaster的邮件,经过maildrop-pickup-cleanup-incoming-active-qmgr-local会发到本地投递代理。本地投递代理查别名表,将此信转向root,即以本地方式发向postfix,又经过maildrop-pickup-cleanup-incoming-active-qmgr-local,后投入root邮件箱中。
  由此可见,如果在上面的transport中少了[email protected],则邮件还是无法到达。如果不写全[email protected][email protected],只写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将[email protected]转向[email protected],然后cleanup-incoming-active-qmgr-local,投在root邮箱。
  因此在transport表中,要有“[email protected] local:”记录。当然了,我们也可以在aliase加入“root:local”。这样,在transport表中就不需要用root记录了。

五、处理本地用户和虚拟用户要看实际情况

  如何处理本地用户和虚拟用户要看实际情况,比如邮件服务器的用途,本地用户的数量,本地用户的邮件需求等。

  假如:邮件服务器所在主机,除了邮件服务外,还有其他用途,还有一些本地用户。那这时可能就要倾向于本地用户和虚拟用户同名了。smtp/imap/pop验证都要使用/etc/passwd。

  假如:邮件服务器就是专门用来做邮件服务,没有本地用户。那么就可以将域名给虚拟用户使用。本地的用户就直接使用主机名做后缀。系统用户就可以转发一些错误日志信息的邮件投递给本地管理员。这时本地管理员就不需要什么SMTP验证了,imap/pop也可以根据需要加入。
  这时也可以考虑做别名转发,将本地管理员的邮件再转到虚拟用户上,这样就避免imap/pop服务器对/etc/passwd的访问。
  只要在别名表中加入root : [email protected] 。用newaliases转化为数据库后,就可以了。

[ 本帖最后由 liushaobo 于 2009-4-19 22:01 编辑 ]

 回复

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>