柴少鹏的官方网站 技术在分享中进步,水平在学习中升华

POSTFIX理论知识记录

一直想找个时间将postfix的理论知识总结一下,这次就抽个时间来记录一下。很多内容还是参考POSTFIX权威指南。

http://www.51niux.com/?id=59 已经很详细的记录了一个企业级的邮件服务器的搭建过程,这里对一些理论知识做些总结记录。

一、postfix介绍

1.1 简介

      postfix的历史就不介绍了,就是为了取代sendmail而设计的,到Centos 6系列以后已经默认用的是postfix软件了。postfix的研发的目标就是可靠性、安全性、效率、灵活性、容易使用、兼容于sendmail。

      Internet E-mail系统采取开放式设计,只要遵循一组公开的协议标准(RFC 2821来规范系统之间如何传递邮件和RFC 2822来规范邮件信息本身的格式)和协议(SMTP、POP3、IMAP),就能与其他Internet E-mail系统交换信息,并用不同的软件组合假设一套邮件系统。Postfix是此系统的重要组件。Postfix扮演的角色是MTA,也就是“邮件传输代理”,也就是传递邮件。

1.2 邮件系统的简单组成

MUA(邮件用户代理):如Outlook Express这种都是MUA,当我们要发送一封邮件的时候,会以SMTP协议要求MUA送出这封邮件,MUA只是将该邮件交给MTA。收信时候以POP3或IMAP协议访问服务器上的邮箱。

MTA(邮件传输代理):如postfix软件就是MTA。每当MTA收到MUA的寄信请求,它会先判断是否应该受理(如本地系统用户或是本地网络上的系统或是任何特许可以通过它转发(relay)邮件到其他目的地的网络)。另一方面MTA也会依据“收件人”来决定是否要收下邮件(收件人是本地系统的用户或是收件人位于它知道要如何传递(forword)的其他系统)。

MDA(邮件投递代理):MTA将邮件交给MDA,一般MTA服务器也有MDA服务。负责投递本地邮件到适当的邮箱,可以过滤邮件内容或是将邮件分类到适当的邮箱,甚至可以将邮件转回给MTA以寄到另一个邮箱。

MRA(邮件访问代理):使用者可以通过(POP3或者IMAP4)协议与MUA进行交互来收下自己的信件,一般就是指dovecot软件服务。

邮箱: 专门存储电子邮件的特殊数据库或者普通文件夹,任何用来长期保持邮件的机制,统一称为邮箱。然后收件人使用MUA来取信、读信(MUA必须让用户成功通过身份验证才可取走邮箱里的邮件)。

邮件管理员:负责管理邮件系统的人(postmaster),可以做增加和删除邮箱账户等操作,依据RFC2142的规定,每个网域都要有一个postmaster别名。

1.3 邮件相关的协议

SMTP:25端口,用于发送邮件。当通过MUA发送邮件时,MUA的某个动态端口(大于1024)就会与MTA的25号端口建立一个连接,邮件就会通过这个连接传送到MTA上,保存起来。

SMTPS:465端口,邮件发送加密端口。
IMAP:143端口,用于接收邮件,IMAP允许用户通过网络要求服务器代为管理邮件,也就是通过IMAP协议删除的邮件,服务器上面也就没有了。
POP3 : 110端口,用于接收收件,通过将所有邮件从服务器搬回自己的主机,所以本地删除了邮件,服务器上面的邮件还是存在的。
IMAPS : 993端口,加密协议。
POP3S:995端口,加密协议。

1.4 邮件投递的过程

postfix邮件过程.png

图片.png

