STARTTLS介绍

一、SMTP和STARTTLS

SMTP 协议默认使用明文在网络传送用户名和密码,这是十分危险的。为此,sendmail使用TLS来解决这个潜在的危险问题。TLS不仅可以用来加密用户名和密码,还可以加密传送信件的内容。Sendmail使用starttls命令来启动一个SMTP会话加密进程(TLS会话)。Micorsoft的 outlook软件和其它的许多MUA也支持STARTTLS。

STARTTLS能实现什么样的功能?

1.实现对一次E-MAIL通讯中server端以及client端彼此身份的校验;
2.加密传输信件(身份不能确认的情况下亦可以实现);
3.认证转发;

由于SMTP是一个存储转发协议,并且一封电子邮件的转交投递可能会涉及到多台SMTP服务器,因此,一个MUA就算能够通过认证并把E-MAIL加密传输至将要经过的第一台SMTP服务器,让最终用户的SMTP通过发送端的身份认证,并认为信件传送过程中没有被篡改也是不太可能的。故而,RFC文件声明说一个实现公共Email的SMTP服务器是不必苛求于在传送邮件中实现上述功能的。不过,对于一个私有网络中的邮件传输来讲,能够以要求必需提供有效证书来实现严格的身份认证和加密传输,因为我们可以将证书部署到需要传送EMAIL服务的每个客户端。

当然,尽管基于TLS的SMTP服务所提供的功能不像基于SSL的HTTP服务那样完美,但在服务器和客户端之间的一次认证会话间加密传输用户名和密码却是完全可以实现的。

二、STARTTLS的工作方式:

1.sendmail作为服务端

在一次SMTP会话中,客户端(可能是其它的SMTP服务器,也可能是一个终端用户的MUA)通过EHLO命令来探测服务器是否支持STARTTLS。如果服务器支持此种方式,客户就把STARTTLS列入可以使用的命令列里面。此时,客户端便可以通过STARTTLS命令来和服务器建立STARTTLS 话,服务器以“准备好启动TLS”来回应客户端。

如果客户端能够提供一个SSL证书,Sendmail将会从中提取出有关CA的信息并和自己信任的CA列表进行比较,并尝试将证书中的common name和客户端的主机名加以比较。同时,Sendmail还将会检查客户端的证书是否已经存在于自己的访问数据库中。如果一切顺利通过,Sendmail将继续后面的会话。实际使用中,即使Sendmail无法验证客户端的证书,它也会接受客户端会话。我们可以在TLS日志中找到有关的详细信息,如果验证顺利进行,将会出现类同“verify=OK"之类的日志记示,否则,则可能显示为“verify=FAIL”或者 “verify=NO”。

在无法验证客户端身份的情况下,Sendmail也将尝试实现信件加密传送。此时,日志中如果记录有类同“ciper=DHE-RSA-AES256-SHA,bit=256/256"的信息,表示加密成功实现。加密协商会话成功实现后,服务器端可能会使用基于PLAIN或者LOGIN的SMTP AUTH方式来验证身份,此时,STARTTLS将会把用户各和密码加密传送,从而在很大程度保证了会话的安全性。

2.Sendmail作为客户端

当 Sendmail服务器为最终用户或者其它的Sendmail转发信件时,它将作为一台客户端与其它的SMTP服务器通信。此时,如果服务端支持 STARTTLS,即使双方没有配置证书的情况下,Sendmail(前提是也支持STARTTLS)仍将通过STARTTLS命令与其建立通信会话。其过程类同前面所述。

日志中将会记录类同“STARTTLS=client”(客户端)或者“STARTTLS=server”(服务端)以及有关版本号、校验方式、加密方式和加密位数等信息。

安装过程

本文将以RedHat9.0为例

一、安装cyrus-sasl

本文使用系统自带的saslauthd认证服务,请检查你的系统是否已经安装如下软件,如果没有的话,请自行安装

1.# rpm -aq |grep cyrus-sasl

    cyrus-sasl-devel-2.1.10-4
    cyrus-sasl-2.1.10-4
    cyrus-sasl-plain-2.1.10-4
    cyrus-sasl-md5-2.1.10-4

2.新建/usr/local/lib/sasl2/Sendmail.conf,添加如下内容:
   pwcheck_method: saslauthd
   mech_list: login plain digest-md5

3.启动服务
  #service saslauthd start
  #chkconfig --level 35 saslauthd on

二、安装openssl0.98e

