Linux Postfix+Dovecot+sasl

      又有业务需求要搞postfix,几年前部署过,这真是一段时间不操作就忘光光啊,趁部署完赶紧记录一下,部署环境debian5,软件都是apt安装,不要源码安装。这次的业务要求是能调用接口发邮件,并且为了安全要经过认证的账号才能发邮件,没经过认证的则拒绝。如果发信时无需认证的邮件服务器,很容易造成大量垃圾邮件的产生,也给服务器带来了不必要的负担。经过google后发现Cyrus SASL(Cyrus简单认证安全层)这个能满足我的需求。

     Postfix使用SASL框架来实现验证,具体地说是由Cyrus-SASL实现的SASL库,Cyrus-SASL是SASL的一种实现。SMTP发信认证的常见形式如下:当用户通过SMTP协议向外部邮件域发送邮件时,服务器会要求用户提供用户帐号和口令进行身份认证,只有成功通过身份认证的用户才被允许向外部发送邮件,否则将拒绝发信请求。

    SASL的验证框架大致如下:

        支持SASL的服务器端(比如postfix的smtpd这个daemon)监听网络连接
        客户端连接应用并发起认证过程:客户端选择一个SMTP AUTH的机制,并根据这个机制准备相应的凭证,然后把它选择的机制和相应的凭证发给服务器
        服务器方保存客户端的验证机制和相应的凭证,并把它交给一个真正完成这种密码验证的后服务,比如saslauthd
        验证服务根据客户的凭证和验证的后端数据(比如/etc/shadow文件)来确定是否通过验证,并把验证结果返回给smtpd
        smtpd根据验证的结果做出相应的动作

   SASL的验证接口:

       在验证的过程中服务器和客户之间需要一个验证接口来告诉客户端需要验证以及哪些验证机制是可用的。SASL本身并没有对这个接口做出规定,而是由具体的服务和协议自己来确定这个接口。比如在ESMTP协议中,在客户端敲入EHLO时,服务器端会提示支持的验证机制。

  saslauthd是Cyrus SASL软件中的一个程序,saslauthd它是一个独立运行的daemon,它是基于系统密码来验证的,可以读取很多种后端的认证数据,包括:getpwent(/etc/passwd), kerberos,pam,rimap(remote IMAP server),shadow,ldap,其中一些是需要root权限的,而saslauthd就是以root身份来运行的,它可以帮助postfix来 验证密码,因为postfix本身在设计的时候就避开了特权身份。saslauthd只支持和PLAIN和LOGIN两种验证机制。

下面开始部署

#安装邮件服务器
apt-get install postfix
#安装客户端
apt-get install dovecot-common dovecot-imapd dovecot-pop3d
#安装sasl
apt-get install sasl2-bin libsasl2-2 libsasl2-dev libsasl2-modules
  安装完成后默认的saslauthd服务是无法启动的,要做如下修改:/etc/default/saslauthd 

START=yes
MECHANISMS="shadow"

 /etc/dovecot/下面的文件不用修改,保持默认。

 新建文件:/etc/postfix/sasl/smtpd.conf   该文件默认不存在,在sasl认证时要用到,内容如下:

pwcheck_method: saslauthd 
saslauthd_path: /var/spool/postfix/var/run/saslauthd/mux
mech_list: PLAIN LOGIN
log_level: 7
 修改/etc/postfix/master.cf文件,变化如下(这一步可以不用添加,只是为了安全):

#所有联机到这里的客户端都必须通过sasl认证
relay     unix  -       -       -       -       -       smtp
        -o smtpd_client_restrictions=permit_sasl_authenticated,reject
下面看看postfix的主配文件:/etc/postfix/main.cf

##通过telnet等工具连接smtp(25)时显示的banner信息,为了安全不显示smtp服务器的信息
smtpd_banner = $myhostname ESMTP unknow

##biff是一个在收到新邮件时,发出通知给本地用户的小程序,一般关闭该程序
biff = no

append_dot_mydomain = no
readme_directory = no

##设定主机名称,描述服务器的域名全称
myhostname = mail5.61.com

#设置域名,我们将让此处设置将成为E-mail地址“@”后面的部分
mydomain = 61.com

##将发信地址“@”后面的部分设置为该域名,该参数指定服务器使用那个域名来向外发邮件,缺省情况使用主机名,建议myorigin和mydomin一致
myorigin = 61.com

#指定该服务器使用那个域名来接收邮件
mydestination = $myhostname,$mydomain,51mole.com,localhost,localhost.localdomain,localhost

