• Sendmail with SASL and TLS support


     


    提要

    Sendmail 提供了基本的 SMTP 協定(Protocal),並可透過郵件代轉機制 (Relay) 替指定的 IP 做代轉服務,然而並非所有用戶端 (Client) 皆具有固定 IP,此時便可透過 SASL (Simple Authentication and Security Layer,SASL) 提供使用者做認證以便提供 SMTP 服務。而 SASL 所提供的密碼交換協定是以明文 (Plaintext) 形式來傳遞,再安全上有相當大的疑慮,TLS (Transport Layer Security) 提供了解決方案,他可提供連線時期的加密傳輸,同時可避免密碼以明文方式傳遞,並確保郵件私密性。

    系統環境

    Ubuntu 5.10 (Debian)
    Sendmail 8.12.10
    SASL 2.1.21
    OpenSSL 0.9.7e

    介紹

    SASL (Simple Authentication and Security Layer)

    原始的 SMTP 不具備驗證能力,在 RFC 2554 (SMTP Service Extension for authentication) 中制定如何在 SMTP protocol 加上驗證機制,透過 SASL 協定便可進行使用者認證。RFC 2222 (Simple Authentication and Security Layer) 制定了基本規範。在設定 SASL 之前須決定 1.驗證機制 (authentication mechanism) 2. 驗證架構 (authentication framework)

    驗證機制 (authentication mechanism)

    驗證機制就是在初始連線時期規範 Server 與 Client 端如何應答。 大致上包含:

    PLAIN
    PLAIN 是最容易使用的機制,卻也相當危險,因為使用者的帳號密碼會以 base64 格式傳送,未進行加密保護。通常會搭配 TLS 使用。

    LOGIN
    LOGIN 不是正式支援的機制,通常是舊版的 MUA會使用到,例如 Outlook Express 5 之前版本。整體而言 LOGIN 和 PLAIN 相當類似。

    KERBEROS
    Kerberos 是一種網路認證協定。詳細資料可參考官方網頁

    OTP(S/KEY)
    OTP (One-Time Passwords),基於 MD5 演算法的單次密碼驗證機制,此機制無加密保護,因為密碼只用一次,沒有加密的必要。也因而每次連線都須改用新密碼。另外 SMTP Client 端須能產生 OTP 憑證。RFC 2444 (The One-Time Password SASL Mechanism)

    DIGEST-MD5
    DIGEST-MD5 認證方式,Client 和 Server 端共用一個 secret password,真實密碼不透過網路傳輸。驗證方式是由 Server 端送出 challenge 給 Client,而 Client 利用 secret password 計算 response 給 server。不同的 challenge 會算出不同的 response ,而擁有 secret password 的人都可對相同的 challenge 算出同樣的 response。這樣的驗證程序只須傳送 challenge 和 response,真實的密碼不會在網路上傳送,即使被 Sniffer 也沒關係。雖然近來有人提出 MD5 Collision 的討論,但 MD5 仍是主流加密演算法之一。RFC 1321 (The MD5 Message-Digest Algorithm) ftp://ftp.rfc-editor.org/in-notes/rfc1321.txt

    CRAM-MD5
    CRAM-MD5 認證方式曾經是在 LDAPv3 Server 上廣為推薦,已逐漸被 DIGEST-MD5 所取代,兩者的關係好比 PLANT 和 LOGIN。

    ANONYMOUS
    ANONYMOUS 在 SASL 上面是沒有意義的,之所以要進行認證就是為了不要讓人任意使用造成 Open relay。SASL 支援 ANONYMOUS 是為了支援其他的協定。

    驗證架構 (authentication framework)

    決定了驗證機制之後,驗證架構是決定 Server 端如何紀錄使用者憑證,以及如何檢驗 Client 所提供的密碼。大致包含了:PAM、SASLdb、Berkeley DB、SQL、LDAP。其中較為常見的是 PAM 與 SASLdb 兩種認證方式。

    PAM
    通常 Unix-like 上的系統密碼檔是 /etc/passwd,不過近來因安全性考量,密碼部分可能會在 /etc/shadow,這些檔案僅有 super user 可以存取。若要使用 Unix 系統上的密碼檔,一般會透過 saslauthd 這個 daemon 提供存取密碼檔的工作,但是透過 saslauthd 認證,僅能使用 plaintext password,因為 saslauthd 需要真實密碼才能夠進行驗證。

    SASLdb
    SASLdb 是 SASL 所支援的其中一種 auxprop (Auxiliary Property Plug-ins),上面所提過的 LDAP、SQL 等等也是 auxprop。使用 SASLdb 不必透過 saslauthd daemon,但是因為他是另外建立一個密碼檔,需要特別注意將需要使用認證的程式都能夠存取 SASLdb。
    需要產生或者維護 SASLdb 可以直接使用 Cyrus SASL 內建的工具 saslpasswd2。例如:
    #saslpasswd2 -c -u hostname testuser
    Password:
    Again (for verification):

    選項 -c (create),-u (Hostname), 最後是 username。

    TLS (Transport Layer Security)

    RFC 3207 (SMTP Service Extension for Secure SMTP over Transport Layer Security)中制定了 STARTTLS 的 SMTP 擴充機制,用來保障 TCP 通訊的隱私性與完整性,與 SASL 結合,可避免密碼以明文型是在網路上傳輸。另外,這裡需要特別注意,TLS 僅是在連線時期加密,當郵件送達 Server 端時仍是未加密的,若需要完整加密可以參考 PGP 或是 GnuPG 

    憑證 (Certificate)

    要保障 TLS 連線時的私密性,便是透過憑證 (certificate) 來確保 Server 的可信度。而憑證需從具公信力的 CAs (Certificate Authorities) 取得。
    談到憑證就需先提到公鑰 (Public key) 與私鑰 (Private Key) 的加密技術。以公鑰加密的資料只有私鑰可以解的開,反之,以私鑰加密的資料可由公鑰解密。這樣可以保障什麼事情呢?
    接收加密:第三方可以使用公鑰加密資料傳送,僅有私鑰擁有者可解密。
    傳送加密:以私鑰加密過的文件,可使用對應的公鑰解開,確保此文件來自私鑰擁有者。(此動作通常稱為簽署)

    而取得一份公鑰時,要如何確保該公鑰所宣稱之擁有者為實呢?此時便需要第三方具備公信力的 CA 來背書,而具有 CA 背書的公鑰稱為憑證 (Certificate)。基於信任 CA 的立場,可相信該公鑰確實為期所宣稱之擁有者。

    公私鑰加密僅在 TLS 的連線初期使用,運作流程大約如下:
    1. Client 對 SMTP Server 發出 STARTTLS 要求加密連線
    2. Server 發出具備 CA 背書的憑證,並加上 CA 本身的根憑證
    3. Client 端檢驗兩個憑證之可信度。
    4. 若 Client 接受憑證便開始 session key 的協商。
    而實際連線時期加密動作是使用該 session key 來進行。

    憑證由許多政府單位或公司所成立之 CA 取得,例如:
    VeriSign
    政府憑證管理中心(GCA)

    安裝與設定

    安裝 SASL v2
    Ubuntu(Debian)
    $sudo apt-get install sasl2-bin libsasl2

    Tarball
    $cd /tmp
    $wget ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/cyrus-sasl-2.1.21.tar.gz
    $tar zxvf cyrus-sasl-2.1.21.tar.gz
    $cd cyrus-sasl-2.1.21
    $./configure
    $make
    $sudo make install
    $sudo ln -s /usr/local/lib/sasl2 /usr/lib/sasl2

    安裝 OpenSSL
    Ubuntu(Debian)
    $sudo apt-get install openssl

    Tarball
    $cd /tmp
    $wget http://www.openssl.org/source/openssl-0.9.8a.tar.gz
    $tar zxvf openssl-0.9.8a.tar.gz
    $cd openssl-0.9.8a
    $./configure
    $make
    $sudo make install

    安裝憑證
    一般我們會從 CA 取得三個檔案
    1. CA 本身的根憑證 (CA_cert.pem)
    2. 向 CA 所申請的公鑰及私鑰 (server_cert.pem, server_key.pem)
    將三個檔案放在 /etc/mail/certs/

    編譯 Sendmail
    在 Ubuntu 5.10 下使用 aptget 安裝的 Sendmail 預設已編入 SMTP AUTH(SASL)與 STARTTLS(SSL),不用重新編譯就可以使用 SASL 及 SSL。
    檢查是否已編譯 SASL 與 STARTTLS
    $sendmail -bt -d0.1
    Version 8.13.2
    Compiled with: DNSMAP LDAPMAP LOG MAP_REGEX MATCHGECOS MILTER MIME7TO8
    MIME8TO7 NAMED_BIND NETINET NETINET6 NETUNIX NEWDB NIS NISPLUS
    PIPELINING SASLv2 SCANF SOCKETMAP STARTTLS TCPWRAPPERS USERDB
    USE_LDAP_INIT XDEBUG

    若無 SASLv2 與 STARTTLS 則須重新編譯 Sendmail。
    $sudo tee -a /usr/src/sendmail-8.13.2/devtools/Site/site.config.m4
    APPENDDEF(`conf_sendmail_ENVDEF',`-DSASL')
    APPENDDEF(`conf_sendmail_LIBS',`-lsasl')
    APPENDDEF(`conf_sendmail_ENVDEF',`-DSTARTTLS')
    APPENDDEF(`conf_sendmail_LIBS',`-lssl -lcrypto')
    dnl The following lines are used to enable the STARTTLS function
    define(`CERT_DIR', `/etc/mail/certs')dnl
    define(`confCACERT_PATH', `CERT_DIR')dnl
    define(`confCACERT', `CERT_DIR/CA_cert.pem')dnl
    define(`confSERVER_CERT', `CERT_DIR/server_cert.pem')dnl
    define(`confSERVER_KEY', `CERT_DIR/server_key.pem')dnl
    define(`confCLIENT_CERT', `CERT_DIR/server_cert.pem')dnl
    define(`confCLIENT_KEY', `CERT_DIR/server_key.pem')dnl
    dnl 設定 mechaninsms
    define(`confAUTH_MECHANISMS',`CRAM-MD5 DIGEST-MD5 LOGIN PLAIN')dnl
    TRUST_AUTH_MECH(`CRAM-MD5 DIGEST-MD5 LOGIN PLAIN')dnl
    FEATURE(`access_db')dnl
    ^D

    $cd /usr/src/sendmail-8.13.2/
    $./Build -c
    $cd sendmail
    $sudo ./Build install
    $kill -HUP'head -1 /var/run/sendmail.pid'

    修改 saslauthd
    #vi /etc/default/saslauthd
    START=yes # unmark,以便開機自動執行
    MECHANISMS="pam" # 設定欲使用之認證架構

    測試

    測試是否支援 SASL 

    tester -01:42- [/usr/bin]-socrates-t localhost 25
    Trying 127.0.0.1...
    Connected to localhost.localdomain.
    Escape character is '^]'.
    220 localhost.localdomain ESMTP Sendmail 8.13.2/8.13.2/Debian-1; Mon, 28 Nov 2005 01:42:02 +0800; (No UCE/UBE) logging access from: localhost.localdomain(OK)-localhost.localdomain [127.0.0.1]
    ehlo localhost
    250-localhost.localdomain 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 DIGEST-MD5 CRAM-MD5 LOGIN PLAIN
    250-DELIVERBY
    250 HELP

    參考資料

    SASL

    Cyrus

  • 相关阅读:
    【Spring-Security】Re01 入门上手
    【JDBC】Extra03 PostgreSQL-JDBC
    【JDBC】Extra02 SqlServer-JDBC
    【JDBC】Extra01 Oracle-JDBC
    【Oracle】Windiws-11G 安装
    【Hibernate】Re08 加载策略配置
    【Hibernate】Re07 关系映射处理
    【Hibernate】Re01.6 HQL
    【Hibernate】Re01.5 API
    【Quartz】
  • 原文地址:https://www.cnblogs.com/huqingyu/p/956867.html
Copyright © 2020-2023  润新知