TLS 1.3 當前(2018.10)支援與部署之現狀
今年8月10日,歷經三年有餘,TLS 1.3 最終版本終於得以釋出—— ofollow,noindex" target="_blank">RFC 8446 . 關於 RFC 的詳細介紹可以進一步閱讀 A Detailed Look at RFC 8446 (a.k.a. TLS 1.3) . TLS 1.3 因為其在握手延遲以及安全性上的改進 (可以參考拙文 《TLS1.3/QUIC 是怎樣做到 0-RTT 的》 ),毫不誇張的說,這是一件將深刻而長遠影響網際網路發展的技術里程碑。那麼將 TLS 1.3 儘快平滑應用到線上環境無疑是一件勢在必行的事情了。
在我日常的工作中,對於 TLS 1.3 的支援和部署主要關注兩個層面: 程式語言(Go, Java)、 API gateway (Nginx) 和瀏覽器. 下面分別介紹一下這三個層面 TLS 1.3 的支援部署現狀。(因為 RFC 8446 已經發布,因此本文中說的 支援
如無特殊說明,都是指對最終版本 RFC 8446 的支援。)
程式語言對 TLS 1.3 的支援
Go 方面,官方在 TLS 1.3 draft 階段一直沒有跟進。因此,有一個關於對 TLS 1.3 支援的 issue 從 2015 年 open 至今都沒有關閉: crypto/tls: add support for TLS 1.3 . 其實 Go 釋出版本和改進標準庫的效率還是挺高的,對於 TLS 1.3 上的“不作為”更多是因為 Go 在相容性上的承諾導致其並適合在最終版釋出前實現互不相容的 draft 方案。
而 Go 1.11 的釋出時間(2018.08.24)與 RFC 8446 的釋出時間比較接近,沒有足夠時間實現併發布該特性。從 golang-dev 小組討論 Re: crypto/tls and TLS 1.3 看,由於 1.11 沒有實現 TLS 1.3 ,那麼 1.12 實現 TLS 1.3 基本是板上釘釘的事了:
The key scheduling fact is that the Go 1.11 feature freeze is just a week away, so we decided that it would be too rushed to merge the 1.3 patches for it. I definitely aim to have TLS 1.3 in Go 1.12.
根據慣例, Go 1.12 的釋出時間將會是 2019.02~03. 如果期間你實在想用 Go 程式設計測試 TLS 1.3, 可以嘗試使用 Flare/">CloudFlare 的 tls-tris 庫。根據 Go net/http 標準庫維護者 Brad Fitzpatrick 的訊息,這個庫將會被合併到標準庫作為 Go 官方 TLS 1.3 的實現。因此,如果你不得不用這個庫幹一些生成環境的活也大可放心,即使日後升級 Go 1.12, 介面相容性還是有保證的。
Java 方面,由於 Java 11 出生時間好(2018.09.25), 因此是出生就支援 TLS 1.3 RFC 8446, 具體可以參見 JEP 332: Transport Layer Security (TLS) 1.3 . Java 11 是 LTS 版本,因此,如果有條件升級到 11, 推薦使用 Java 11 實現的 TLS 1.3 以及配套的 HttpClient;如果生產環境暫無法升級 Java 版本,推薦使用 OkHttp. 關於 Java Http Client 選型可以參見 Java HTTP 元件庫選型看這篇就夠了 。
Nginx 對 TLS 1.3 的支援
準確講應該是 Nginx 所使用 SSL lib 對 TLS 1.3 的支援。在這方面,Boring SSL 跟進速度飛快,在 RFC 釋出後第4天實現了對 最終版本的支援 。OpenSSL 雖然很早就跟進了 draft 的實現,但是 對最終版本的支援 需要 1.1.1-pre9 及以後的版本:
The OpenSSL git master branch (and the 1.1.1-pre9 beta version) contain our development TLSv1.3 code which is based on the final version of RFC8446 and can be used for testing purposes (i.e. it is not for production use). Earlier beta versions of OpenSSL 1.1.1 implemented draft versions of the standard. Those versions contained the macro TLS1_3_VERSION_DRAFT_TXT in the tls1.h header file which identified the specific draft version that was implemented. This macro has been removed from 1.1.1-pre9 and the current master branch. TLSv1.3 is enabled by default in the latest development versions (there is no need to explicitly enable it). To disable it at compile time you must use the “no-tls1_3” option to “config” or “Configure”. Although the latest 1.1.1 versions support the final standard version, other applications that support TLSv1.3 may still be using older draft versions. This is a common source of interoperability problems. If two peers supporting different TLSv1.3 draft versions attempt to communicate then they will fall back to TLSv1.2.
而第一個 OpenSSL 1.1.1 release 是在 2018.09.11, 因此如果你跟我一樣是 OpenSSL 的死忠粉,當前階段 Nginx 支援 TSL 1.3 的最佳方式是 Nginx 1.15.5 + OpenSSL 1.1.1
. 而這種髒活、苦活、累活當然是交給 Docker 解決了: 從原始碼編譯 nginx docker 映象開啟 TLS 1.3 ,專案地址可以參見 docker-nginx .
配置 Nginx 支援 TLS 1.3 需要注意一點:預設情況下 Nginx 因為安全原因,沒有開啟 TLS 1.3 0-RTT,可以通過新增 ssl_early_data on;
指令開啟 0-RTT. 完整配置可以參考 nginx.conf .
瀏覽器對 TLS 1.3 的支援
當前階段,Chrome 69 和 Firefox 62 都只支援到 draft 28, 而 draft 28 與最終版本是不相容的。因此,要測試體驗 TLS 1.3 final 需要使用 Chrome Beta 測試版 。然後在 chrome://flags/#tls13-variant 開啟 TLS 1.3 final:
擴充套件閱讀
- CloudFlare TLS 1.3 Blogs
- How To Enable TLS 1.3 in Nginx on Ubuntu 18.04 and 16.04
–EOF–