|
SMTP協(xié)議分析
第1章. SMTP概述
1.1. SMTP在郵件通信中的位置 SMTP,即簡單郵件傳送協(xié)議,所對應RFC文檔為RFC821。同http等多數(shù)應用層協(xié)議一樣,它工作在C/S模式下,用來實現(xiàn)因特網上的郵件傳送。SMTP在整個電子郵件通信中所處的位置如圖 1所示。 ![]() 圖 1電子郵件的通信過程 可以看出,SMTP是用來將客戶機上的郵件傳送到服務器上。這里的客戶機是指某次連接中的發(fā)送方,服務器是指相應的接收方。在講解發(fā)送郵件的整個通信過程前,先解釋一下面幾個術語。
1.2. 幾個術語
1.2.1. 郵件 郵件是一種消息的格式,由信封、首部和正文組成。 信封上最重要的是收信人的地址。郵件服務器用這個地址將郵件發(fā)送到收信人所在的郵件服務器上。
首部是由用戶代理或郵件服務器添加的一些信息。包括Received、Message-ID、From、Data、Reply-To、X-Phone、X-Mailer、To和Subject等字段。
正文是是發(fā)送用戶發(fā)給接收用戶報文的內容。RFC 822 規(guī)定正文為NVT ASCII文字行。
更為詳細的說明,請參考RFC821和RFC822等協(xié)議。
1.2.2. 用戶代理
用戶代理UA(User Agent)是用戶與電子郵件系統(tǒng)的交互接口,一般來說它就是我們PC機上的一個程序。Windows上常見的用戶代理是Foxmail和Outlook Express。 用戶代理提供一個好的用戶界面,它提取用戶在其界面填寫的各項信息,生成一封符合SMTP等郵件標準的郵件,然后采用SMTP協(xié)議將郵件發(fā)送到發(fā)送端郵件服務器。
1.2.3. 郵件服務器
郵件服務器是電子郵件系統(tǒng)的核心,它用來發(fā)送和接收郵件。郵件服務器不同于普通PC的是它幾乎是全天工作的,所以它可以在任何時候為用戶提供服務,后面將提到這正是為什么需要郵件服務器的一個重要原因。很多ISP都提供免費的郵件服務器,如126提供smtp.126.com郵件服務器。 郵件服務器向其它郵件服務器轉發(fā)郵件也是采用SMTP協(xié)議。
1.3. 郵件的收發(fā)過程
一般情況下,一封郵件的發(fā)送和接收過程如下。 1) 發(fā)信人在用戶代理里編輯郵件,包括填寫發(fā)信人郵箱、收信人郵箱和郵件標題等等。
2) 用戶代理提取發(fā)信人編輯的信息,生成一封符合郵件格式標準(RFC822)的郵件。
3) 用戶代理用SMTP將郵件發(fā)送到發(fā)送端郵件服務器(即發(fā)信人郵箱所對應的郵件服務器)。
4) 發(fā)送端郵件服務器用SMTP將郵件發(fā)送到接收端郵件服務器(即收信人郵箱所對應的郵件服務器)。
5) 收信人調用用戶代理。用戶代理用POP3協(xié)議從接收端郵件服務器取回郵件。
6) 用戶代理解析收到的郵件,以適當?shù)男问匠尸F(xiàn)在收信人面前。
第2章. SMTP詳解
2.1. 通信過程 一個具體的SMTP通信(如發(fā)送端郵件服務器與接收端服務器的通信)的過程如下。 1) 發(fā)送端郵件服務器(以下簡稱客戶端)與接收端郵件服務器(以下簡稱服務器)的25號端口建立TCP連接。
2) 客戶端向服務器發(fā)送各種命令,來請求各種服務(如認證、指定發(fā)送人和接收人)。
3) 服務器解析用戶的命令,做出相應動作并返回給客戶端一個響應。
4) 2)和3)交替進行,直到所有郵件都發(fā)送完或兩者的連接被意外中斷。
從這個過程看出,命令和響應是SMTP協(xié)議的重點,下面將予以重點講述。
2.2. 命令和響應
2.2.1. 格式 SMTP的命令不多(14個),它的一般形式是:COMMAND [Parameter] <CRLF>。其中COMMAND是ASCII形式的命令名,Parameter是相應的命令參數(shù),<CRLF>是回車換行符(0DH, 0AH)。 SMTP的響應也不復雜,它的一般形式是:XXX Readable Illustration。XXX是三位十進制數(shù);Readable Illustration是可讀的解釋說明,用來表明命令是否成功等。XXX具有如下的規(guī)律:以2開頭的表示成功,以4和5開頭的表示失敗,以3開頭的表示未完成(進行中)。
2.2.2. 一個例子
命令和響應的格式是語法,各命令和響應的意思則是語義,各命令和各響應在時間上的關系則是同步。下面將通過一個簡單的SMTP通信過程來說明協(xié)議的這三個要素。 C:telnet smtp.126.com 25 /* 以telnet方式連接126郵件服務器 */
S:220 126.com Anti-spam GT for Coremail System (126com[071018]) /* 220為響應數(shù)字,其后的為歡迎信息,會應服務器不同而不同*/
C:HELO smtp.126.com /* HELO 后用來填寫返回域名(具體含義請參閱RFC821),但該命令并不檢查后面的參數(shù) */
S:250 OK
C: MAIL FROM: bripengandre@126.com /* 發(fā)送者郵箱 */
S:250 … ./* “…”代表省略了一些可讀信息 */
C:RCPT TO: bripengandre@smail.hust.edu.cn /* 接收者郵箱 */
S:250 … ./* “…”代表省略了一些可讀信息 */
C:DATA /* 請求發(fā)送數(shù)據(jù) */
S:354 Enter mail, end with "." on a line by itself
C:Enjoy Protocol Studing
C:.
S:250 Message sent
C:QUIT /* 退出連接 */
S:221 Bye
分析上面的過程可參考注釋進行,這里要補充如下幾點。
1) “C:”開頭的行(不包括"C:")是客戶端的輸入,而以“S:”開頭的行(不包括"S:")則是服務器的輸出。
2) 上述的命令并不一定會一次性成功,服務器會返回錯誤響應,客戶端應該按照協(xié)議規(guī)定的時序,來輸入后續(xù)的命令(或重復執(zhí)行失敗的命令,或重置會話,或退出會話等等)。
2.2.3. 常用命令
SMTP命令不區(qū)分大小寫,但參數(shù)區(qū)分大小寫,有關這方面的詳細說明請參考RFC821。常用的命令如下。 HELO <domain> <CRLF>。向服務器標識用戶身份發(fā)送者能欺騙,說謊,但一般情況下服務器都能檢測到。
MAIL FROM: <reverse-path> <CRLF>。<reverse-path>為發(fā)送者地址,此命令用來初始化郵件傳輸,即用來對所有的狀態(tài)和緩沖區(qū)進行初始化。
RCPT TO:<forward-path> <CRLF>。 <forward-path>用來標志郵件接收者的地址,常用在MAIL FROM后,可以有多個RCPT TO。
DATA <CRLF>。將之后的數(shù)據(jù)作為數(shù)據(jù)發(fā)送,以<CRLF>.<CRLF>標志數(shù)據(jù)的結尾。
REST <CRLF>。重置會話,當前傳輸被取消。
NOOP <CRLF>。要求服務器返回OK應答,一般用作測試。
QUIT <CRLF>。結束會話。
VRFY <string> <CRLF>。驗證指定的郵箱是否存在,由于安全方面的原因,服務器大多禁止此命令。
EXPN <string> <CRLF>。驗證給定的郵箱列表是否存在,由于安全方面的原因,服務器大多禁止此命令。
HELP <CRLF>。查詢服務器支持什么命令。
2.2.4. 常用響應
常用的響應如下所示,數(shù)字后的說明是從英文譯過來的。更詳細的說明請參考RFC821。 501參數(shù)格式錯誤
502命令不可實現(xiàn)
503錯誤的命令序列
504命令參數(shù)不可實現(xiàn)
211系統(tǒng)狀態(tài)或系統(tǒng)幫助響應
214幫助信息
220<domain>服務就緒
221<domain>服務關閉
421<domain>服務未就緒,關閉傳輸信道
250要求的郵件操作完成
251用戶非本地,將轉發(fā)向<forward-path>
450要求的郵件操作未完成,郵箱不可用
550要求的郵件操作未完成,郵箱不可用
451放棄要求的操作;處理過程中出錯
551用戶非本地,請嘗試<forward-path>
452系統(tǒng)存儲不足,要求的操作未執(zhí)行
552過量的存儲分配,要求的操作未執(zhí)行
553郵箱名不可用,要求的操作未執(zhí)行
354開始郵件輸入,以"."結束
554操作失敗
第3章. SMTP的擴充
3.1. SMTP的缺點 從2.2.2的例子可以看出,SMTP至少還有如下缺點。 1) 命令過于簡單,沒提供認證等功能。
2) 只傳送7位的ASCII碼,不能傳送二進制文件。
針對缺點1),標準化組織制定了擴充的SMTP(即ESMTP),對應的RFC文檔為RFC1425。針對缺點2),標準化組織在兼容SMTP的前提下,提出了傳送非7位ASCII碼的方法,對應的RFC文檔有兩個:郵件首部的擴充對應于RFC1522,郵件正文的擴充對應與RFC1521(即MIME)。
3.2. ESMTP
ESMTP最顯著的地方是添加了用戶認證功能。如果用戶想使用ESMTP提供的新命令,則在初次與服務器交互時,發(fā)送的命令應該是EHLO而不是HELO。先來看一個例子。 C:telnet smtp.126.com 25 /* 以telnet方式連接126郵件服務器 */
S:220 126.com Anti-spam GT for Coremail System (126com[071018]) /* 220為響應數(shù)字,其后的為歡迎信息,會應服務器不同而不同*/
C:EHLO smtp.126.com /* 除了HELO所具有的功能外,EHLO主要用來查詢服務器支持的擴充功能 */
S:250-mail
S:250-AUTH LOGIN PLAIN
S:250-AUTH=LOGIN PLAIN
S:250 8BITMIME /* 最后一個響應數(shù)字應答碼之后跟的是一個空格,而不是'-' */
C:AUTH LOGIN /* 請求認證 */
S:334 dxNlcm5hbWU6 /* 服務器的響應——經過base64編碼了的“Username” */
C:Y29zdGFAYW1heGl0Lm5ldA== /* 發(fā)送經過BASE64編碼了的用戶名 */
S:334 UGFzc3dvcmQ6 /* 經過BASE64編碼了的"Password:" */
C:MTk4MjIxNA== /* 客戶端發(fā)送的經過BASE64編碼了的密碼 */
S:235 auth successfully /* 認證成功 */
C: MAIL FROM: bripengandre@126.com /* 發(fā)送者郵箱 */
S:250 … ./* “…”代表省略了一些可讀信息 */
C:RCPT TO: bripengandre@smail.hust.edu.cn /* 接收者郵箱 */
S:250 … ./* “…”代表省略了一些可讀信息 */
C:DATA /* 請求發(fā)送數(shù)據(jù) */
S:354 Enter mail, end with "." on a line by itself
C:Enjoy Protocol Studing
C:.
S:250 Message sent
C:QUIT /* 退出連接 */
S:221 Bye
對于這個例子有如下幾點說明。
1) 只是一個示意性的過程,再輸入用戶名、密碼時需采用base64編碼,這需要專門的計算,所以在telnet終端上模擬比較麻煩。
2) 認證過程有很多種,有基于明文的認證,也有基于MD5加密的認證,這里給出的只是一個示意性的過程。
3) EHLO對于具體服務器,響應會不同,關鍵字“8BITMIME”用來說明服務器是否支持正文中傳送8位ASCII碼,而以“X”開頭的關鍵字都是指服務器自定義的擴充(還沒納入RFC標準)
更詳細的說明,請參看RFC1425。
3.3. 郵件首部的擴充
首部通過兩種編碼方式來支持傳送非7位ASCII碼。它首先通過一個如下格式的編碼字來表明所用的編碼方式。 =?charset?encoding?encoded-text?text
charset是字符集規(guī)范。有效值是兩個字符串us-ascii和iso-8859-x,其中x 是一個單個數(shù)字,例如iso-8859-1中的數(shù)字為“ 1”。
encoding是一個單個字符用來指定編碼方法,支持兩個值。
Q代表quoted-printable(可打印)編碼。任何要發(fā)送的字符若其第8比特置1則被作為3個字符發(fā)送:第1個是字符是“=”,后面的兩個字符對應于字符的十六進制表示。例如對于二進制碼11111111,其對應的十六進制表示為“FF”,所以對應的編碼位“=FF”。為了能夠傳輸“=”,“=”的編碼方式與第8比特置1的字符相同,因為其二進制代碼為00111101,所以對應的編碼為“=3D”??梢钥闯鲞@種編碼方式的開銷達200%,所以只適合傳送只含有少量非7位ASCII碼的文本。
B代表base64編碼。它的編碼方法是先將二進制代碼劃分為一個24bit長的單元,然后將這24 bit單元劃分為4個6 bit組。每個組按圖 2所示的方法轉換成ASCII碼。
![]() 圖 2 base64映射表 可以看出這種映射方法是這樣的:0-25依次映射成A-Z,26-51依次映射成a-z,52-61依次映射成數(shù)字0-9,然后62映射成+,63映射成/。
對于二進制代碼01001001 00110001 01111001,先將其劃分成4個6 bit組,即010010 0100011 000101 111001。接著按圖 2所示的映射表,可得到base64編碼為:STF5??梢钥闯?,這種編碼方式的開銷是25%,相對quoted-printable編碼來說,它更適合用來傳送含大量非7位ASCII碼的二進制文件。
3.4. 正文的擴充
正文的擴充主要是使正文不僅可以傳輸NVT ASCII字符,而且可以傳輸任意字符,對應的文檔為RFC1511(即MIME)。 MIME全稱為“Multiple Internet Mail Extensions”, 比較確切的中文名稱為“多用途互聯(lián)網郵件擴展”。它通過新增一些郵件首部字段、郵件內容格式和傳送編碼,使得其成為一種應用很廣泛的可以傳輸多媒體的電子郵件規(guī)范。
更詳細的說明請參看另一篇文章《MIME協(xié)議分析》和RFC1511。
第4章. 常見的疑問
4.1. 為什么需要SMTP服務器 一般的PC資源不夠,處理能力不夠,不可能全天候地連接在因特網上來收發(fā)郵件。所以使用SMTP服務器,可以讓多個用戶共用服務器,有效地降低了成本。 4.2. SMTP和郵件格式的關系
如前所述,SMTP是客戶機向服務器發(fā)送郵件時所使用的協(xié)議,其核心是2.2中所述的命令和響應,至于它命令和響應中所帶的參數(shù)采用什么格式,則是依賴于其他標準的。例如DATA后所帶的參數(shù),則應遵循郵件格式標準RFC822. SMTP和郵件格式的關系可用這么一個例子來說明。甲與乙書信往來,甲通過郵局向乙發(fā)信,郵局間轉交郵件可看成使用了SMTP協(xié)議,至于書信的格式則會因為地區(qū)習慣等的不同而不同(中國人的書信格式和美國人的書信格式不同),這個書信格式則可看成是郵件格式標準。
應當認識到不能孤立地看待協(xié)議,各個協(xié)議之間往往存在著耦合關系,但為了分析方便,我們在具體敘述某個協(xié)議時,只能抓住主要矛盾——主要闡述單個協(xié)議。
4.3. 瀏覽器發(fā)送郵件用的什么協(xié)議
瀏覽器如IE、Maxthon可通過登陸用戶郵箱,來收發(fā)郵件,這是怎樣實現(xiàn)的?例如bripengandre@126.com可通過登陸www.126.com來收發(fā)郵件。 這個過程是這樣的:bripengandre@126.com在www.126.com提供的郵件頁面上填寫的相應信息(如發(fā)信人郵箱、收信人郵箱等),通過http協(xié)議被提交給126服務器;126服務器根據(jù)這些信息組裝一封符合郵件規(guī)范的郵件(就像用戶代理一樣);然后smtp.126.com通過SMTP協(xié)議將這封郵件發(fā)送到接收端郵件服務器。
可以看出,瀏覽器發(fā)送郵件只是用戶代理的功能直接放到郵件服務器上去做了,至于郵件服務器間發(fā)送郵件還是采用的SMTP協(xié)議。我們看問題,如果有必要還是要適當?shù)赝高^現(xiàn)象看本質。
4.4. 如何用實驗驗證SMTP的通信過程
1) 可以通過ethereal等協(xié)議分析軟件來抓包分析協(xié)議。 2) 可以利用socket編程實現(xiàn)SMTP的通信過程。
3) 可以利用用戶代理來查看一封郵件的原始編碼。例如在Foxmail中,可以選擇郵件列表右鍵菜單的“原始信息”進行查看。
第5章. 分析方案
表 1 協(xié)議分析要求 表 1給出了協(xié)議分析要求。容易看出,獲取各個字段是比較容易的。我們可以抓取客戶端與服務器端的交互信息,然后根據(jù)各命令字或響應字來提取出我們想要的字段。例如,要獲取user name,我們只需檢測到服務器端要求客戶端發(fā)送用戶名這個時候,然后提取這之后客戶端的發(fā)送信息即可。需要說明的是,雖然客戶端與服務端交互的信息可能經過了編碼或加密,但我們仍能夠通過解碼或解密來獲得所需要的信息。
第6章. 參考資料
[1] RFC文檔:RFC821對應SMTP協(xié)議,RFC822對應郵件標準,RFC1425對應ESMTP,RFC1522對應郵件首部的擴充,RFC1521對應郵件正文的擴充,RFC1939對應POP3協(xié)議。 [2] http://www./rfcs/,上面有全面的英文RFC文檔
[3] http://www./,上面有不少有用的協(xié)議分析文檔,也有中文RFC文檔,但質量不是特別高
[4] Stevens, W.R., TCP/IP Illustrated, Vol1. Addision-Wesley, 機械工業(yè)出版社,2002
本文來自51CTO博客,轉載請標明出處:http://blog.51CTO.net/bripengandre/archive/2008/03/17/2191048.aspx
|
|||||||||||||||||||||||||
|
|