这里简单画了了一个从csp@51niux.com到csp@120ni.com的邮件处理流程:

  1. 51niux.com邮件域的这个csp用户通过MUA也就是Foxmail之类的软件编写了一封邮件,也可以看做是postfix服务器的client端。然后邮件编写完了要发送,通过25端口交给postfix服务端,然后调用sendmail。

  2. postfix服务端的sendmail程序从csp@51niux.com的MUA软件中收下邮件,然后放到队列的maildrop/(/var/spool/postfix/maildrop)子目录下.

  3. pickup daemon从maildrop/目录取出邮件,交给cleanup daemon运行必要的清理程序,如主动补全不足的信息以确保邮件格式符合标准。

  4. 完成清理程序之后,cleanup将邮件存入收件队列,并通知queue manager,queue manager如果已经准备好处理新邮件了,它会将邮件移动到活动队列。

  5. 因为我们要发送给120ni.com网域的用户,是其他网域,queue manager使用smtp MDA来投递该邮件。smtp使用DNS查出120ni.com网域mx记录,smtp协议送出邮件到对端的邮件服务器主机。

  6. 120ni.com域的邮件服务器同样运行postfix(或者是其他符合标准的MTA),服务器上的postfix smtpd收下51niux.com域下的csp用户通过smtp MDA发来的邮件。

  7. 120ni.com域的邮件服务器smtpd确认收下该邮件后,会将受到的信交给cleanup daemon进行检查,然后存入收件队列。

  8. Queue manager将邮件搬移到活动队列,检查收件人地址,然后使用local MDA来进行投递操作。

  9. 如果local发现收件地址csp@120ni.com是别名,真实地址是另一个网域,就又回到了Postfix的队列系统,将邮件和新地址传给cleanup daemon,然后依靠trivial-rewrite将地址转换成标准格式,当queue manager发现新邮件应该送到另一个网络,则会调用smtp来进行投递操作。不过一般我们也不会开启转发操作。只会接收和处理发送到本域的邮件。

  10. 如果收件人是本地网域的用户,local MDA会将csp@51niux.com发送来的邮件存入120ni.com改系统的邮件,到这个时候,postfix就完成了它的工作。剩下的用户通过MUA来阅读邮件什么的就不是postfix所能控制的了。

#上面的例子是理想的简单状况,实际的传送程序可能会遇到诸如临时断线、邮件空间不足等意外情况,发送意外时,MDA会通知queue manager将邮件暂时存放到延迟队列,等待一段时间之后再重新投递。当然queue manager可能要通过lmtp MDA来投递邮件或者通过pipe MDA将邮件送到一个实现确定的外部程序。

1.5 postfix的组件

postfix采用模块化设计,不同的功能分别交由不同的专门程序来处理,这些专门的程序也就叫做组件,大多数组件都是以daemon的形式存在,也就是常驻系统内存里的连续运行的后台进程。

master daemon :  postfix被启动时,首先启动的就是这个组件,它主导邮件的处理流程,同时也对其他组件进行管理。被master启动的组件在完成任务交付的工作之后会自动结束或者如果组件处理时间超过时限或者工作量达到预定限度,组件也会自行结束。master daemon会在启动时从main.cf和master.cf这两个配置文件取得驱动参数。

queue manager:真实命令名称为qmgr, 邮件处理流程粗略的分为接收邮件、将邮件排入队列、递送邮件是哪个阶段,每个阶段都由一组独立的postfix组件负责。当邮件被收下并排入队列后,队列管理器(queue manager)会启动适当的MDA将邮件送到终点。收件进入队列之前的关卡是cleanup daemon,只有经过清理的邮件,才能进入队列。当queue manager察觉收信队列有新信到达时,就会使用trivial-rewrite来绝对邮件路由信息(传输方法、下一站以及收件人地址)。总共维护四种队列:收件(incoming)、活动(active)、延迟(deferred)、故障(corrupt)。在/var/spool/postfix目录下面有各种队列的目录。queue manager还要负责协调bounce与defer daemons根据这些目录下的状态信息产生通知函告知发件人邮件无法送达。postsuper、postqueue为管理队列的命令,postcat可以查看邮件的内容。

sendmail工具(postdrop): 当邮件进入到postfix系统,通常使用sendmail寄出邮件,postfix提供了一个与此命令兼容的同名工具sendmail,会使用postdrop程序将邮件存入postfix队列目录下的maildrop/子目录。

pickup daemon:注意maildrop/子目录有无变化,每当有新邮件进入maildrop/,pickup daemon便会读出新邮件,然后交给cleanup daemon。

cleanup daemon : 清理程序就是弥足遗漏的标头字段,让邮件格式称为一封有效的邮件格式。

trivial-rewrite daemon:如果发件人是一个别名用户,依据虚拟的查询表将原本的地址改成其他地址。