1.下载相关软件包至/usr/local/src目录

http://www.openssl.org/source/openssl-0.9.8e.tar.gz

2.安装

#cd /usr/local/src
#tar zxvf openssl-0.9.8e.tar.gz
#cd openssl-0.9.8e
#./config shared zlib
#make
#make test
#make install
mv /usr/bin/openssl /usr/bin/openssl.OFF
mv /usr/include/openssl /usr/include/openssl.OFF
ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl
ln -s /usr/local/ssl/include/openssl /usr/include/openssl

3.配置库文件搜索路径
  #echo "/usr/local/ssl/lib" >> /etc/ld.so.conf

  #ldconfig -v

4.查看openssl的版本号,以验正是否安装正确

#openssl version -a
OpenSSL 0.9.8e 23 Feb 2007
built on: Sat Mar 24 21:24:41 CST 2007
platform: linux-elf
options:  bn(64,32) md2(int) rc4(idx,int) des(ptr,risc1,16,long) idea(int) blowfish(idx)
compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2 -DSHA1_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM
OPENSSLDIR: "/usr/local/ssl"

三、安装Sendmail-8.14.0

1.下载相关软件包至/usr/local/src目录

ftp://ftp.sendmail.org/pub/sendmail/sendmail.8.14.0.tar.gz

2.先检查本机是否已经开启了MTA,若有,先关闭并卸载它们,如:

#service sendmail stop
#rpm -e sendmail
3. 安装:

解压原码包 
#cd /usr/local/src
#tar zxvf sendmail.8.14.0.tar.gz
#cd sendmail-8.14.0
编辑site.config.m4文件