#alias_maps = hash:/etc/aliases
#alias_database = hash:/etc/aliases

relayhost = 

##设定转发信任网络 mynetworks
mynetworks = 0.0.0.0/0,10.1.0.0/16,127.0.0.1

#规范可以转发的域名 relay_domains
#relay_domains = $myhostname, $mydomain, 61.com

##监听的网络地址,这里监听所有网络介质
inet_interfaces = all

###################################
#smtpd_helo_restrictions = 
                          #允许mynetworks的连接
                          #permit_mynetworks,
			  #拒绝错误的hostname
			  #reject_invalid_hostname,
			  #拒绝DNS的A记录或者MX记录域名
			  #reject_unknown_hostname,
			  #拒绝不符合域名规则的域名
	                  #reject_non_fqdn_hostname

							
##当必须进行helo握手时,检验握手信息是否正确
smtpd_helo_restrictions = permit_mynetworks


##对连接到该邮件服务器的客户端进行限制,允许/拒绝客户端使用邮件服务器
smtpd_client_restrictions =  
                            #允许子网中的连接
                            permit_mynetworks,
			    #拒绝不能进行进行反向解析的ip地址
			    reject_unknow_client,
			    #拒绝rbl连接
                            reject_rbl_client cblless.anti-spam.org.cn,
                            reject_rbl_client sbl-xbl.spamhaus.org,
                            reject_rbl_client relays.ordb.org,
                            reject_rhsbl_client dsn.rfc-ignorant.org


##对发信人的地址进行过滤,设置发信人的地址必须符合规则
smtpd_sender_restrictions = 
      #拒绝为没有DNS A记录或者MX记录的域发邮件,就是MAIL FROM命令提供的主机名在DNS中没有相应的A或MX记录则拒绝该客户端的连接请求
                            reject_unknown_sender_domain,
#拒绝不符合规则的发信人地址,就是MAIL FROM命令提供的主机名不是RFC规定的完整的域名则拒绝客户端的连接请求.
                            reject_non_fqdn_sender,


##对收信人的地址进行过滤,就是在执行RCPT TO命令时提供的地址进行限制
smtpd_recipient_restrictions = 
                               #允许经过sasl认证的地址
			       permit_sasl_authenticated,reject
			       #拒绝没有经过认证的
                               #reject_unauth_destination
                               #reject_non_fqdn_recipient,
                               #reject_unknown_recipient_domain,
                               #permit_mynetworks,


##客户端在SMTP会话的开始时是否必须发送一个HELO命令,默认是no
smtpd_helo_required = no

##RFC 821对邮件的信头做了严格的规定,是否只接受符合RFC821规则的邮件
strict_rfc821_envelopes = no

##设置一封邮件允许有多少个收件人,这里指定一封邮件可以同时发给50个人
smtpd_recipient_limit = 50

##设置一封邮件大小(包括正文,附件等所有内容),这里指定为20MB
message_size_limit = 20480000

##设置用户邮箱在大小,这里为4GB
mailbox_size_limit = 0

##当SMTP服务端口接收到非法的命令时,系统将缓冲处理的时间间隔,这里指定为10秒
smtpd_error_sleep_time = 10s

##当超过该参数所指定的错误次数时,系统应用缓冲时间,即10秒,这里指定错误次数为2次
smtpd_soft_error_limit = 2

##当超过该参数所指定的错误次数时,系统强制断开客户端,这里指定为5次
smtpd_hard_error_limit = 5

##smtp服务器的最大并发链接数,这里指定为300
default_process_limit = 300

##控制对同一目标主机的初始化并发连接数目,这里调整为10
initial_destination_concurrency = 10

##缺省的对同一目标主机的最大并发连接数目,这里调整为10
default_destination_concurrency_limit = 10

##控制对同一本地收件人的最大同时投递的邮件数目
local_destination_concurrency_limit = 2

##设置postfix在放弃投递而返回不可投递信息前,被延迟邮件在deferred邮件队列中的生存时间
maximal_queue_lifetime = 1d
bounce_queue_lifetime = 1d

##设置队列管理程序进行扫描deferred(拖延)邮件队列的扫描频率,这里调整为1小时
queue_run_delay = 3600s

##当一封邮件投递失败后,邮件队列将在一段时间内忽视该邮件的存在,最小的忽略时间为300秒
minimal_backoff_time = 300s

