Linux运维第三阶段(十)postfix
postfix
mail-server:
SMTP(simple mail transfer protocol):功能简陋,无法实现用户认证、邮件存储、检索邮件等,所以功能简单,仅负责将邮件从发送方传输到目的方,能实现传输路由功能,TCP/25port
SMTPS(secure安全版)
ESMTP(entended SMTP):仅实现检测用户身份,无法实现认证,功能增强版
POP3(post office protocol):邮局协议version3,TCP/110port
IMAP4(internet mail access protocol):互联网邮件访问协议,TCP/143port,功能与pop3近似,比pop3要强大,但消耗资源多,所以众多站点用pop3
UUCP(unix to unix protocol):UNIX主机复制文件的协议,功能简陋
SASL(simple authentication secure layer):简单认证安全层,提供安全认证框架,服务名saslauthd,现使用V2,软件cyrus-sasl、courier-authlib
注:smtp,pop3与imap4均明文plaintext方式工作(可借助ssl加密传输,如smtps,pop3s,imaps仅能保证传输过程加密,例:smtp-->smtps并不能真正保证邮件的安全性,起码要保证两段,其中本地MUA-->smtpd-->smtp,本地到远端smtp-->smtpd(dst),远端smtpd-->MDA-->邮箱,若远端的邮箱可被其它人访问,也是不安全的)
S/MIME(secure/multi internet mail extended):USER<-->USER,每个用户都有一个独立的证书(用户证书,公信的CA颁发)
(写好一封mail,用单向加密算法生成指纹finger print(hash),使用自己的私钥加密指纹,用一次性会话密钥加密前面数据,再用对方的公钥加密总的数据,传至对方)
openssl(GPG(软件GNU privacyguard)是PGP(privacy guard protocol)的一种实现
MUA(mail user agent):mutt(linux文本界面)、mail命令(linux)、outlook(windows)、foxmail、thunderbird、evolution
MTA(mail transfer agent):SMTP服务器、sendmail(主流地位,互联网邮件服务的鼻祖,UUCP、单体结构、SUID、配置文件语法m4编写)、qmail(比sendmail效率快近20倍)、postfix(目前流行,模块化设计、安全、与sendmail兼容、不使用SUID、效率比sendmail快至少4倍)、exim(英国剑桥)、exchange(win下使用,异步消息协作平台)
MDA(mail delivery agent):邮件投递代理,软件:procmail、maildrop(独立的服务,抽取邮件文本信息的特征码实现垃圾邮件过滤)
MRA(mail retrieval agent):邮件检索(取回)代理(pop3、imap4协议),软件:cyrus-imap、dovecot(鸽子笼)
Webmail:openwebmail(perl)、squinelmail(php)、Extmail,Extman(extmanager,centos下EMOS)
注:每个主机都有client(smtp发邮件)和server(smtpd接收邮件);用MUA编辑好邮件通过SMTP协议发送至smtpd,若收件方是本地域,smtpd则直接投递至邮件中转站(邮箱)中,若是远程主机则smtpd转至smtp,smtp向远端服务器的smtpd传送;一个服务器若有多个MX记录,找优先级高的;借助于认证工具实现要提供帐号密码才可发送邮件(协议使用SASL)
open-relay:开放式中继,是本地的接收,不是本地的都转发,源到目的不是中继,open-relay这种方式保证了邮件就算被误传了最终也能放到真正的目的地,但垃圾邮件就此开始了,而且这有被滥用的风险(例如某用户编辑了1000封邮件,放至你的服务器发送,则其它服务器都认为你的邮件服务器是垃圾制造者),一般关闭开放式中继,仅允许本地用户中继
(举例tom@magedu.com发邮件至clair@b.net,开启转发功能,则会将邮件正确发送至b.net,b.net看到的是a.org发来的邮件(与他建立连接的是a.org),,仅主机是a.org,发件人和主机间没有必然联系)
LDAP(lightweight directory access protocol):轻量级目录访问协议,存放帐号密码,把数据结构进行组织,速度无与伦比的快,缺点(读快写慢,还不成熟),适合场景(大规模用户账号系统,资源系统,服务信息检索系统,一次写入多次读取),放帐号密码至LDAP比放mysql快至少10倍,win-server对LDAP支持很好,redhat中介绍LDAP用了一本书讲解
就算用户量不大也应该采取mysql存放账号密码,与系统中的用户账号密码区别开来(/etc/{passwd,shadow}),避免***OS,mysql中存放的账号密码仅用于访问某服务的数字标识(虚拟用户)
pop3自身有mysql访问驱动、LDAP访问驱动,来完成账号密码验证;而smtp是借助于SASL(SASL本身是在/etc/passwd中找),给SASL附加一个工具让其可以到mysql中检索数据
www.postfix.org
注:redhat提供postfix的rpm包安装,但不支持sasl认证(虚拟用户),redhat5默认安装sendmail(系统中任务计划管理需要邮件提示用户执行情况),redhat6默认安装postfix
准备环境:
本例:centos5.8-x86_64、mysql5.5.45(二进制包安装,参照文档<理解LAMP>)、postfix2.9
安装软件组:Development Libraries、Development Tools、Legacy Software Development、X SoftwareDevelopment
安装软件包:httpd, tcl, tcl-devel, libart_lgpl, libart_lgpl-devel, libtool-ltdl,libtool-ltdl-devel, expect
注:redhat中编译某一软件,若编译的这个软件依赖于某包,则依赖的包的devel包一定要装上(提供开发库和头文件),例如:编译postfix时依赖sasl包,那么sasl-devel包就一定要装上;编译httpd时依赖openssl,则openssl-devel包一定要装上。
注:编辑修改某一配置文件时,最好先备份一份再修改,修改时要复制一行再改动。
#service sendmail stop
#chkconfig sendmail off
#rpm -e --nodeps sendmail
#yum list all | grep cyrus-sasl(确保devel包和plain包已安装)
确保mysql已安装
#service saslauthd start
#chkconfig saslauthd on
#tar xf postfix-2.9-20110116.tar.gz
#cd postfix-2.9-20110116
#less INSTALL
#groupadd -g 2525 postfix
#groupadd -g 2526 postdrop
#useradd -u 2525 -g postfix -s /sbin/nologin postfix
#useradd -u 2526 -g postdrop -s /sbin/nologin postdrop
#make makefiles 'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include -DUSE_SASL_AUTH-DUSE_CYRUS_SASL -I/usr/include/sasl -DUSE_TLS' 'AUXLIBS=-L/usr/local/mysql/lib -lmysqlclient -lz -lm-L/usr/lib/sasl2 -lsasl2 -lssl -lcrypto'(CCARGS指定头文件,AUXLIBS指定库文件)
#make
#make install(所有要指定的目录按默认,/usr/sbin下是命令脚本,/usr/libexec/postfix服务器进程,/var/spool/postfix队列进程)
#newaliases(生成别名二进制文件)
为postfix提供sysv脚本(见此文档尾)
#service postfix start
#netstat -tnlp(0.0.0.0:25所有地址,且是master进程)
#tail /var/log/maillog
#vim /etc/postfix/master.cf(主进程配置文件,模块化设计,有主进程、辅助进程)
#vim /etc/postfix/main.cf(功能配置文件;格式:参数 = 值)
注:每行参数要顶格写,若前面有空格则表示上一行的延续
myhostname = mail.magedu.com(邮件服务器自己的主机名,#hostname的结果)
mydomain = magedu.com
myorigin = magedu.com(邮件地址伪装,会自动修改为root@magedu.com;发邮件时只写用户名不写@后内容,则会自动补上此行的值)
mydestination = $myhostname, localhost.$mydomain,localhost, $mydomain(允许使用$PARAMETER;发邮件时@后的内容是此处设定的值时才接收邮件,否则就要中继)
mynetworks = 192.168.101.0/24, 127.0.0.0/8(设置允许给哪些主机中继,一般设为本地网络;若只写127.0.0.0/8,则发往本网络其它主机邮件的地址会被当作外网地址)
#man postconf(命令行配置工具)
#postconf -d(显示默认配置信息Print default parameter settings instead of actual settings)
#postconf -n(显示更改的配置Print parameter settings that are not left at their built-in default value, because they areexplicitly specified in main.cf)
#postconf -m(显示支持的查找表类型List the names of all supported lookup table types)
#postconf -A(客户端支持的SASL插件类型List the available SASL client plug-in types)
#postconf -a(服务端支持的SASL插件类型List the available SASL server plug-in types.)
#postconf -e PARAMETER=VALUE(更改某参数的配置信息并保存至main.cf中)
smtp状态码:1XX纯信息;2XX正确类信息;3XX上一步操作尚未完成,需要继续补充;4XX暂时性错误;5XX永久性错误
smtp协议命令(原语):
helo(以smtp协议向对方发送信息)
ehlo(以esmtp协议)
mail from:
rcpt to:(至关重要,根据此处信息,服务器来判断是接收还是中继)
data(回车后,输入主题Subject和正文,另起一行以点结束表示发送)
举例:用mail命令给本地用户发送邮件
#telnet localhost 25
ehlo
mail from:obama@whitehouse.com
rcpt to:hadoop(不写@会自动补上main.cf中myorigin设置的值,表示本地域)
data
Subject:How are you?
postfix test!!!
.
quit
#tail /var/log/maillog(注意status为sent状态)
注:在互联网上,邮件服务器依赖DNS,且必须要有PTR记录,否则互联网上的其它服务器会将其视为垃圾,拒收该服务器邮件
alias(postfix依赖邮件别名,来判别用户是否在)
#newaliases(rebuild the database for the mail aliases file,此命令可将/etc/aliases-->hash-->/etc/aliases.db散列成.db格式的hash数据库(键值对数据库),这样检索效率会快得多,最适合查找单个匹配条目,mysql中也有hash索引相关概念)
#vim /etc/aliases(可编辑别名文件,格式如:redhat: hadoop)
redhat: hadoop(注意冒号)
postmaster@magedu.com(的邮件都将转至postmaster@magedu.com)
#postaliase /etc/aliases(将此文件转为hash格式,或用命令#newaliases)
注:postfix默认把本机的IP地址所在网段视为本地网络,为之中继邮件
测试:给redhat用户发邮件,再查看redhat和hadoop的邮件情况
dovecot(MRA)
rpm包方式安装dovecot(依赖于mysql,支持四种协议pop3,pops,imap4,imaps;当用户登录,dovecot去/etc/passwd检索,不依赖于SASL,dovecot自身就能实现用户认证,虽然它能调用SASL)
邮件格式(dovecot两种格式都支持):
mbox(一个文件存储所有邮件,redhat默认,dovecot默认)
maildir(一个文件存储一封邮件,所有邮件存储在一目录中)
#yum -y install dovecot
#rpm -ql dovecot
#vim /etc/dovecot.conf
#service dovecot start
#netstat -tnlp(110,143,提供两种不同方式)
举例:
用win的outlook发邮件
#telnet mail.magedu.com 110(在服务端收邮件)
USER obama(用户名在/etc/passwd中要有记录)
PASS obama(密码)
LIST (查看是否有邮件)
RETR #(输入序号查看邮件)
#tail /var/log/maillog
以上不能实现验证用户身份,仅基于IP就能发邮件
客户端的访问控制:
#postconf -m(可列出支持的查询表类型,有hash,mysql等)
#vim /etc/postfix/access(Postfix SMTP server access table访问控制文件,格式为:PATTERN ACTION)
REJECT(拒绝)
microsoft.com OK(允许)
192.168.1.225 REJECT(PATTERN可以是邮件格式,域名,IP,NETWORK/NETMASK等)
#postmap /etc/postfix/access(将文件转换为hash格式的数据库,/etc/postfix/access.db)
#ls /etc/postfix/access*(确保access和access.db文件都在)
#vim /etc/postfix/main.cf(每个参数后可跟访问控制文件,也可跟内置的限定条件)
smtpd_client_restrictions =check_client_access hash:/etc/postfix/access(connection阶段控制,此处hash:后的文件不写.db,hash就表示access.db的文件)
smtpd_helo_restrictions = check_helo_accessmysql:/etc/postfix/mysql_user(helo阶段控制,限定谁可以发送helo指令)
smtpd_sender_restrictions =check_sender_access hash:/PATH/TO/FILE(mail from:阶段)
smtpd_recipient_restrictions =permit_mynetworks, reject_unauth_destination(允许本地转发,从而关闭openrelay功能,rcpt to:此阶段是必须定义的项,所有的信息都在这段才能真正显示出来能否发送,permit_mynetworks为内置的限定条件)
smtpd_data_restriction = (data阶段)
举例:禁止192.168.101.106在服务器上发邮件
#vim /etc/postfix/access
192.168.101.106 REJECT
#postmap /etc/postfix/access
#vim /etc/postfix/main.cf
smtpd_client_restrictions =check_client_access hash:/etc/postfix/access
#service postfix restart
#postconf -n
在win上IP为106的主机上给root@magedu.com发邮件,会有提示:The message could not be sent because one of the recipients wasrejected by the server. The rejected e-mail address was 'root@magedu.com'.Subject 'test3', Account: '192.168.101.154', Server: '192.168.101.154',Protocol: SMTP, Server Response: '554 5.7.1 <unknown[192.168.101.106]>:Client host rejected: Access denied', Port: 25, Secure(SSL): No, Server Error:554, Error Number: 0x800CCC79
举例:禁止@whitehouse.com这个域的所有用户发邮件
#vim /etc/postfix/access
whitehouse.com REJECT(注意无@)
#postmap !$
#vim /etc/postfix/main.cf
smtpd_sender_restrictions =check_sender_access hash:/etc/postfix/access
#!service
#telnet mail.magedu.com 25
mail from:obama@whitehouse.com
rcpt to:root@magedu.com
554 5.7.1 <obama@whitehouse.com>:Sender address rejected: Access denied
举例:禁止openstack@在本地服务器所有域上接收邮件(本地域的所有主机都不能给hadoop发邮件)
#vim /etc/postfix/recipient
openstack@ REJECT
#postmap /etc/postfix/recipient
#vim /etc/postfix/main.cf
smtpd_recipient_restrictions = check_recipient_accesshash:/etc/postfix/recipient permit_mynetworks, reject_unauth_destination(注意次序,默认的后两个都要有)
#service postfix restart
mail from:root@magedu.com
250 2.1.0 Ok
rcpt to:hadoop
554 5.7.1 <hadoop>: Recipient address rejected:Access denied
为postfix开启基于cyrus-sasl的认证功能
#vim /etc/sysconfig/saslauthd
MECH=shadow(Mechanism to usewhen checking passwords更改此项,默认为pam)
#saslauthd -v(显示支持哪种认证机制authentication mechanisms: getpwent kerberos5 pam rimap shadow ldap)
#testsaslauthd -h
#testsaslauthd -u hadoop -p hadoop(显示0: OK"Success.")
#postconf -a(确保有cyrus)
#vim /etc/postfix/main.cf(添加如下内容)
############################CYRUS-SASL############################
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject_invalid_hostname,reject_non_fqdn_hostname,reject_unknown_sender_domain,reject_non_fqdn_sender,reject_non_fqdn_recipient,reject_unknown_recipient_domain,reject_unauth_pipelining,reject_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
smtpd_sasl_security_options = noanonymous
smtpd_sasl_application_name = smtpd
smtpd_banner = Welcome to our $myhostnameESMTP,Warning: Version not Available!
#vim /usr/lib/sasl2/smtpd.conf
pwcheck_method: saslauthd(说明sasl基于哪种方式认证)
mech_list: PLAIN LOGIN(两种认证机制,outlook基于LOGIN)
#service postfix restart
#service saslauthd restart
#telnet mail.magedu.com 25(测试时将主配置文件main.cf中改mynetworks= 127.0.0.0/8)
ehlo mail.magedu.com(确保有以下两行)
250-AUTH PLAIN CRAM-MD5 DIGEST-MD5 LOGIN
250-AUTH=PLAIN CRAM-MD5 DIGEST-MD5 LOGIN
mail from:root@magedu.com
rcpt to:hadoop@aol.com(hadoop是本地用户但域不是本地域,提示554 5.7.1 <hadoop@aol.com>: Relay access denied)
rcpt to:hello@aol.com(用户和域都不在本地:提示554 5.7.1 <hello@aol.com>: Relay access denied)
rcpt to:bbb@magedu.com(用户不在本地,则提示:550 5.1.1 <bbb@magedu.com>: Recipient address rejected: Userunknown in local recipient table)
mutt的使用(The Mutt MailUser Agent):
#mutt -f PROTOCOL://USERNAME@SERVER
#mutt -f pop://hadoop@mail.magedu.com
#mutt -f pop://hadoop@192.168.101.154
i键返回,r回复,q退出
httpd若要用虚拟主机则要注释中心主机;一台邮件服务器也可以为多个域收发邮件(中心域参数:mydestination,mydomain,myorigin),若要使用虚拟域至少要注释掉mydomain
mydomain = a.org,b.net,c.com……(域要是很多,则可使用查找表,将域名放到一文本文件中,用命令#postmap FILE,将之转换为hash数据库.db格式,缺陷(每次增删时都要使用命令执行);但通过其它程序接口操作更麻烦,建议使用mysql,将账号密码放至库中的表,开发一php网页在页面上对mysql中的账号密码进行操作(在线注册),提交至mysql(或LDAP)
虚拟域<--->用户别名(建立关联关系)
用户账号(虚拟账号):如果给系统账号,别人可以尝试登录服务器,不安全,因此要把账号密码放在非/etc/{passwd,shadow}中,使之仅能访问某服务,而不能登录系统
基于虚拟用户的虚拟域邮件系统架构:如下方附图
附:/etc/rc.d/init.d/postfix(sysv风格启动脚本):
#!/bin/bash
#
# postfix Postfix Mail Transfer Agent
#
# chkconfig: 2345 80 30
# description: Postfix is a Mail TransportAgent, which is the program \
# that moves mail from one machineto another.
# processname: master
# pidfile:/var/spool/postfix/pid/master.pid
# config: /etc/postfix/main.cf
# config: /etc/postfix/master.cf
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ $NETWORKING = "no" ] &&exit 3
[ -x /usr/sbin/postfix ] || exit 4
[ -d /etc/postfix ] || exit 5
[ -d /var/spool/postfix ] || exit 6
RETVAL=0
prog="postfix"
start() {
#Start daemons.
echo-n $"Starting postfix: "
/usr/bin/newaliases >/dev/null 2>&1
/usr/sbin/postfixstart 2>/dev/null 1>&2 && success || failure $"$progstart"
RETVAL=$?
[$RETVAL -eq 0 ] && touch /var/lock/subsys/postfix
echo
return$RETVAL
}
stop() {
#Stop daemons.
echo-n $"Shutting down postfix: "
/usr/sbin/postfixstop 2>/dev/null 1>&2 && success || failure $"$progstop"
RETVAL=$?
[$RETVAL -eq 0 ] && rm -f /var/lock/subsys/postfix
echo
return$RETVAL
}
reload() {
echo-n $"Reloading postfix: "
/usr/sbin/postfixreload 2>/dev/null 1>&2 && success || failure $"$progreload"
RETVAL=$?
echo
return$RETVAL
}
abort() {
/usr/sbin/postfixabort 2>/dev/null 1>&2 && success || failure $"$progabort"
return$?
}
flush() {
/usr/sbin/postfixflush 2>/dev/null 1>&2 && success || failure $"$progflush"
return$?
}
check() {
/usr/sbin/postfixcheck 2>/dev/null 1>&2 && success || failure $"$progcheck"
return$?
}
restart() {
stop
start
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
reload)
reload
;;
abort)
abort
;;
flush)
flush
;;
check)
check
;;
status)
status master
;;
condrestart)
[-f /var/lock/subsys/postfix ] && restart || :
;;
*)
echo$"Usage: $0{start|stop|restart|reload|abort|flush|check|status|condrestart}"
exit1
esac
exit $?
# END
以上是学习《马哥网络视频》做的笔记。