#vi devtools/Site/site.config.m4
添加:
APPENDDEF(`confENVDEF',`-DSASL=2')
APPENDDEF(`conf_sendmail_LIBS',`-lsasl2')
APPENDDEF(`confINCDIRS',`-I/usr/local/ssl/include')dnl
APPENDDEF(`conf_sendmail_ENVDEF',`-DSTARTTLS')
APPENDDEF(`conf_sendmail_ENVDEF',`-D_FFR_SMTP_SSL')
APPENDDEF(`conf_sendmail_LIBS',`-lssl -lcrypto -L/usr/local/ssl/lib')
编译并安装

#sh Build
#mkdir -pv /usr/man/man{1,8}
#sh Build install

拷贝cf目录至/usr/share/sendmail 
#mkdir -pv /usr/share/sendmail
#cp -a cf /usr/share/sendmail

#cd cf/cf
#cp generic-linux.mc sendmail.mc

编辑sendmail.mc文件,添加如下内容:

include(`/usr/share/sendmail/cf/m4/cf.m4')dnl
FEATURE(`access_db')dnl
define(`confAUTH_MECHANISMS',`A p y')dnl
define(`confAUTH_MECHANISMS',`LOGIN PLAIN DIGEST-MD5')dnl
TRUST_AUTH_MECH(`LOGIN PLAIN DIGEST-MD5')dnl
define(`confCACERT_PATH',`/etc/mail/certs')dnl
define(`confCACERT',`/etc/mail/certs/cacert.pem')dnl
define(`confSERVER_CERT',`/etc/mail/certs/mysmtp.pem')dnl
define(`confSERVER_KEY',`/etc/mail/certs/mysmtp.pem')dnl
define(`confCLIENT_CERT',`/etc/mail/certs/mysmtp.pem')dnl
define(`confCLIENT_KEY',`/etd/mail/certs/mysmtp.pem')dnl
dnl define(`confTLS_SRV_OPTIONS',`V')dnl
FEATURE(`no_default_msa')dnl
DAEMON_OPTIONS(`Port=25,Name=MTA,M=Ea')dnl
DAEMON_OPTIONS(`Family=inet,Port=465,Name=MTA-SSL,M=s')dnl

安装sendmail.cf及submit.cf文件
#make install-cf

#cp sendmail.mc /etc/mail

添加必须的用户组(redhat9.0上,已经存在此用户和组)

#groupadd –g 51 -r smmsp
#useradd –u 51 -r -g smmsp -s /sbin/nologin smmsp

添加必要的配置文件

#cd /etc/mail

#touch aliases access  virtusertable

添加接收邮件的域

#echo "benet.org">local-host-names
#echo "mail.benet.org">>local-host-names

配置转发域

#echo "localhost  RELAY" >> access
#echo "127.0.0.1  RELAY" >> access

生成相应的数据库文件

#makemap hash access.db < access
# makemap hash virtusertable &lt; virtusertable

改变相关目录的权限,以保证安全(RedHat 9.0上已经设置正确)

#mkdir -pv /var/spool/{mail,mqueue,clientqueue}

#chmod 775       /var/spool/mail
#chown root.mail /var/spool/mail

#chmod 755       /var/spool/mqueue
#chown root.mail /var/spool/mqueue

#chmod 770         /var/spool/clientmqueue
#chown smmsp.smmsp /var/spool/clientmqueue

chmod 4555      /usr/sbin/sendmail
chown root.smmsp /usr/sbin/sendmail

四、为TLS生成证书:

#cd /etc/mail/certs/

生成CA的签名及证书

# openssl req -new -x509 -keyout cakey.pem -out cacert.pem -days 3650

Generating a 1024 bit RSA private key
...............................++++++
.....++++++
writing new private key to 'cakey.pem'
Enter PEM pass phrase:      &lt;----此处输入CA密码
Verifying - Enter PEM pass phrase:    &lt;----重复上个密码
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN    &lt;----此处为国家名
State or Province Name (full name) [Some-State]:HA    &lt;----此处为地域(省)名
Locality Name (eg, city) []:ZZ    &lt;----此处为城市名
Organization Name (eg, company) [Internet Widgits Pty Ltd]:BENET  &lt;----此处为单位名
Organizational Unit Name (eg, section) []:    &lt;----此处为部门名
Common Name (eg, YOUR name) []:    &lt;----此处为你的名字或服务器的名字,也可省略
Email Address []:redhat@benet.org    &lt;----此处为管理邮件

生成Sendmail的证书
# openssl req -nodes -new -x509 -keyout mysmtp.pem -out mysmtp.pem -days 3650

Generating a 1024 bit RSA private key
..++++++
...................................++++++
writing new private key to 'mysmtp.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:HA
Locality Name (eg, city) []:ZZ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:BENET
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:
Email Address []:redhat@benet.org

查看证书内容
# openssl x509 -noout -text -in mysmtp.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            e7:3a:cf:c4:2c:e9:71:8f
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=CN, ST=HA, L=ZZ, O=BENET/emailAddress=redhat@benet.org
        Validity
            Not Before: Mar 24 14:19:21 2007 GMT
            Not After : Mar 21 14:19:21 2017 GMT
        Subject: C=CN, ST=HA, L=ZZ, O=BENET/emailAddress=redhat@benet.org
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:f6:17:f8:27:be:9b:c6:b9:b0:b3:0b:0c:62:c1:
                    7e:cd:19:80:62:b4:83:91:ec:a3:b1:83:df:77:6f:
                    12:83:56:94:6c:e3:e0:5a:a7:20:75:60:d3:92:00:
                    18:9a:e5:fc:3a:27:93:bc:10:60:4b:f3:d1:b4:43:
                    5c:af:17:f9:de:72:04:3a:8e:12:f1:19:c5:11:28:
                    9c:08:f6:fe:b0:db:e6:c5:8c:c1:c8:d2:86:f2:0a:
                    d7:b3:a3:e3:08:d0:5b:8c:5a:03:d7:87:0d:4e:56:
                    62:2b:54:3c:f7:ea:70:03:53:96:4d:bc:ac:f8:de:
                    cd:2b:87:6f:24:79:d0:8b:a3
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                C7:1B:1C:D0:58:B2:A7:19:7F:F1:8C:DB:D0:C9:49:24:A4:BA:B3:FA
            X509v3 Authority Key Identifier:
                keyid:C7:1B:1C:D0:58:B2:A7:19:7F:F1:8C:DB:D0:C9:49:24:A4:BA:B3:FA
                DirName:/C=CN/ST=HA/L=ZZ/O=BENET/emailAddress=redhat@benet.org
                serial:E7:3A:CF:C4:2C:E9:71:8F

            X509v3 Basic Constraints:
                CA:TRUE
    Signature Algorithm: sha1WithRSAEncryption
        a5:c0:58:52:f4:db:76:78:d3:05:d3:36:a9:7e:ef:05:4a:01:
        93:3f:64:48:8a:66:36:20:25:c1:b2:93:b6:a4:05:1b:6e:55:
        c6:21:ec:70:a1:41:d8:0f:cd:46:d6:8f:f2:e8:48:c2:0d:5f:
        9e:2f:dd:af:61:f6:ca:08:16:20:7c:b5:e6:38:58:d8:e7:cd:
        92:d9:35:00:93:70:5d:04:d0:4c:d0:33:e6:49:18:30:a7:1b:
        0e:3b:d0:3f:82:ce:6e:03:da:96:32:7b:8a:69:9e:8e:0b:8b:
        ab:ea:9a:40:c8:b3:a8:f5:62:a5:0e:ab:bf:24:47:aa:02:ef:

        61:0f

×××权限,如果没有此步骤,启动sendmail时会报starttls启动错误

#chmod 400 mysmtp.pem

五、启动并验正Sendmail

1.执行如下命令,查看sendmail是否sasl2方式的身份认证(按我们如上的步骤编译安装,sendmail是支持此认证的)及starttls:

# sendmail -d0.1 -bv root
Version 8.14.0
Compiled with: DNSMAP LOG MATCHGECOS MILTER MIME7TO8 MIME8TO7
                NAMED_BIND NETINET NETUNIX NEWDB PIPELINING SASLv2 SCANF
STARTTLS USERDB XDEBUG

============ SYSTEM IDENTITY (after readcf) ============
      (short domain name) $w = mail
  (canonical domain name) $j = mail.benet.org
         (subdomain name) $m = benet.org
              (node name) $k = mail.benet.org
========================================================

root... deliverable: mailer local, user root

请查看执行结果中是否显示为橙色字体的部分。如果有,则可进行以下步骤,否则,请检查前面的编译安装过程是否有遗漏或错误之处,或者查看日志以检查错误之所在。也可以运行如下命令仔细检查问题所在。

#sendmail -O loglevel=14 -bs

2.启动sendmail,

#sendmail -bd -q30m
注:Sendmail的命令参数的含义如下:

   -b:指定Sendmail在后台运行,并且监听端口25的请求。
   -d:指定Sendmail以Daemon方式运行(守护进程)。
   -q:当Sendmail无法将邮件成功地发送到目的地时,它会将邮件保存在队列里。该参数指定邮件在队列里保存的时间。例子里的30m表示保留30分钟。

3.查看Sendmail对于认证及TLS的支持是否已经打开

# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.benet.org ESMTP Sendmail 8.13.8/8.13.8; Sun, 25 Mar 2007 01:46:08 +0800
ehlo localhost    &lt;--此句为输入的命令
250-mail.benet.org Hello localhost.localdomain [127.0.0.1], pleased to meet you
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-EXPN
250-VERB
250-8BITMIME
250-SIZE
250-DSN
250-ETRN
250-AUTH LOGIN PLAIN DIGEST-MD5
250-STARTTLS
250-DELIVERBY
250 HELP

请注意查看输出中有没有类同橙色的两行。
六、开启基于SSL的IMAP服务
1.检查是否已经安装imap软件包,如果没有,请自行安装
#rpm -qa |grep imap
imap-2001a-18
imap-devel-2001a-18
2.开启imaps服务
#chkconfig imaps on
# chkconfig --list imaps
imaps           on
3.重新启动xinetd服务
#service xinet.d restart
4.查看是否已经监听相应的993端口:
#netstat -tnlp |grep :993
tcp        0      0 0.0.0.0:993             0.0.0.0:*               LISTEN      32477/xinetd

七、验正
1.使用outlook客户端登录,测试发信情况,注意如下设置:

Outlook设置1

Outlook设置2

2.查看日志
#tail /var/log/maillog
Mar 25 03:58:55 mail sendmail[1962]: STARTTLS=server, relay=[192.168.1.100], version=TLSv1/SSLv3, verify=NO, cipher=RC4-MD5, bits=128/128
Mar 25 03:58:55 mail sendmail[1962]: AUTH=server, relay=[192.168.1.100], authid=redhat, mech=LOGIN, bits=0
Mar 25 03:58:55 mail sendmail[1962]: l2OJwsnF001962: from=&lt;redhat@benet.org>, size=1700, class=0, nrcpts=1, msgid=<003601c76ed5$6a012da0$6400a8c0@microsofde20f2>, proto=ESMTP, daemon=MTA-SSL, relay=[192.168.1.100]
Mar 25 03:58:55 mail sendmail[1963]: l2OJwsnF001962: to=<root@benet.org>, ctladdr=<redhat@benet.org> (500/500), delay=00:00:00, xdelay=00:00:00, mailer=local, pri=31953, dsn=2.0.0, stat=Sent