incoming queue : 收件队列,经过cleanup daemon处理好的邮件就会进入这个队列。queue manager会不断注意收件队列的变化,每当有新邮件便会用适当的MDA将邮件送到下一站或者直接送到最终目的地。

defer或bounce daemon :当用户的邮件被延时或是根本无法递送到目的地时,postfix会使用这个组件产生一封通知函,通知函会被交给cleanup daemon,由它进行例行的清理程序之后再排入收件队列,由queue manager接手处理。

smtp daemon:MDA可以直接使用SMTP client(smtp daemon)送出邮件,一般是直接发送给指定的收件人。但是当一个收件人是一个组邮件的时候有多个收件人的时候,MDA会以提交新邮件的方式让邮件重新回到postfix系统。当收件地址不是本地(local)、虚拟别名(virtual alias)、虚拟邮箱(virtual mailbox)以及转发(relay)四种类型时,则邮件会被交给SMTP client通过网络寄送出去,否则如果是这四种类型,Queue Manager便根据地址的类型选择适当的MDA来投递邮件。

1.6 投递操作

postfix依据收件地址的类型,来判断是否要收下邮件以及如何进行投递操作。

本地:如果收件人为postfix本地系统用户,则邮件会被交给local MDA处理。main.cf配置文件里面定义的mydestination网域的任何有效账户的邮件,local MDA会先检查收件人是否有个人的.forward文件,如果没有,邮件会被存入用户的个人邮箱;否则会依据.forward文件的内容来进行投递操作(或者交给外部程序处理)。

虚拟别名:寄给虚拟别名地址的邮件全部都要转寄(forward)到其真实地址,main.cf配置文件里面的virtual_alias_domains参数指定了虚拟网域。用户与其真实地址之间对应关系在virtual_alias_maps参数中指定。

虚拟邮箱:虚拟邮箱的网域名称列在virtual_mailbox_maps参数中,virtual_mailbox_maps参数所指定的查询表中定义了用户与邮箱之间的对应关系。虚拟邮箱邮件的投递操作由virtual MDA负责运行。

relay:实际邮箱位于其他MTA控制管理的网域、但是postfix愿意代收并转寄的邮件称为转发邮件。网域的名称列在relay_domains参数中定义,其邮件由smtp MDA通过网络送到目标网域的MTA。
#其他传送代理程序还有LMTP投递(queue manager调用lmtp MDA发送特殊的邮件格式)和Pipe投递(postfix提供了pipe daemon将邮件传送给外部程序如进行内容过滤程序、病毒扫描程序垃圾邮件分析程序)。

博文来自:www.51niux.com

二、master.cf

postfix的所有服务器程序都是由master daemon在必要时启动的,这些服务器程序的运行参数,全部定义在master.cf配置文件中。

2.1 默认参数

# cat /etc/postfix/master.cf|grep -v ^#  #参数行的每一栏,代表一个配置选项。“-”符号代表该栏为默认值。

#service  type  private unpriv  chroot  wakeup  maxproc command + args
smtp      inet  n       -       n       -       -       smtpd
smtp2      inet  n       -       n       -       -       smtpd
pickup    fifo  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       n       -       -       smtp
relay     unix  -       -       n       -       -       smtp
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
retry     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache

第一列为服务名称:服务器组件的名称。

第二列为传送方式:有效的传送方式包括inet(网络套接字)、unix(unix进程间通信)、fifo(命令管道)

第三列为私有的:某些服务组件仅供postfix系统自己使用。如果标记为y表示私有访问(默认值);n代表开放公共访问,inet类型的组件必须表示为n。

第四列为非特权的:是否使用非特权账户。默认值为y,表示服务组件运行时只需使用mail_owner参数指定的非特权账户(默认值为postfix)。如果需要root特权的服务组件,这里设定为n。

第五列为改变根目录:是否要改变组件的工作根目录,工作根目录的位置由main.cf的queue_directory参数决定。此栏默认为y,大部分组件都可以在chroot环境下运行。不过标准的安装方式是让所有的组件都在正常环境下运行,避免许多额外的操作,也就是这里设置为n。

