1.介紹
HTTP[RFC2616]最初是在INTERNET上不用密碼的應用。但隨着HTTP的敏感性應用日益增加,對安全性的要求也隨之增加。SSL及其後繼TLS[RFC2246]提供了面向通道的安全性。本文介紹怎樣在TLS之上應用HTTP。
相關術語
在本文中的關鍵字“必須”,“必須不”,“要求”,“應該”,“不應該”和“可能”的解釋見[RFC2119]。
2. TLS之上的HTTP
從概念上講,HTTP/TLS非常簡單。簡單地在TLS上應用HTTP,如同在TCP上應用HTTP一樣。
2.1 初始化連接
作爲HTTP客戶的代理同時也應作爲TLS的客戶。它應該向服務器的適當端口發起一個連接,然後發送TLS ClientHello來開始TLS握手。當TLS握手完成,客戶可以初始化第一個HTTP請求。所有的HTTP數據必須作爲TLS的“應用數據”發送。正常的HTTP行爲,包括保持連接,應當被遵守。
2.2 關閉連接
TLS提供了安全關閉連接的機制。當收到一個有效的關閉警告時,實現上必須保證在這個連接上不再接收任何數據。TLS的實現在關閉連接之前必須發起交換關閉請求。TLS實現可能在發送關閉請求後,不等待對方發送關閉請求即關閉該連接,產生一個“不完全的關閉”。注意:這樣的實現可能選擇重用該對話。這隻應在應用瞭解(典型的是通過檢測HTTP的消息邊界)它已收到所有它關心的數據的情況下進行。
如[RFC2246]中所定義的,任何未接收一個有效的關閉警告(一個“未成熟關閉”)即接到一個連接關閉必須不重用該對話。注意:一個未成熟請求並不質疑數據已被安全地接收,而僅意味着接下來數據可能被截掉。由於TLS並不知道HTTP的請求/響應邊界,爲了解數據截斷是發生在消息內還是在消息之間,有必要檢查HTTP數據本身(即Content-Length頭)。
2.2.1 客戶行爲
由於HTTP使用連接關閉表示服務器數據的終止,客戶端實現上對任何未成熟的關閉要作爲錯誤對待,對收到的數據認爲有可能被截斷。在某些情況下HTTP協議允許客戶知道截斷是否發生,這樣如果客戶收到了完整的應答,則在遵循“嚴出鬆入[RFC1958]”的原則下可容忍這類錯誤,經常數據截斷不體現在HTTP協議數據中;有兩種情況特別值得注意:
一個無Content-Length頭的HTTP響應。在這種情況下數據長度由連接關閉請求通知,我們無法區分由服務器產生的未成熟關閉請求及由網絡***者僞造的關閉請求。
一個帶有有效Content-Length頭的HTTP響應在所有數據被讀取完之前關閉。由於TLS並不提供面向文檔的保護,所以無法知道是服務器對Content-Length計算錯誤還是***者已截斷連接。
以上規則有一個例外。當客戶遇到一個未成熟關閉時,客戶把所有已接收到的數據同Content-Length頭指定的一樣多的請求視爲已完成。
客戶檢測到一個未完成關閉時應予以有序恢復,它可能恢復一個以這種方式關閉的TLS對話。
客戶在關閉連接前必須發送關閉警告。未準備接收任何數據的客戶可能選擇不等待服務器的關閉警告而直接關閉連接,這樣在服務器端產生一個不完全的關閉。
2.2.2 服務器行爲
RFC2616允許HTTP客戶在任何時候關閉連接,並要求服務器有序地恢復它。特別是,服務器應準備接收來自客戶的不完全關閉,因爲客戶往往能夠判斷服務器數據的結束。服務器應樂於恢復以這種方式關閉的TLS對話。
實現上注意:在不使用永久連接的HTTP實現中,服務器一般期望能通過關閉連接通知數據的結束。但是,當Content-Length被使用時,客戶可能早已發送了關閉警告並斷開了連接。
服務器必須在關閉連接前試圖發起同客戶交換關閉警告。服務器可能在發送關閉警告後關閉連接,從而形成了客戶端的不完全關閉。
2.3端口號
HTTP服務器期望最先從客戶收到的數據是Request-Line production。TLS服務器期望最先收到的數據是ClientHello。因此,一般做法是在一個單獨的端口上運行HTTP/TLS,以區分是在使用哪種協議。當在TCP/IP連接上運行HTTP/TLS時,缺省端口是443。這並不排除HTTP/TLS運行在其它傳輸上。TLS只假設有可靠的、面向連接的數據流。
2.4 URI格式
HTTP/TLS和HTTP的URI不同,使用協議描述符https而不是http。使用HTTP/TLS的一個URI例子是:
https://www.example.com/~smith/home.html
3 端標識
3.1 服務器身份
通常,解析一個URI產生HTTP/TLS請求。結果客戶得到服務器的主機名。若主機名可用,爲防止有人在中間***,客戶必須把它同服務器證書信息中的服務器的身份號比較檢查。
若客戶有相關服務器標誌的外部信息,主機名檢查可以忽略。(例如:客戶可能連接到一個主機名和IP地址都是動態的服務器上,但客戶瞭解服務器的證書信息。)在這種情況下,爲防止有人***,儘可能縮小可接受證書的範圍就很重要。在特殊情況下,客戶簡單地忽略服務器的身份是可以的,但必須意識到連接對***是完全敞開的。
若dNSName類型的subjectAltName擴展存在,則必須被用作身份標識。否則,在證書的Subject字段中必須使用Common Name字段。雖然使用Common Name是通常的做法,但不受贊成,而Certification Authorities被鼓勵使用dNSName。
使用[RFC2459]中的匹配規則進行匹配。若在證書中給定類型的身份標識超過一個(也就是,超過一個dNSName和集合中的相匹配),名字可以包括通配符*表示和單個域名或其中的一段相匹配。例如:*.a.com和foo.a.com匹配但和bar.foo.a.com不匹配。f*.com和foo.com匹配但和bar.com不匹配。
在某些情況下,URI定義的不是主機名而是IP地址。在這種情況下,證書中必須有iPAddress subjectAltName字段且必須精確匹配在URI中的IP地址。
若主機名和證書中的標識不相符,面向用戶的客戶端必須或者通知用戶(客戶端可以給用戶機會來繼續連接)或終止連接並報證書錯。自動客戶端必須將錯誤記錄在適當的審計日誌中(若有的話)並應該終止連接(帶一證書錯)。自動客戶端可以提供選項禁止這種檢查,但必須提供選項使能它。
注意,在很多情況下URI本身是從不可信任的源得到的。以上描述的檢查並未提供對危害源的***的保護。例如,若URI是從一個未採用HTTP/TLS的HTML頁面得到的,某個人可能已在中間已替換了URI。爲防止這種***,用戶應仔細檢查服務器提供的證書是否是期望的。
3.2 客戶標識
典型情況下,服務器並不知道客戶的標識是什麼也就無法檢查(除非有合適的CA證書)。若服務器知道的話(通常是在HTTP和TLS之外的源得到的),它應該象上面描述的那樣檢查。
《RFC2818-TLS之上的HTTP.doc》