Why使用TLS記錄協議封裝IP層VPNISABadIdea

科技小能手發表於2017-11-12
一個很自然的想法,使用TLS封裝一個IP資料包實現一個第三層的VPN。
這種想法一定是經過了深思熟慮的,但是不幸的是,這是個錯誤的想法。有一篇文章《Why TCP Over TCP Is A Bad Idea》,詳細解釋了Why。事實上重傳疊加問題是無法解決的,要知道,TCP的RTO計算是極其複雜的,影響它的因素也很多,這就是說,只要你用一個TCP封裝另一個TCP,外層TCP丟包,且RTO小於內層TCP的RTO,連線就會崩潰。而以上這個條件是很容易滿足的。
      用TLS來封裝IP資料包是對TLS的誤用!SSL/TLS的初衷是提供傳輸層之上的安全層,本身執行了可靠的TCP上,其記錄層協議封裝的是應用層資料,因此,SSL/TLS是對基於TCP應用的安全增強,並不是一個通用的傳輸協議。之所以TLS執行於TCP之上,就是這個原因,因為應用是基於TCP的。如果你想實現一個IP層的VPN,用TLS來封裝IP資料包,就相當於你將IP資料包當成了一個基於TCP的應用資料,這不正是《Why TCP Over TCP Is A Bad Idea》中描述的那種連線崩潰的場景嗎?事實是,IP資料包顯然不是基於TCP的應用資料。
      後來出現了DTLS,顯然去掉了很多約束,輕量了很多,如果非要封裝使用TLS封裝IP資料包,首先要想到的怎麼也應該是DTLS而不是TLS。DTLS衍生自TLS,並且保留了UDP無序的語義,但是它還是從TLS繼承了很多複雜的東西,本質上,DTLS也是封裝應用資料的,這些應用基於UDP。循著這個思路,如果我們可以將IP資料包看作是一個基於UDP的應用資料,那麼就可以用DTLS封裝它了,能嗎?當然能!UDP本身就是IP的第四層映象,只是多了一個多路複用機制。使用DTLS封裝IP資料包實現一個IP層VPN將會是一個不錯的選擇,但是還有更好的方法。
      OpenVPN提供了一種更好的方式,僅僅使用TLS實現控制通道,而封裝加密IP資料包的資料通道則是首選普通UDP通道。這有點IPSec的影子,不是嗎?IPSec使用獨立的IKE協商好SA,然後使用獨立的ESP/AH協議封裝加密IP資料包。其實,這才是實現IP層VPN的正確方式,本來安全引數的協商和認證/加密就是兩個獨立的過程,獨立的過程。TLS/DTLS將這些封裝進了一個會話過程中,該會話通過一個稱為SSL握手的過程建立,在握手的過程中協商安全引數,握手完畢後將使用協商好的安全引數保護後續的應用資料。這種方式的不靈活性在於你無法增加自己的協商機制,除非修改TLS協議。另外作為一個TLS Record,IP資料包被封裝在Application data中,外部能看到的只是一個TLS Record,中間系統很難對其進行識別和控制,也就是說,作為加密後的IP資料包的傳輸協議,TLS很適合,但是很難從外部去控制它,你看到的永遠是一個TLS Record頭,而看不到VPN協議的頭。
      對於IP資料包的保護,最終的思想還是IPSec的那套思想,即定義安全端點,定義安全聯盟,協商安全引數,保護IP資料包,四個過程是完全獨立的。雖然你可以將IP資料包看作是“應用資料”,但是它畢竟不是應用資料,TLS源自應用資料的安全需求,它針對單一應用,單獨的業務邏輯可以起到很好的安全加固作用,比如實現HTTPS,比如OpenVPN的控制通道,這些都是業務單一且固定的應用,但是加密IP資料包卻不適合,拋開TCP over TLS的連線崩潰問題不談而引入DTLS,控制和傳輸疊加在一個會話中將會使擴充套件很難,比如防火牆無法區分VPN資料和其它TLS應用資料,比如無法實現組播加密,比如無法重協商單獨的安全引數,同一個SSL會話無法被不同的安全端點共享…

      因此, 使用TLS記錄協議封裝IP層VPN IS A Bad Idea,DTLS好一點,但也不絕對。真正的好的方案是,最大限度使用TLS來做控制通道協商交換安全引數,然後定義獨立的封裝協議來封裝安全引數保護的IP資料包。例子太多了,IPSec,OpenVPN,不過OpenVPN的程式碼太噁心了,理解它的思想後自己寫一個吧,或許會更好些。


 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1403645



相關文章