第六列为唤醒间隔:某些组件必须每隔一段时间被唤醒一次,定期执行他们的任务。pickup daemon就是这样一个例子,其默认休眠间隔是60秒,master daemon每隔一分钟就唤醒pickup一次,要求它检查maildrop队列是否收到新邮件。在时间值之后尾随一个问号(?)表示只有在需要该组件时才唤醒,0表示不必唤醒。此栏默认值为0,大部分组件不需要master 的定期唤醒,一般pickup和qmgr需要被定期唤醒。

第七列为进程数上线:可以同时运行的进程个数的上限,如果没指定,则以main.cf的default_process_limit参数为准(默认值为100)。如果设定为0表示无限制。

第八列为命令:运行服务的实际命令,不必包含路径信息,因为master daemon假设所有程序文件都放在daemon_directory参数所指定的目录下(默认目录为/usr/libexec/postfix)。

2.2 加入时间单位

postfix提供了一组简写代号来表示时间单位:s(秒)、m(分)、h(时)、d(天)、w(周)。

如:

smtp-quick  unix  -       -       n       -       -       smtp

       -o smtp_connect_timeout=5s

#-o参数让master.cf中强制设定你要的参数值,这就相当于多了一个特殊的smtp-quick服务,当寄信时如果对方服务器五秒内没有响应就会自动断线。

博文来自:www.51niux.com

三、本地投递与POP/IMAP

SMTP协议要求收下邮件的MTA,必须负责将邮件送到最终目的地(本地系统的邮箱或者同一网络上的其他主机),这段工作过程称为投递(delivery)。

3.1 postfix的投递代理程序

本地邮件:若邮件终点站是mydestination参数所列出的网域之一,postfix就视其为本地邮件,由local MDA执行投递任务。本地邮件一般会被投递到mail_spool_directory参数定义的/var/spool/mail目录下,邮件存储格式就是mbox形式,如果mail_spool_directory = /var/spool/mail/是这种形式就是想改用成maildir格式。为了避免收下不明用户的邮件,所有本地收件人的名称都必须列在local_recipient_maps参数所指的表中,此参数默认是指向unix系统的密码文件与别名表,所以通常不需要修改这个参数。

转发邮件:若邮件终点站是relay_domains参数所列出的网域之一,postfix就视其为转发邮件,由relay MDA来执行投递任务。一般postfix被当成局域网络的邮件网关使用,网络中还有其他网域的邮件服务器。

虚拟网域邮件:虚拟邮箱网域必须列于virtual_mailbox_domains参数中,如果一台服务器要服务多个网域就被称为虚拟网域,虚拟邮件的网域由virtual MDA负责投递,每个虚拟邮箱网域都有自己的邮箱目录。

3.2 邮件格式

postfix投递本地邮件时,邮件内容会被传送到postfix系统上适当邮箱,常见邮件格式的就是传统的mbox以及较新的maildir。mbo几乎全世界都支持但是文件锁定问题导致maildir格式的出现。

mbox格式:如/var/spool/mail/root这种格式就是mbox格式,所有的邮件都写到一个文件中,新邮件都是以From开头。然后一直在这个文件中追加。由于postfix和POP/IMAP server有可能会同时访问同一个mbox文件,所以使用“文件锁定机制”来确保访问权。在local投递本地邮件之前,必须先将该文件加锁,然后才能将邮件内容写入mbox文件。postfix支持多种锁定机制自己自动调度#postconf -l可以查看。

maildir格式:maildir邮箱格式使用目录结构来存出邮件,如:/var/mailbox/120ni.com/csp/Maildir,这个就是有个网域目录:120ni.com,然后每个用户都是一个目录,这里csp@120ni.com,就是一个csp目录。然后在其Maildir/目录下面有三个子目录:tmp/(供MDA将邮件内容存储成文件,在确定全部内容都写入文件之后,邮件文件会被搬到new/目录)、new/(MDA已经送达但是尚未被用户阅读的信文件本身的修改时间就是收下邮件的时间)以及cur/(用户看过邮件之后,邮件文件会被迁移到此目录)。

3.3 POP与IMAP