##当一封邮件投递失败后,邮件队列将在一段时间内忽视该邮件的存在,最大的忽略时间为3600秒
maximal_backoff_time = 3600s

##控制读入数据时每一行的大小,这里为2048个字节
line_length_limit = 2048

##限制信头长度
header_size_limit = 102400

##设置整个队列目录最大使用的磁盘功能,这里调整为不限制
queue_minfree = 0

##弹回邮件的长度过滤参数,限制某一邮件不可投递时,返回给发件人不可投递报告的大小
bounce_size_limit = 50000

#内存中收件人地址的最大数目,这里为20000个
qmgr_message_recipient_limit = 20000


#设置active邮件队列中邮件数目的最大值
qmgr_message_active_limit = 20000

#设置需要local和cleanup后台程序记住的收件人地址的最大数目
duplicate_filter_limit = 1000


#设置local程序等待一个外部命令完成的时间
command_time_limit = 1000s

#设置锁定一个文件的最大尝试次数
deliver_lock_attempts = 5

#设置如果锁定一个文件失败后再次尝试的等待时间
deliver_lock_delay = 1s

#试图重启动一个进程的最大尝试次数
fork_attempts = 5

#每两次尝试之间的等待时间
fork_delay = 1s

#队列管理进程每两次尝试连接一个不正常的投递代理进程之间的等待时间
transport_retry_time = 60s

##开启服务器的smtp认证
smtpd_sasl_auth_enable = yes

##设定 SASL 支持非标准 E-mail Client 的认证动作
broken_sasl_auth_clients = yes

##不使用匿名方式认证
smtpd_sasl_security_options = noanonymous

##指定dmtp认证的本地域名
smtpd_sasl_local_domain = $myhostname
 重启各项服务

/etc/init.d/postfix restart
/etc/init.d/dovecot restart
/etc/init.d/saslauthd restart

 下面是在配置过程中遇到的错误

 1 fatal: open database /etc/aliases.db: No such file or directory

   只要是新搭建postfix都会遇到该错误,需要新建aliases数据库,通过newaliases命令来解决

 2 warning: SASL authentication failure: cannot connect to saslauthd server: No such file or directory

   postfix没有找到saslauthd的工作目录,由于postfix的工作目录默认在/var/spool/postfix/var/run/saslauthd中;而saslauthd默认的工作目录为/var/run/saslauthd中,从而导致postfix无法连接saslauthd服务。所以设置saslauthd的工作目录为/var/spool/postfix/var/run/saslauthd。(在/etc/default/saslauthd文件中设置)

   由于testsaslauthd也是采用saslauthd的默认目录,所以如果saslauthd的工作目录不在/var/run/saslauthd的话,就会无法连接saslauthd服务,需要通过-f选项来指定工作目录。testsaslauthd -f /var/spool/postfix/var/run/saslauthd/mux -u test  -p passwd

 3 warning: SASL authentication failure: cannot connect to saslauthd server: Permission denied

  postfix的权限不够,执行如下命令usermod -G  postfix  sasl 

下面用tenlnet测试:

  因为在saslauth配置文件中选用的shadow认证,所有认证账户需要smtp服务器上的用户,我以账户guol为例,密码也是guol

  先生成base64的加密字符串

#因为密码和用户名一样,就只执行一次即可
echo -n guol | openssl base64 -a
 开始测试(有用户认证的):

telnet mail.xx.com 25
Trying xx.xx.xx.xx...
Connected to mail.xx.com.
Escape character is '^]'.
220 mail.xx.com ESMTP unknow
helo mail.xx.com
250 mail.xx.com
auth login
334 VXNlcm5hbWU6
Z3VvbA==               <---此处为base64加密的用户名
334 UGFzc3dvcmQ6
Z3VvbA==               <---此处为base64加密的密码
235 2.7.0 Authentication successful
mail from:<[email protected]>
250 2.1.0 Ok
rcpt to:<[email protected]>
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
ai ye
.
250 2.0.0 Ok: queued as E2F1218943E
quit
221 2.0.0 Bye
Connection closed by foreign host.

 再次用不经过认证的账户发邮件时则会被拒绝。helo是普通smtp,不带身份验证也可以mail from,如果邮件设置必须身份验证,则到rcpt to才会被拒绝,而ehlo是esmpt,带有身份验证的。

Linux Postfix+Dovecot+sasl

 采用foxmail客户端测试

Linux Postfix+Dovecot+sasl


你可能感兴趣的:(Linux Postfix+Dovecot+sasl)