一、DTLS
DTLS 是指 Datagram Transport Level Security,即數據報安全傳輸協議;
其提供了UDP 傳輸場景下的安全解決方案,能防止消息被竊聽、篡改、身份冒充等問題。
DTLS作為UDP版本的TLS,具備了同樣的安全機制和防護等級,在版本上存在對應關系,如DTLS 1.2版本對應於 TLS1.2。
二、握手流程
前面的文章介紹過TLS的相關算法流程,對於傳輸層安全來說,密鑰交換機制和數據加密及簽名算法決定了整個方案的安全等級。
而密鑰協商都必須通過握手流程完成,因而這是理解DTLS的關鍵要點。
根據RFC6347定義,一個DTLS握手流程如下所示:
------ ------ ClientHello --------> Flight 1 <------- HelloVerifyRequest Flight 2 ClientHello --------> Flight 3 ServerHello \ Certificate* \ ServerKeyExchange* Flight 4 CertificateRequest* / <-------- ServerHelloDone / Certificate* \ ClientKeyExchange \ CertificateVerify* Flight 5 [ChangeCipherSpec] / Finished --------> / [ChangeCipherSpec] \ Flight 6 <-------- Finished /
三、關鍵算法
DTLS 由於網絡IO機制的限制,其支持的算法為TLS的子集。
這里將DTLS算法描述為一種算法可能並不恰當,因為一個完整的DTLS過程中,所涉及的算法是很多的,比如
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,這其中涉及的算法包括:
1 密鑰交換算法 ECDHE_RSA,這是由ECC和DH密鑰交換算法衍生出來的算法;
2 動態密鑰算法 AES_128_GCM,用於實現數據包的加解密;
3 MAC算法 HMAC_SHA256,用於創建加密數據塊的摘要;
4 偽隨機函數 PRF,TLS1.2 定義其與MAC算法一致。
因此將一個DTLS過程中協商使用的算法列表稱謂算法套件,即CipherSuite,個人認為這個定義還是比較好理解的。
以下是幾個常用的 CipherSuite
TLS_PSK_WITH_AES_128_CBC_SHA256
TLS_PSK_WITH_AES_128_CCM_8
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
算法的選擇
不同算法帶來的數據傳輸及計算性能開銷是不同的,尤其在UDP場景下,我們可能更關注的是網絡IO的不穩定性,MTU過載導致丟包等等問題。
非對稱密鑰加解密的性能是低下的,尤其在微型設備上,其計算資源十分有限,因此采用輕量級的密鑰交換算法可能是最佳方案。
PSK(Pre shared key) 算法中,服務端為終端預置了密鑰,在交換過程中憑一個identity信息可快速完成信息交換,這個極大簡化了密鑰交換的工作。
一個典型的PSK握手流程如下所示:
Client Server ------ ------ ClientHello --------> <-------- HelloVerifyRequest (contains cookie) ClientHello --------> (with cookie) ServerHello *ServerKeyExchange <-------- ServerHelloDone ClientKeyExchange ChangeCipherSpec Finished --------> ChangeCipherSpec <-------- Finished Application Data <-------> Application Data
PSK方案的缺陷在於其無法較好的防止PSF(Perfect Forward Secrecy)攻擊問題,一旦PSK泄露,將丟失安全性。
然而方案的選擇並非力求完美,我們往往要找的是最適合需求的方案。PSK方案輕量級,節省開銷,且具備一定的通用性;
而對於安全級別特別高的場景,你或許可以選擇ECDHE交換算法,而為了節省證書傳輸的開銷,你可以采取一些擴展機制,如Raw Public Key。
這是一種允許直接將公鑰數據替代證書的方案,可一定程度節省CA證書傳輸及信任鏈校驗的開銷。
RFC7925 對物聯網場景下的DTLS提供了一些擴展定義,可供參考。
四、防護機制
A. 握手流程
握手流程必須嚴格按順序執行,因此有必要保證消息可靠到達,按序接收。
重傳
DTLS 采用了簡單的重傳機制來確保握手消息到達,流程如下:
Client Server ------ ------ ClientHello ------> X<-- HelloVerifyRequest (lost) [Timer Expires] ClientHello ------> (retransmit)
順序
為保證握手消息按序傳輸,每個handshake消息包含了一個序列號;
接收方直接處理屬於當前步驟的消息,對於提前到達的消息則提供一個隊列進行緩存;
分段
理論上一個握手消息可能接近2^24-1字節, 而UDP 傳輸中往往限制於MTU 大小,一般為1500字節;
因此 DTLS 要求針對握手消息實現分段,每一個握手消息都可能包含了fragment的offset 和長度,由接收端重新組裝;
重復
DTLS 定義了消息重放檢測機制,由接收方維護一個bitmap用於記錄一接收的數據包,用於檢測重復數據包;建議解決方案實現對bitmap的自動老化。
該做法借鑒了IPsec AH/ESP機制。
B. 數據包傳輸
加解密算法很可能依賴於上下文,如CBC組合算法中,當前數據包的解密依賴於上一個數據包,因此有必要保證數據包傳輸的可靠和有序;
DTLS為每個加密數據包增加了MAC鑒權摘要,用於保證數據包的完整性;此外顯式附帶了一個SN號用於排序。
C. Dos攻擊
攻擊者很可能會利用一些已入侵的主機對服務器展開攻擊(數據包轉發),通過瞬時對DTLS服務器發送大量的握手消息導致服務器資源耗盡;
DTLS定義了基於cookie驗證的機制來預防攻擊,如前面流程中涉及的HelloVerifyRequest便是用於進行cookie驗證
Client Server ------ ------ ClientHello ------> <----- HelloVerifyRequest (contains cookie) ClientHello ------> (with cookie) [Rest of handshake]
Cookie的算法:HMAC(Secret, Client-IP, Client-Parameters)
其中Secret由server端內置,用於計算cookie值,client端需要在接收到VerifyRequest后提供同樣的cookie值;
server端根據發送方IP計算cookie值,一旦返現不一致則判定為非法數據。
D. 會話恢復
握手流程所占的開銷是較大的,與TLS類似,DTLS也定義了會話恢復機制。
Client Server ------ ------ ClientHello --------> Flight 1 ServerHello \ [ChangeCipherSpec] Flight 2 <-------- Finished / [ChangeCipherSpec] \Flight 3 Finished -------->
簡單原理
握手成功之后,Server端將生成SessionID 返回,客戶端在下次連接時附帶SessionID;
若驗證通過,可直接沿用原有的會話數據,包括協商算法和密鑰。
五、與TLS的不同
最后,總結下與TLS的差異吧
-
TLS 建立於TCP可靠的傳輸機制之上,而DTLS基於UDP,必須自建保障機制:
DTLS 必須檢測MTU大小,當應用層數據包超過時報錯;
為防止握手的IP數據包超載導致丟失,DTLS 針對握手消息實現fragment處理。 -
TLS 在傳輸出錯時會中斷連接,而DTLS需兼容多種出錯場景,出錯時往往直接丟棄處理;
- DTLS不支持RC4流加密算法。
六、參考文檔
DTLS1.2 定義
https://tools.ietf.org/html/rfc6347
DTLS -IOT extension
https://tools.ietf.org/html/rfc7925#section-4.1
TLS /SSL 原理解析
http://seanlook.com/2015/01/07/tls-ssl/
關於TLS的隱式向量
https://en.wikipedia.org/wiki/Initialization_vector
老外寫的關於PSF的文章
https://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html