Postfix的职责是将收下的邮件放入邮箱,让用户能从邮箱取走邮件的协议是IMAP与POP,IMAP/POP服务是由Postfix之外的软件所提供的的。

POP与IMAP的差别:POP协议是让用户连接到邮件服务器取走所有的邮件,但是POP不支持多邮箱,而且强制要求必须完整下载邮件后才能读信。IMAP协议是为了克服POP的缺点设计的,IMAP上所有邮件都留在服务器上,用户看信之前必须先联机,联机之后可再远程进行任何控制管理动作,所有的实质动作都发生再服务器上,也可以离线阅读(将邮件的副本存放在本地端)而且可以拥有多个邮箱。

Postfix与POP/IMAP servers:它们之间的合作相当简单,每当postfix收下发送到本地的邮件,就将邮件封存在邮箱里,当POP/IMAP server收到用户的要求时,只要从同样的邮箱取出邮件即可。

LMTP:本地邮件传输协议。LMTP除了可以让MTA用来将邮件投递到非标准格式的邮箱。其最大的好处是让邮件管理人员可以假设出容器扩展且可靠的邮件系统,如对于邮件量很大的站点,可以假设一台或多台postfix servers专门接收来自Internet的邮件,然后投递给多个LMTP后台系统。最知名的因使用专属邮件格式,而需要以LMTP接收邮件的POP/IMAP服务器软件应当是Cyrus IMAP server.

Postfix与Cyrus IMAP : Cyrus IMAP是专门提供POP/IMAP服务的服务器,用户不需要系统账户。Cyrus IMAP提供两种LMTP投递渠道,分别是unix-domain socket与TCP socket。要让Postfix收下投递给本地Cyrus IMAP server的邮件,则收件地址的网域名称必须被列于mydestination参数(如果使用virtual MDA来投递邮箱给Cyrus需要另外的配置)。Cyrus IMAP使用Cyrus SASL函数库来验证用户身份,Cyrus软件至少需要Berkeley DB 3以上的版本。

3.4 虚拟网域

postfix对于虚拟网域邮件的四种处理方式:共享网域搭建虚拟账户、独立网域搭建虚拟账户、独立网域搭配虚拟账户、虚拟网域搭配非postfix控制管理的特殊格式邮箱。

独立网域搭建虚拟账户:

      共享网域搭建虚拟账户和独立网域搭建虚拟账户最大的缺点是每一个邮件地址都必须再服务器上有对应的系统账户。虚拟邮箱与一般邮箱的差别在于邮件文件与系统账户之间不用一比一的对应关系。

      使用虚拟邮件模式时,必须在virtual_mailbox_domains参数列出每一个虚拟网域的名称,当然我们可以这样virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf,将多个虚拟网域存放到数据库中,让邮箱web管理,或着可以virtual_mailbox_domains = /etc/postfix/virtual_domains存放到文件里,文件里面一行一个虚拟网域的域名。

      每当postfix收到写给virtual_mailbox_domains所列的虚拟网域的邮件时,就交由virtual MDA执行投递操作。其代价是牺牲了本地别名文件、.forward文件、MLM的支持,不过可以使用 virtual_alias_maps来达到同样的效果,如:virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf 将用户组别名等写到数据库里面方便调用和管理。

      设置虚拟邮箱时,每个虚拟网域应该分别放到不同的子目录下,定义虚拟邮箱的基础目录的参数是virtual_mailbox_base,#virtual_mailbox_base = /var/mailbox 给出完整的目录路径。virtual_mailbox_maps参数定义了虚拟邮箱查询表的位置。如:virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf  #这里面定义了每一个虚拟用户邮箱账户以及相关的信息。

邮箱文件的拥有权:

      虚拟邮箱文件也需要属主属组,通常POP/IMAP server的运行权限继承于某个专属的系统账户,所以邮箱文件的拥有者权限应该是POP/IMAP server所用的那个虚账户。virtual_uid_maps和virtual_gid_maps参数绝对了postfix的virtual MDA投递邮件到虚拟邮箱时,应该继承的系统账户。当然也可以指定不同的uid和gid的查询表文件之类的. 

作者:忙碌的柴少 分类:邮件服务器 浏览:2354 评论:0
留言列表
发表评论
来宾的头像