230-TLS是什么
1.http不安全
由于 HTTP 天生“明文”的特點,整個傳輸過程完全透明,任何人都能夠在鏈路中截獲、修改或者偽造請求 / 響應報文,數據不具有可信性 ;
“代理服務”。它作為 HTTP 通信的中間人,在數據上下行的時候可以添加或刪除部分頭字段,也可以使用黑白名單過濾 body 里的關鍵字,甚至直接發(fā)送虛假的請求、響應,而瀏覽器和源服務器都沒有辦法判斷報文的真?zhèn)?。
這對于網絡購物、網上銀行、證券交易等需要高度信任的應用場景來說是非常致命的。如果沒有基本的安全保護,使用互聯網進行各種電子商務、電子政務就根本無從談起
對于安全性要求不那么高的新聞、視頻、搜索等網站來說,由于互聯網上的惡意用戶、惡意代理越來越多,也很容易遭到“流量劫持”的攻擊,在頁面里強行嵌入廣告,或者分流用戶,導致各種利益損失
對于你我這樣的普通網民來說,HTTP 不安全的隱患就更大了,上網的記錄會被輕易截獲,網站是否真實也無法驗證,黑客可以偽裝成銀行網站,盜取真實姓名、密碼、銀行卡等敏感信息,威脅人身安全和財產安全
2、安全的實現
通常認為,如果通信過程具備了四個特性,就可以認為是“安全”的,這四個特性是:機密性、完整性,身份認證和不可否認
機密性(Secrecy/Confidentiality)是指對數據的“保密”,只能由可信的人訪問,對其他人是不可見的“秘密”,簡單來說就是不能讓不相關的人看到不該看的東西。
完整性(Integrity,也叫一致性)是指數據在傳輸過程中沒有被竄改,不多也不少,“完完整整”地保持著原狀 。
機密性雖然可以讓數據成為“秘密”,但不能防止黑客對數據的修改,黑客可以替換數據,調整數據的順序,或者增加、刪除部分數據,破壞通信過程 。
身份認證(Authentication)是指確認對方的真實身份,也就是“證明你真的是你”,保證消息只能發(fā)送給可信的人。
如果通信時另一方是假冒的網站,那么數據再保密也沒有用,黑客完全可以使用冒充的身份“套”出各種信息,加密和沒加密一樣
不可否認(Non-repudiation/Undeniable),也叫不可抵賴,意思是不能否認已經發(fā)生過的行為,不能“說話不算數”“耍賴皮”。
3、HTTPS的介紹
新的協議名“https”,默認端口號 443
至于其他的什么請求 - 應答模式、報文結構、請求方法、URI、頭字段、連接管理等等都完全沿用 HTTP
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9MoeGXqi-1618498415299)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1617727930979.png)]
,HTTPS 憑什么就能做到機密性、完整性這些安全特性呢?
秘密就在于 HTTPS 名字里的“S”,它把 HTTP 下層的傳輸協議由 TCP/IP 換成了 SSL/TLS,由“HTTP over TCP/IP”變成了“HTTP over SSL/TLS”,讓 HTTP 運行在了安全的 SSL/TLS 協議上(可參考第 4 講和第 5 講),收發(fā)報文不再使用 Socket API,而是調用專門的安全接口。
4、ssl/tls
①SSL/TLS的來歷
SSL 即安全套接層(Secure Sockets Layer),在 OSI 模型中處于第 5 層(會話層),由網景公司于 1994 年發(fā)明,有 v2 和 v3 兩個版本,而 v1 因為有嚴重的缺陷從未公開過。
SSL 發(fā)展到 v3 時已經證明了它自身是一個非常好的安全通信協議,于是互聯網工程組 IETF 在 1999 年把它改名為 TLS(傳輸層安全,Transport Layer Security),正式標準化,版本號從 1.0 重新算起,所以 TLS1.0 實際上就是 SSLv3.1。
到今天 TLS 已經發(fā)展出了三個版本,分別是 2006 年的 1.1、2008 年的 1.2 和去年(2018)的 1.3,每個新版本都緊跟密碼學的發(fā)展和互聯網的現狀,持續(xù)強化安全和性能,已經成為了信息安全領域中的權威標準。
目前應用的最廣泛的 TLS 是 1.2,而之前的協議(TLS1.1/1.0、SSLv3/v2)都已經被認為是不安全的,各大瀏覽器即將在 2020 年左右停止支持,所以接下來的講解都針對的是 TLS1.2。
②TLS的組成
TLS 由記錄協議、握手協議、警告協議、變更密碼規(guī)范協議、擴展協議等幾個子協議組成,綜合使用了對稱加密、非對稱加密、身份認證等許多密碼學前沿技術。
瀏覽器和服務器在使用 TLS 建立連接時需要選擇一組恰當的加密算法來實現安全通信,這些算法的組合被稱為“密碼套件”(cipher suite,也叫加密套件)。
TLS 的密碼套件命名非常規(guī)范,格式很固定?;镜男问绞恰懊荑€交換算法 + 簽名算法 + 對稱加密算法 + 摘要算法”,比如剛才的密碼套件的意思就是:
“握手時使用 ECDHE 算法進行密鑰交換,用 RSA 簽名和身份認證,握手后的通信使用 AES 對稱算法,密鑰長度 256 位,分組模式是 GCM,摘要算法 SHA384 用于消息認證和產生隨機數。”
5、OpenSSL
①OpenSSL的發(fā)展
說到 TLS,就不能不談到 OpenSSL,它是一個著名的開源密碼學程序庫和工具包,幾乎支持所有公開的加密算法和協議,已經成為了事實上的標準,許多應用軟件都會使用它作為底層庫來實現 TLS 功能,包括常用的 Web 服務器 Apache、Nginx 等。
OpenSSL 是從另一個開源庫 SSLeay 發(fā)展出來的,曾經考慮命名為“OpenTLS”,但當時(1998 年)TLS 還未正式確立,而 SSL 早已廣為人知,所以最終使用了“OpenSSL”的名字。
OpenSSL 目前有三個主要的分支,1.0.2 和 1.1.0 都將在2019年年底不再維護,最新的長期支持版本是 1.1.1
由于 OpenSSL 是開源的,所以它還有一些代碼分支,比如 Google 的 BoringSSL、OpenBSD 的 LibreSSL,這些分支在 OpenSSL 的基礎上刪除了一些老舊代碼,也增加了一些新特性,雖然背后有“大金主”,但離取代 OpenSSL 還差得很遠。
小結
- 因為 HTTP 是明文傳輸,所以不安全,容易被黑客竊聽或竄改;
- 通信安全必須同時具備機密性、完整性,身份認證和不可否認這四個特性;
- HTTPS 的語法、語義仍然是 HTTP,但把下層的協議由 TCP/IP 換成了 SSL/TLS;
- SSL/TLS 是信息安全領域中的權威標準,采用多種先進的加密技術保證通信安全;
- OpenSSL 是著名的開源密碼學工具包,是 SSL/TLS 的具體實現。
課下作業(yè)
- 你能說出 HTTPS 與 HTTP 有哪些區(qū)別嗎?
- 你知道有哪些方法能夠實現機密性、完整性等安全特性呢?
課外延伸
==============
240-對稱加密與非對稱加密
①引入
實現機密性最常用的手段是“加密”(encrypt),就是把消息用某種方式轉換成誰也看不懂的亂碼,只有掌握特殊“鑰匙”的人才能再轉換出原始文本。
這里的“鑰匙”就叫做“密鑰”(key),加密前的消息叫“明文”(plain text/clear text),加密后的亂碼叫“密文”(cipher text),使用密鑰還原明文的過程叫“解密”(decrypt),是加密的反操作,加密解密的操作過程就是“加密算法”。
由于 HTTPS、TLS 都運行在計算機上,所以“密鑰”就是一長串的數字,但約定俗成的度量單位是“位”(bit),而不是“字節(jié)”(byte)。比如,說密鑰長度是 128,就是 16 字節(jié)的二進制串,密鑰長度 1024,就是 128 字節(jié)的二進制串。
按照密鑰的使用方式,對稱加密和非對稱加密
1、對稱加密
“對稱加密”很好理解,就是指加密和解密時使用的密鑰都是同一個,是“對稱”的。只要保證了密鑰的安全,那整個通信過程就可以說具有了機密性。
TLS 里有非常多的對稱加密算法可供選擇,比如 RC4、DES、3DES、AES、ChaCha20 等,但前三種算法都被認為是不安全的,通常都禁止使用,目前常用的只有 AES 和 ChaCha20。
AES 的意思是“高級加密標準”(Advanced Encryption Standard),密鑰長度可以是 128、192 或 256。它是 DES 算法的替代者,安全強度很高,性能也很好,而且有的硬件還會做特殊優(yōu)化,所以非常流行,是應用最廣泛的對稱加密算法。
ChaCha20 是 Google 設計的另一種加密算法,密鑰長度固定為 256 位,純軟件運行性能要超過 AES,曾經在移動客戶端上比較流行,但 ARMv8 之后也加入了 AES 硬件優(yōu)化,所以現在不再具有明顯的優(yōu)勢,但仍然算得上是一個不錯算法。
1.1、加密分組模式
對稱算法還有一個“分組模式”的概念,它可以讓算法用固定長度的密鑰加密任意長度的明文,把小秘密(即密鑰)轉化為大秘密(即密文)。
最早有 ECB、CBC、CFB、OFB 等幾種分組模式,但都陸續(xù)被發(fā)現有安全漏洞,所以現在基本都不怎么用了。最新的分組模式被稱為 AEAD(Authenticated Encryption with Associated Data),在加密的同時增加了認證的功能,常用的是 GCM、CCM 和 Poly1305。
把上面這些組合起來,就可以得到 TLS 密碼套件中定義的對稱加密算法。
把上面這些組合起來,就可以得到 TLS 密碼套件中定義的對稱加密算法。
比如,AES128-GCM,意思是密鑰長度為 128 位的 AES 算法,使用的分組模式是 GCM;ChaCha20-Poly1305 的意思是 ChaCha20 算法,使用的分組模式是 Poly1305。
2、非對稱加密
對稱加密看上去好像完美地實現了機密性,但其中有一個很大的問題:如何把密鑰安全地傳遞給對方,術語叫“密鑰交換”。
它有兩個密鑰,一個叫**“公鑰”(public key),一個叫“私鑰”(private key)。兩個
密鑰是不同的,“不對稱”,公鑰可以公開給任何人使用,而私鑰必須嚴格保密。
公鑰和私鑰有個特別的“單向”**性,雖然都可以用來加密解密,但公鑰加密后只能用私鑰解密,反過來,私鑰加密后也只能用公鑰解密。
非對稱加密可以解決“密鑰交換”的問題。網站秘密保管私鑰,在網上任意分發(fā)公鑰,你想
要登錄網站只要用公鑰加密就行了,密文只能由私鑰持有者才能解密。而黑客因為沒有私
鑰,所以就無法破解密文。
非對稱加密算法的設計要比對稱算法難得多,在 TLS 里只有很少的幾種,比如 DH、
DSA、RSA、ECC 等。
RSA 可能是其中最著名的一個,幾乎可以說是非對稱加密的代名詞,它的安全性基于“整
數分解”的數學難題,使用兩個超大素數的乘積作為生成密鑰的材料,想要從公鑰推算出私
鑰是非常困難的。
10 年前 RSA 密鑰的推薦長度是 1024,但隨著計算機運算能力的提高,現在 1024 已經不
安全,普遍認為至少要 2048 位。
ECC(Elliptic Curve Cryptography)是非對稱加密里的“后起之秀”,它基于“橢圓曲線
離散對數”的數學難題,使用特定的曲線方程和基點生成公鑰和私鑰,子算法 ECDHE 用于
密鑰交換,ECDSA 用于數字簽名。
目前比較常用的兩個曲線是 P-256(secp256r1,在 OpenSSL 稱為 prime256v1)和
x25519。P-256 是 NIST(美國國家標準技術研究所)和 NSA(美國國家安全局)推薦使
用的曲線,而 x25519 被認為是最安全、最快速的曲線。
RSA 的運算速度是非常慢的,2048 位的加解密大約是 15KB/S(微秒或毫秒級),而 AES128 則是 13MB/S(納秒級),差了幾百倍。
TLS 里使用的混合加密方式,其實說穿了也很簡單:
在通信剛開始的時候使用非對稱算法,比如 RSA、ECDHE,首先解決密鑰交換的問題。
然后用隨機數產生對稱算法使用的**“會話密鑰”(session key)**,再用公鑰加密。因為會
話密鑰很短,通常只有 16 字節(jié)或 32 字節(jié),所以慢一點也無所謂。
對方拿到密文后用私鑰解密,取出會話密鑰。這樣,雙方就實現了對稱密鑰的安全交換,后續(xù)就不再使用非對稱加密,全都使用對稱加密。
小結
-
加密算法的核心思想是“把一個小秘密(密鑰)轉化為一個大秘密(密文消息)”,守
住了小秘密,也就守住了大秘密; -
對稱加密只使用一個密鑰,運算速度快,密鑰必須保密,無法做到安全的密鑰交換,常
用的有 AES 和 ChaCha20; -
非對稱加密使用兩個密鑰:公鑰和私鑰,公鑰可以任意分發(fā)而私鑰保密,解決了密鑰交
換問題但速度慢,常用的有 RSA 和 ECC; -
把對稱加密和非對稱加密結合起來就得到了“又好又快”的混合加密,也就是 TLS 里使
用的加密方式。
課下作業(yè)
- 加密算法中“密鑰”的名字很形象,你能試著用現實中的鎖和鑰匙來比喻一下嗎?
- 在混合加密中用到了公鑰加密,因為只能由私鑰解密。那么反過來,私鑰加密后任何人
都可以用公鑰解密,這有什么用呢? - [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-imKXuxyq-1618498415306)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618418756034.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MD9vWDiS-1618498415308)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618418766692.png)]
============
250-數字簽名與證書
1.1、摘要算法
實現完整性的手段主要是摘要算法(Digest Algorithm),也就是常說的散列函數、哈希
函數(Hash Function)。
你可以把摘要算法近似地理解成一種特殊的壓縮算法,它能夠把任意長度的數據“壓縮”成
固定長度、而且獨一無二的“摘要”字符串,就好像是給這段數據生成了一個數字“指紋”。
換一個角度,也可以把摘要算法理解成特殊的“單向”加密算法,它只有算法,沒有密鑰,
加密后的數據無法解密,不能從摘要逆推出原文。
摘要算法實際上是把數據從一個“大空間”映射到了“小空間”,所以就存在“沖
突”(collision,也叫碰撞)的可能性,就如同現實中的指紋一樣,可能會有兩份不同的原
文對應相同的摘要。好的摘要算法必須能夠“抵抗沖突”,讓這種可能性盡量地小。
因為摘要算法對輸入具有“單向性”和“雪崩效應”,輸入的微小不同會導致輸出的劇烈變
化,所以也被 TLS 用來生成偽隨機數(PRF,pseudo random function)。
你一定在日常工作中聽過、或者用過 MD5(Message-Digest 5)、SHA-1(Secure
Hash Algorithm 1),它們就是最常用的兩個摘要算法,能夠生成 16 字節(jié)和 20 字節(jié)長度
的數字摘要。但這兩個算法的安全強度比較低,不夠安全,在 TLS 里已經被禁止使用了
目前 TLS 推薦使用的是 SHA-1 的后繼者:SHA-2。
SHA-2 實際上是一系列摘要算法的統(tǒng)稱,總共有 6 種,常用的有 SHA224、SHA256、SHA384,分別能夠生成 28 字節(jié)、32 字節(jié)、48 字節(jié)的摘要。
1.2、完整性
摘要算法保證了“數字摘要”和原文是完全等價的。所以,我們只要在原文后附上它的摘要,就能夠保證數據的完整性。
不過摘要算法不具有機密性,如果明文傳輸,那么黑客可以修改消息后把摘要也一起改了,網站還是鑒別不出完整性。
所以,真正的完整性必須要建立在機密性之上,在混合加密系統(tǒng)里用會話密鑰加密消息和摘要,這樣黑客無法得知明文,也就沒有辦法動手腳了。這有個術語,叫哈希消息認證碼(HMAC)。
1.3、數字簽名
加密算法結合摘要算法,我們的通信過程可以說是比較安全了。但這里還有漏洞,就是通信的兩個端點(endpoint)。
就像一開始所說的,黑客可以偽裝成網站來竊取信息。而反過來,他也可以偽裝成你,向網站發(fā)送支付、轉賬等消息,網站沒有辦法確認你的身份,錢可能就這么被偷走了。
現實生活中,解決身份認證的手段是簽名和印章,只要在紙上寫下簽名或者蓋個章,就能夠證明這份文件確實是由本人而不是其他人發(fā)出的。
這個東西就是非對稱加密里的“私鑰”,使用私鑰再加上摘要算法,就能夠實現“數字簽名”,同時實現“身份認證”和“不可否認”。
數字簽名的原理其實很簡單,就是把公鑰私鑰的用法反過來,之前是公鑰加密、私鑰解密,現在是私鑰加密、公鑰解密。
但又因為非對稱加密效率太低,所以私鑰只加密原文的摘要,這樣運算量就小的多,而且得到的數字簽名也很小,方便保管和傳輸。
簽名和公鑰一樣完全公開,任何人都可以獲取。但這個簽名只有用私鑰對應的公鑰才能解開,拿到摘要后,再比對原文驗證完整性,就可以像簽署文件一樣證明消息確實是你發(fā)的。
剛才的這兩個行為也有專用術語,叫做“簽名”和“驗簽”。
只要你和網站互相交換公鑰,就可以用“簽名”和“驗簽”來確認消息的真實性,因為私鑰保密,黑客不能偽造簽名,就能夠保證通信雙方的身份。
1.4、數字證書和 CA
到現在,綜合使用對稱加密、非對稱加密和摘要算法,我們已經實現了安全的四大特性,是
不是已經完美了呢?
不是的,這里還有一個**“公鑰的信任”問題**。因為誰都可以發(fā)布公鑰,我們還缺少防止黑客偽造公鑰的手段,也就是說,怎么來判斷這個公鑰就是你或者某寶的公鑰呢?
找一個公認的可信第三方,讓它作為“信任的起點,遞歸的終點”,構建起公鑰的信任鏈。
這個“第三方”就是我們常說的CA(Certificate Authority,證書認證機構)。它就像網絡世界里的公安局、教育部、公證中心,具有極高的可信度,由它來給各個公鑰簽名,用自身的信譽來保證公鑰無法偽造,是可信的。
CA 對公鑰的簽名認證也是有格式的,不是簡單地把公鑰綁定在持有者身份上就完事了,還要包含序列號、用途、頒發(fā)者、有效時間等等,把這些打成一個包再簽名,完整地證明公鑰關聯的各種信息,形成**“數字證書”(Certificate)**
知名的 CA 全世界就那么幾家,比如 DigiCert、VeriSign、Entrust、Let’s Encrypt 等,
它們簽發(fā)的證書分 DV、OV、EV 三種,區(qū)別在于可信程度。
DV 是最低的,只是域名級別的可信,背后是誰不知道。EV 是最高的,經過了法律和審計的嚴格核查,可以證明網站擁有者的身份(在瀏覽器地址欄會顯示出公司的名字,例如(Apple、GitHub 的網站)。
不過,CA 怎么證明自己呢?
這還是信任鏈的問題。小一點的 CA 可以讓大 CA 簽名認證,但鏈條的最后,也就是Root CA,就只能自己證明自己了,這個就叫“自簽名證書”(Self-Signed Certificate)或者“根證書”(Root Certificate)。你必須相信,否則整個證書信任鏈就走不下去了。
有了這個證書體系,操作系統(tǒng)和瀏覽器都內置了各大 CA 的根證書,上網的時候只要服務器發(fā)過來它的證書,就可以驗證證書里的簽名,順著證書鏈(Certificate Chain)一層層地驗
證,直到找到根證書,就能夠確定證書是可信的,從而里面的公鑰也是可信的。
我們的實驗環(huán)境里使用的證書是“野路子”的自簽名證書(在 Linux 上用 OpenSSL 命令行簽發(fā)),肯定是不會被瀏覽器所信任的,所以用 Chrome 訪問時就會顯示成紅色,標記為不安全。但你只要把它安裝進系統(tǒng)的根證書存儲區(qū)里,讓它作為信任鏈的根,就不會再有危險警告。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DD1p1PF7-1618498415308)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618419775781.png)]
1.5、證書體系的弱點
證書體系(PKI,Public Key Infrastructure)雖然是目前整個網絡世界的安全基礎設施,但絕對的安全是不存在的,它也有弱點,還是關鍵的**“信任”**二字。
如果 CA 失誤或者被欺騙,簽發(fā)了錯誤的證書,雖然證書是真的,可它代表的網站卻是假的。
還有一種更危險的情況,CA 被黑客攻陷,或者 CA 有惡意,因為它(即根證書)是信任的源頭,整個信任鏈里的所有證書也就都不可信了。
這兩種事情并不是“聳人聽聞”,都曾經實際出現過。所以,需要再給證書體系打上一些補丁。
針對第一種,開發(fā)出了 CRL(證書吊銷列表,Certificate revocation list)和 OCSP(在線證書狀態(tài)協議,Online Certificate Status Protocol),及時廢止有問題的證書。
對于第二種,因為涉及的證書太多,就只能操作系統(tǒng)或者瀏覽器從根上“下狠手”了,撤銷對 CA 的信任,列入“黑名單”,這樣它頒發(fā)的所有證書就都會被認為是不安全的。
小結
今天的內容可以簡單概括為四點:
- 摘要算法用來實現完整性,能夠為數據生成獨一無二的“指紋”,常用的算法是 SHA-
2; - 數字簽名是私鑰對摘要的加密,可以由公鑰解密后驗證,實現身份認證和不可否認;
- 公鑰的分發(fā)需要使用數字證書,必須由 CA 的信任鏈來驗證,否則就是不可信的;
- 作為信任鏈的源頭 CA 有時也會不可信,解決辦法有 CRL、OCSP,還有終止信任。
課后作業(yè)
1、為什么公鑰能夠建立信任鏈,用對稱加密算法里的對稱密鑰行不行呢?
2. 假設有一個三級的證書體系(Root CA=> 一級 CA=> 二級 CA),你能詳細解釋一下證書信任鏈的驗證過程嗎?
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ridWyP1q-1618498415309)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420004619.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6aohSf4L-1618498415310)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420018197.png)]
=====
260-TLS1.2連接過程解析
1.1HTTPS建立連接
瀏覽器首先要從 URI 里提取出協議名和域名。因為
協議名是“https”,所以瀏覽器就知道了端口號是默認的 443,它再用 DNS 解析域名,得到目標的 IP 地址,然后就可以使用三次握手與網站建立 TCP 連接了。
在 HTTP 協議里,建立連接后,瀏覽器會立即發(fā)送請求報文。但現在是 HTTPS 協議,它需要再用另外一個“握手”過程,在 TCP 上建立安全連接,之后才是收發(fā) HTTP 報文。
這個“握手”過程與 TCP 有些類似,是 HTTPS 和 TLS 協議里最重要、最核心的部分,懂了它,你就可以自豪地說自己“掌握了HTTPS”。
1.2、TLS 協議的組成
TLS 包含幾個子協議,你也可以理解為它是由幾個不同職責的模塊組成,比較常用的有記錄協議、警報協議、握手協議、變更密碼規(guī)范協議等。
記錄協議(Record Protocol)規(guī)定了 TLS 收發(fā)數據的基本單位:記錄(record)。它有點像是 TCP 里的 segment,所有的其他子協議都需要通過記錄協議發(fā)出。但多個記錄數據可以在一個 TCP 包里一次性發(fā)出,也并不需要像 TCP 那樣返回 ACK。
**警報協議(**Alert Protocol)的職責是向對方發(fā)出警報信息,有點像是 HTTP 協議里的狀態(tài)碼。比如,protocol_version 就是不支持舊版本,bad_certificate 就是證書有問題,收到警報后另一方可以選擇繼續(xù),也可以立即終止連接。
握手協議(Handshake Protocol)是 TLS 里最復雜的子協議,要比 TCP 的 SYN/ACK 復雜的多,瀏覽器和服務器會在握手過程中協商 TLS 版本號、隨機數、密碼套件等信息,然后交換證書和密鑰參數,最終雙方協商得到會話密鑰,用于后續(xù)的混合加密系統(tǒng)。
最后一個是變更密碼規(guī)范協議(Change Cipher Spec Protocol),它非常簡單,就是一個“通知”,告訴對方,后續(xù)的數據都將使用加密保護。那么反過來,在它之前,數據都是明文的。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-h8QXbNNe-1618498415311)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420469965.png)]
1.3、 抓包的準備工作
TLS 握手的前幾個消息都是明文的,能夠在 Wireshark 里直接看。但只要出現了“Change Cipher Spec”,后面的數據就都是密文了,看到的也就會是亂碼,不知道究竟是什么東西。
為了更好地分析 TLS 握手過程,你可以再對系統(tǒng)和 Wireshark 做一下設置,讓瀏覽器導出握手過程中的秘密信息,這樣 Wireshark 就可以把密文解密,還原出明文。
首先,你需要在 Windows 的設置里新增一個系統(tǒng)變量“SSLKEYLOGFILE”,設置瀏覽器日志文件的路徑,如“D:\http_study\www\temp\sslkey.log”(具體的設置過程就不詳細說了,可以在設置里搜索“系統(tǒng)變量”)。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vRt1F7cy-1618498415311)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420600327.png)]
設置好之后,過濾器選擇“tcp port 443”,就可以抓到實驗環(huán)境里的所有 HTTPS 數據了。
如果你覺得麻煩也沒關系,GitHub 上有抓好的包和相應的日志,用 Wireshark 直接打開就行。
1.4、ECDHE 握手過程
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-r9vI8uZB-1618498415312)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420677147.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-prgZcKWV-1618498415313)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420690904.png)]
在 TCP 建立連接之后,瀏覽器會首先發(fā)一個“Client Hello”消息,也就是跟服務器“打招呼”。里面有客戶端的版本號、支持的密碼套件,還有一個隨機數(ClientRandom),用于后續(xù)生成會話密鑰。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-j8Qo9o0N-1618498415314)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420821516.png)]
這個的意思就是:“我這邊有這些這些信息,你看看哪些是能用的,關鍵的隨機數可得留著。”
作為“禮尚往來”,服務器收到“Client Hello”后,會返回一個“Server Hello”消息。把版本號對一下,也給出一個隨機數(Server Random),然后從客戶端的列表里選一個作為本次通信使用的密碼套件,在這里它選擇
了“TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384”
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-oPKUkGFF-1618498415315)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420890500.png)]
這個的意思就是:“版本號對上了,可以加密,你的密碼套件挺多,我選一個最合適的吧,
用橢圓曲線加 RSA、AES、SHA384。我也給你一個隨機數,你也得留著?!?/p>
然后,服務器為了證明自己的身份,就把證書也發(fā)給了客戶端(Server Certificate)。
接下來是一個關鍵的操作,因為服務器選擇了 ECDHE 算法,所以它會在證書后發(fā)送“Server Key Exchange”消息,里面是橢圓曲線的公鑰(Server Params),用來實現密鑰交換算法,再加上自己的私鑰簽名認證。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QEcIHZcQ-1618498415316)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618420937023.png)]
這相當于說:“剛才我選的密碼套件有點復雜,所以再給你個算法的參數,和剛才的隨機數一樣有用,別丟了。為了防止別人冒充,我又蓋了個章?!?/p>
之后是“Server Hello Done”消息,服務器說:“我的信息就是這些,打招呼完畢?!?/p>
這樣第一個消息往返就結束了(兩個 TCP 包),結果是客戶端和服務器通過明文共享了三個信息:Client Random、Server Random 和 Server Params。
客戶端這時也拿到了服務器的證書,那這個證書是不是真實有效的呢?
這就要用到第 25 講里的知識了,開始走證書鏈逐級驗證,確認證書的真實性,再用證書公鑰驗證簽名,就確認了服務器的身份:“剛才跟我打招呼的不是騙子,可以接著往下走?!?/p>
然后,客戶端按照密碼套件的要求,也生成一個橢圓曲線的公鑰(Client Params),用“Client Key Exchange”消息發(fā)給服務器。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Dmv3eATE-1618498415317)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618421047982.png)]
現在客戶端和服務器手里都拿到了密鑰交換算法的兩個參數**(Client Params、Server Params)**,就用 ECDHE 算法一陣算,算出了一個新的東西,叫“Pre-Master”,其實也是一個隨機數。
至于具體的計算原理和過程,因為太復雜就不細說了,但算法可以保證即使黑客截獲了之前的參數,也是絕對算不出這個隨機數的。
現在客戶端和服務器手里有了三個隨機數:Client Random、Server Random 和 Pre-Master。用這三個作為原始材料,就可以生成用于加密會 話的主密鑰,叫“MasterSecret”。而黑客因為拿不到“Pre-Master”,所以也就得不到主密鑰。
為什么非得這么麻煩,非要三個隨機數呢?
這就必須說 TLS 的設計者考慮得非常周到了,他們不信任客戶端或服務器偽隨機數的可靠性,為了保證真正的**“完全隨機”“不可預測”**,把三個不可靠的隨機數混合起來,那么“隨機”的程度就非常高了,足夠讓黑客難以猜測。
你一定很想知道“Master Secret”究竟是怎么算出來的吧,貼一下 RFC 里的公式:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cduDSBZi-1618498415318)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618421177987.png)]
這里的“PRF”就是偽隨機數函數,它基于密碼套件里的最后一個參數,比如這次的SHA384,通過摘要算法來再一次強化“Master Secret”的隨機性。
主密鑰有 48 字節(jié),但它也不是最終用于通信的會話密鑰,還會再用 PRF 擴展出更多的密鑰,比如客戶端發(fā)送用的會話密鑰(client_write_key)、服務器發(fā)送用的會話密鑰(server_write_key)等等,避免只用一個密鑰帶來的安全隱患。
有了主密鑰和派生的會話密鑰,握手就快結束了。客戶端發(fā)一個“Change Cipher Spec”,然后再發(fā)一個“Finished”消息,把之前所有發(fā)送的數據做個摘要,再加密一下,讓服務器做個驗證。
意思就是告訴服務器:“后面都改用對稱算法加密通信了啊,用的就是打招呼時說的AES,加密對不對還得你測一下。
服務器也是同樣的操作,發(fā)“Change Cipher Spec”和“Finished”消息,雙方都驗證加密解密 OK,握手正式結束,后面就收發(fā)被加密的 HTTP 請求和響應了。
1.5、RSA 握手過程
如今主流的 TLS 握手過程,這與傳統(tǒng)的握手有兩點不同。
第一個,使用 ECDHE 實現密鑰交換,而不是 RSA,所以會在服務器端發(fā)出“Server KeyExchange”消息。
第二個,因為使用了 ECDHE,客戶端可以不用等到服務器發(fā)回“Finished”確認握手完畢,立即就發(fā)出 HTTP 報文,省去了一個消息往返的時間浪費。這個叫“TLS False Start”,意思就是“搶跑”,和“TCP Fast Open”有點像,都是不等連接完全建立就提
前發(fā)應用數據,提高傳輸的效率。
大體的流程沒有變,只是“Pre-Master”不再需要用算法生成,而是客戶端直接生成隨機數,然后用服務器的公鑰加密,通過“Client Key Exchange”消息發(fā)給服務器。服務器再用私鑰解密,這樣雙方也實現了共享三個隨機數,就可以生成主密鑰。
1.6、雙向認證
不過上面說的是“單向認證”握手過程,只認證了服務器的身份,而沒有認證客戶端的身份。這是因為通常單向認證通過后已經建立了安全通信,用賬號、密碼等簡單的手段就能夠確認用戶的真實身份。
但為了防止賬號、密碼被盜,有的時候(比如網上銀行)還會使用 U 盾給用戶頒發(fā)客戶端證書,實現“雙向認證”,這樣會更加安全。
雙向認證的流程也沒有太多變化,只是在“Server Hello Done”之后,“Client Key Exchange”之前,客戶端要發(fā)送“Client Certificate”消息,服務器收到后也把證書鏈走一遍,驗證客戶端的身份。
小結
今天我們學習了 HTTPS/TLS 的握手,內容比較多、比較難,不過記住下面四點就可以。
- HTTPS 協議會先與服務器執(zhí)行 TCP 握手,然后執(zhí)行 TLS 握手,才能建立安全連接;
- 握手的目標是安全地交換對稱密鑰,需要三個隨機數,第三個隨機數“Pre-Master”必須加密傳輸,絕對不能讓黑客破解;
- “Hello”消息交換隨機數,“Key Exchange”消息交換“Pre-Master”;
- “Change Cipher Spec”之前傳輸的都是明文,之后都是對稱密鑰加密的密文
課后作業(yè)
1.密碼套件里的那些算法分別在握手過程中起了什么作用?
2. 你能完整地描述一下 RSA 的握手過程嗎?
-
你能畫出雙向認證的流程圖嗎?
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5yc82gLH-1618498415318)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618421538193.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UkHx2i87-1618498415319)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618421548220.png)]
270-TLS1.3特性解析
TLS1.2 已經是 10 年前(2008 年)的“老”協議了,雖然歷經考驗,但畢竟“歲月
不饒人”,在安全、性能等方面已經跟不上如今的互聯網了。
于是經過四年、近 30 個草案的反復打磨,TLS1.3 終于在去年(2018 年)“粉墨登場”,再次確立了信息安全領域的新標準。
TLS1.3 的三個主要改進目標:兼容、安全與性能。
1.1、最大化兼容性
由于 1.1、1.2 等協議已經出現了很多年,很多應用軟件、中間代理(官方稱
為“MiddleBox”)只認老的記錄協議格式,更新改造很困難,甚至是不可行(設備僵化)。
在早期的試驗中發(fā)現,一旦變更了記錄頭字段里的版本號,也就是由 0x303(TLS1.2)改為 0x304(TLS1.3)的話,大量的代理服務器、網關都無法正確處理,最終導致 TLS 握手失敗。
為了保證這些被廣泛部署的“老設備”能夠繼續(xù)使用,避免新協議帶來的“沖擊”,
TLS1.3 不得不做出妥協,保持現有的記錄格式不變,通過“偽裝”來實現兼容,使得
TLS1.3 看上去“像是”TLS1.2。
那么,該怎么區(qū)分 1.2 和 1.3 呢?
這要用到一個新的擴展協議(Extension Protocol),它有點“補充條款”的意思,通過在記錄末尾添加一系列的“擴展字段”來增加新的功能,老版本的 TLS 不認識它可以直接忽
略,這就實現了“后向兼容”。
在記錄頭的 Version 字段被兼容性“固定”的情況下,只要是 TLS1.3 協議,握手
的**“Hello”消息后面就必須有“supported_versions”擴展**,它標記了 TLS 的版本號,使用它就能區(qū)分新舊協議。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-s0UyrgRU-1618498415320)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618421750005.png)]
TLS1.3 利用擴展實現了許多重要的功能,比
如“supported_groups”“key_share”“signature_algorithms”“server_name”等
,這些等后面用到的時候再說。
1.2、強化安全
TLS1.2 在十來年的應用中獲得了許多寶貴的經驗,陸續(xù)發(fā)現了很多的漏洞和加密算法的弱點,所以 TLS1.3 就在協議里修補了這些不安全因素。
比如:
偽隨機數函數由 PRF 升級為 HKDF(HMAC-based Extract-and-Expand Key
Derivation Function);
明確禁止在記錄協議里使用壓縮;
廢除了 RC4、DES 對稱加密算法;
廢除了 ECB、CBC 等傳統(tǒng)分組模式;
廢除了 MD5、SHA1、SHA-224 摘要算法;
廢除了 RSA、DH 密鑰交換算法和許多命名曲線。
經過這一番“減肥瘦身”之后,TLS1.3 里只保留了 AES、ChaCha20 對稱加密算法,分組模式只能用 AEAD 的 GCM、CCM 和 Poly1305,摘要算法只能用 SHA256、SHA384,密鑰交換算法只有 ECDHE 和 DHE,橢圓曲線也被“砍”到只剩 P-256 和 x25519 等 5種。
減肥可以讓人變得更輕巧靈活,TLS 也是這樣。
算法精簡后帶來了一個意料之中的好處:原來眾多的算法、參數組合導致密碼套件非常復雜,難以選擇,而現在的 TLS1.3 里只有 5 個套件,無論是客戶端還是服務器都不會再犯“選擇困難癥”了。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-fHFvrdof-1618498415320)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618421897072.png)]
這里還要特別說一下廢除 RSA 和 DH 密鑰交換算法的原因。
上一講用 Wireshark 抓包時你一定看到了,瀏覽器默認會使用 ECDHE 而不是 RSA 做密鑰交換,這是因為它不具有**“前向安全”(Forward Secrecy)**。
假設有這么一個很有耐心的黑客,一直在長期收集混合加密系統(tǒng)收發(fā)的所有報文。如果加密系統(tǒng)使用服務器證書里的 RSA 做密鑰交換,一旦私鑰泄露或被破解(使用社會工程學或者巨型計算機),那么黑客就能夠使用私鑰解密出之前所有報文的“Pre-Master”,再算出會話密鑰,破解所有密文。
這就是所謂的**“今日截獲,明日破解”**。
而 ECDHE 算法在每次握手時都會生成一對臨時的公鑰和私鑰,每次通信的密鑰對都是不同的,也就是“一次一密”,即使黑客花大力氣破解了這一次的會話密鑰,也只是這次通信被攻擊,之前的歷史消息不會受到影響,仍然是安全的。
所以現在主流的服務器和瀏覽器在握手階段都已經不再使用 RSA,改用 ECDHE,而TLS1.3 在協議里明確廢除 RSA 和 DH 則在標準層面保證了“前向安全”。
1.3 提升性能
HTTPS 建立連接時除了要做 TCP 握手,還要做 TLS 握手,在 1.2 中會多花兩個消息往返(2-RTT),可能導致幾十毫秒甚至上百毫秒的延遲,在移動網絡中延遲還會更嚴重。
現在因為密碼套件大幅度簡化,也就沒有必要再像以前那樣走復雜的協商流程了。TLS1.3壓縮了以前的“Hello”協商過程,刪除了“Key Exchange”消息,把握手時間減少到了“1-RTT”,效率提高了一倍。
那么它是怎么做的呢?
其實具體的做法還是利用了擴展??蛻舳嗽凇癈lient Hello”消息里直接
用“supported_groups”帶上支持的曲線,比如 P-256、x25519,用“key_share”帶
上曲線對應的客戶端公鑰參數,用“signature_algorithms”帶上簽名算法。
服務器收到后在這些擴展里選定一個曲線和參數,再用“key_share”擴展返回服務器這邊的公鑰參數,就實現了雙方的密鑰交換,后面的流程就和 1.2 基本一樣了。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-AbBRUQ2R-1618498415321)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618422061150.png)]
1.3 握手分析
目前 Nginx 等 Web 服務器都能夠很好地支持 TLS1.3,但要求底層的 OpenSSL 必須是1.1.1,而我們實驗環(huán)境里用的 OpenSSL 是 1.1.0,所以暫時無法直接測試 TLS1.3。
注意“Client Hello”里的擴展**,“supported_versions”表示這是
TLS1.3,“supported_groups”是支持的曲線,“key_share”**是曲線對應的參數。
這就好像是說:
“還是照老規(guī)矩打招呼,這邊有這些這些信息。但我猜你可能會升級,所以再多給你一些東西,也許后面用的上,咱們有話盡量一口氣說完。”
服務器收到“Client Hello”同樣返回“Server Hello”消息,還是要給出一個隨機數
(Server Random)和選定密碼套件。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-tUZQzTKa-1618498415322)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618422201970.png)]
表面上看和 TLS1.2 是一樣的,重點是后面的擴展?!皊upported_versions”里確認使用的是 TLS1.3,然后在“key_share”擴展帶上曲線和對應的公鑰參數。
服務器的“Hello”消息大概是這個意思:
“還真讓你給猜對了,雖然還是按老規(guī)矩打招呼,但咱們來個‘舊瓶裝新酒’。剛才你給的我都用上了,我再給幾個你缺的參數,這次加密就這么定了。”
這時只交換了兩條消息,客戶端和服務器就拿到了**四個共享信息:Client Random和Server Random、Client Params和Server Params,**兩邊就可以各自用 ECDHE 算出“Pre-Master”,再用 HKDF 生成主密鑰“Master Secret”,效率比 TLS1.2 提高了一大截。
在算出主密鑰后,服務器立刻發(fā)出**“Change Cipher Spec”消息**,比 TLS1.2 提早進入加密通信,后面的證書等就都是加密的了,減少了握手時的明文信息泄露。
這里 TLS1.3 還有一個安全強化措施,多了個**“Certificate Verify”消息**,用服務器的私鑰把前面的曲線、套件、參數等握手數據加了簽名,作用和“Finished”消息差不多。但由于是私鑰簽名,所以強化了身份認證和和防竄改。
這兩個“Hello”消息之后,客戶端驗證服務器證書,再發(fā)“Finished”消息,就正式完成了握手,開始收發(fā) HTTP 報文。
小結
學習了 TLS1.3 的新特性,用抓包研究了它的握手過程,不過 TLS1.3 里的內
容很多,還有一些特性沒有談到,后面會繼續(xù)講。
- 為了兼容 1.1、1.2 等“老”協議,TLS1.3 會“偽裝”成 TLS1.2,新特性在“擴展”里
實現; - 1.1、1.2 在實踐中發(fā)現了很多安全隱患,所以 TLS1.3 大幅度刪減了加密算法,只保留了ECDHE、AES、ChaCha20、SHA-2 等極少數算法,強化了安全;
- TLS1.3 也簡化了握手過程,完全握手只需要一個消息往返,提升了性能。
課下作業(yè):
- TLS1.3 里的密碼套件沒有指定密鑰交換算法和簽名算法,那么在握手的時候會不會有問
題呢? - 結合上一講的 RSA 握手過程,解釋一下為什么 RSA 密鑰交換不具有“前向安全”。
- TLS1.3 的握手過程與 TLS1.2 的“False Start”有什么異同?
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0MkkxN26-1618498415323)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618422380535.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Uq7iUeDY-1618498415324)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618422389606.png)]
==========
280-HTTPS的優(yōu)化
HTTPS 連接大致上可以劃分為兩個部分,第一個是建立
連接時的非對稱加密握手,第二個是握手后的對稱加密報文傳輸。
由于目前流行的 AES、ChaCha20 性能都很好,還有硬件優(yōu)化,報文傳輸的性能損耗可以說是非常地小,小到幾乎可以忽略不計了。所以,通常所說的“HTTPS 連接慢”指的就是剛開始建立連接的那段時間。
在 TCP 建連之后,正式數據傳輸之前,HTTPS 比 HTTP 增加了一個 TLS 握手的步驟,這個步驟最長可以花費兩個消息往返,也就是 2-RTT。而且在握手消息的網絡耗時之外,還會有其他的一些“隱形”消耗,比如:
產生用于密鑰交換的臨時公私鑰對(ECDHE);
驗證證書時訪問 CA 獲取 CRL 或者 OCSP;
非對稱加密解密處理“Pre-Master”。
在最差的情況下,也就是不做任何的優(yōu)化措施,HTTPS 建立連接可能會比 HTTP 慢上幾百毫秒甚至幾秒,這其中既有網絡耗時,也有計算耗時,就會讓人產生“打開一個 HTTPS 網站好慢啊”的感覺。
不過剛才說的情況早就是“過去時”了,現在已經有了很多行之有效的 HTTPS 優(yōu)化手段,運用得好可以把連接的額外耗時降低到幾十毫秒甚至是“零”。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-s8pxgOyv-1618498415324)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618422564136.png)]
1.1、 硬件優(yōu)化
在計算機世界里的“優(yōu)化”可以分成“硬件優(yōu)化”和“軟件優(yōu)化”兩種方式,先來看看有哪
些硬件的手段。
HTTPS 連接是計算密集型,而不是 I/O 密集型。所以,如果你花大價錢去買網卡、帶寬、SSD 存儲就是“南轅北轍”了,起不到優(yōu)化的效果。
那該用什么樣的硬件來做優(yōu)化呢?
首先,你可以選擇更快的 CPU,最好還內建 AES 優(yōu)化,這樣即可以加速握手,也可以加速傳輸。
其次,你可以選擇“SSL 加速卡”,加解密時調用它的 API,讓專門的硬件來做非對稱加解密,分擔 CPU 的計算壓力。
不過“SSL 加速卡”也有一些缺點,比如升級慢、支持算法有限,不能靈活定制解決方案等。
所以,就出現了第三種硬件加速方式:“SSL 加速服務器”,用專門的服務器集群來徹底“卸載”TLS 握手時的加密解密計算,性能自然要比單純的“加速卡”要強大的多。
1.2、軟件優(yōu)化
軟件優(yōu)化的方式相對來說更可行一些,性價比高,能夠“少花錢,多辦事”。
軟件方面的優(yōu)化還可以再分成兩部分:一個是軟件升級,一個是協議優(yōu)化。
軟件升級實施起來比較簡單,就是把現在正在使用的軟件盡量升級到最新版本,比如把Linux 內核由 2.x 升級到 4.x,把 Nginx 由 1.6 升級到 1.16,把 OpenSSL 由 1.0.1 升級到1.1.0/1.1.1。
由于這些軟件在更新版本的時候都會做性能優(yōu)化、修復錯誤,只要運維能夠主動配合,這種軟件優(yōu)化是最容易做的,也是最容易達成優(yōu)化效果的。
但對于很多大中型公司來說,硬件升級或軟件升級都是個棘手的問題,有成千上萬臺各種型號的機器遍布各個機房,逐一升級不僅需要大量人手,而且有較高的風險,可能會影響正常的線上服務。
所以,在軟硬件升級都不可行的情況下,我們最常用的優(yōu)化方式就是在現有的環(huán)境下挖掘協議自身的潛力。
1.3 協議優(yōu)化
從剛才的 TLS 握手圖中你可以看到影響性能的一些環(huán)節(jié),協議優(yōu)化就要從這些方面著手,先來看看核心的密鑰交換過程。
如果有可能,應當盡量采用 TLS1.3,它大幅度簡化了握手的過程,完全握手只要 1-RTT,而且更加安全。
如果暫時不能升級到 1.3,只能用 1.2,那么握手時使用的密鑰交換協議應當盡量選用橢圓曲線的 ECDHE 算法。它不僅運算速度快,安全性高,還支持“False Start”,能夠把握手的消息往返由 2-RTT 減少到 1-RTT,達到與 TLS1.3 類似的效果。
另外,橢圓曲線也要選擇高性能的曲線,最好是 x25519,次優(yōu)選擇是 P-256。對稱加密算法方面,也可以選用“AES_128_GCM”,它能比“AES_256_GCM”略快一點點。
在 Nginx 里可以用“ssl_ciphers”“ssl_ecdh_curve”等指令配置服務器使用的密碼套件
和橢圓曲線,把優(yōu)先使用的放在前面,例如:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vBB6P12K-1618498415325)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618422851316.png)]
1.4 證書優(yōu)化
除了密鑰交換,握手過程中的證書驗證也是一個比較耗時的操作,服務器需要把自己的證書鏈全發(fā)給客戶端,然后客戶端接收后再逐一驗證。
這里就有兩個優(yōu)化點,一個是證書傳輸,一個是證書驗證。
服務器的證書可以選擇橢圓曲線(ECDSA)證書而不是 RSA 證書,因為 224 位的 ECC 相當于 2048 位的 RSA,所以橢圓曲線證書的“個頭”要比 RSA 小很多,即能夠節(jié)約帶寬也能減少客戶端的運算量,可謂“一舉兩得”。
客戶端的證書驗證其實是個很復雜的操作,除了要公鑰解密驗證多個證書簽名外,因為證書還有可能會被撤銷失效,客戶端有時還會再去訪問 CA,下載 CRL 或者 OCSP 數據,這又會產生 DNS 查詢、建立連接、收發(fā)數據等一系列網絡通信,增加好幾個 RTT。
CRL(Certificate revocation list,證書吊銷列表)由 CA 定期發(fā)布,里面是所有被撤銷信任的證書序號,查詢這個列表就可以知道證書是否有效。
但 CRL 因為是“定期”發(fā)布,就有“時間窗口”的安全隱患,而且隨著吊銷證書的增多,列表會越來越大,一個 CRL 經常會上 MB。想象一下,每次需要預先下載幾 M 的“無用數據”才能連接網站,實用性實在是太低了。
所以,現在 CRL 基本上不用了,取而代之的是 OCSP(在線證書狀態(tài)協議,Online Certificate Status Protocol),向 CA 發(fā)送查詢請求,讓 CA 返回證書的有效狀態(tài)。
但 OCSP 也要多出一次網絡請求的消耗,而且還依賴于 CA 服務器,如果 CA 服務器很忙,那響應延遲也是等不起的。
于是又出來了一個“補丁”,叫“OCSP Stapling”(OCSP 裝訂),它可以讓服務器預先訪問 CA 獲取 OCSP 響應,然后在握手時隨著證書一起發(fā)給客戶端,免去了客戶端連接 CA服務器查詢的時間。
1.4 會話復用
到這里,我們已經討論了四種 HTTPS 優(yōu)化手段(硬件優(yōu)化、軟件優(yōu)化、協議優(yōu)化、證書優(yōu)化),那么,還有沒有其他更好的方式呢?
我們再回想一下 HTTPS 建立連接的過程:先是 TCP 三次握手,然后是 TLS 一次握手。這后一次握手的重點是算出主密鑰“Master Secret”,而主密鑰每次連接都要重新計算,未免有點太浪費了,如果能夠把“辛辛苦苦”算出來的主密鑰緩存一下“重用”,不就可以免去了握手和計算的成本了嗎?
這種做法就叫“會話復用”(TLS session resumption),和 HTTP Cache 一樣,也是提高 HTTPS 性能的“大殺器”,被瀏覽器和服務器廣泛應用。
會話復用分兩種,第一種叫“Session ID”,就是客戶端和服務器首次連接后各自保存一個會話的 ID 號,內存里存儲主密鑰和其他相關的信息。當客戶端再次連接時發(fā)一個 ID 過來,服務器就在內存里找,找到就直接用主密鑰恢復會話狀態(tài),跳過證書驗證和密鑰交換,只用一個消息往返就可以建立安全通信。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hWYO46pQ-1618498415326)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618423083004.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hDeVUnkj-1618498415327)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618423095145.png)]
通過抓包可以看到,服務器在“ServerHello”消息后直接發(fā)送了“Change Cipher
Spec”和“Finished”消息,復用會話完成了握手。
1.4 會話票證
“Session ID”是最早出現的會話復用技術,也是應用最廣的,但它也有缺點,服務器必須保存每一個客戶端的會話數據,對于擁有百萬、千萬級別用戶的網站來說存儲量就成了大問題,加重了服務器的負擔。
于是,又出現了第二種“Session Ticket”方案。
它有點類似 HTTP 的 Cookie,存儲的責任由服務器轉移到了客戶端,服務器加密會話信息,用“New Session Ticket”消息發(fā)給客戶端,讓客戶端保存。
重連的時候,客戶端使用擴展“session_ticket”發(fā)送“Ticket”而不是“Session ID”,
服務器解密后驗證有效期,就可以恢復會話,開始加密通信。
不過“Session Ticket”方案需要使用一個固定的密鑰文件(ticket_key)來加密 Ticket,為了防止密鑰被破解,保證“前向安全”,密鑰文件需要定期輪換,比如設置為一小時或者一天。
1.5 預共享密鑰
“False Start”“Session ID”“Session Ticket”等方式只能實現 1-RTT,而 TLS1.3 更
進一步實現了**“0-RTT”,原理和“Session Ticket”差不多,但在發(fā)送 Ticket 的同時會
帶上應用數據(Early Data),免去了 1.2 里的服務器確認步驟,這種方式叫“Pre-**
shared Key”,簡稱為“PSK”。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mObWW2Zt-1618498415327)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618423280586.png)]
但“PSK”也不是完美的,它為了追求效率而犧牲了一點安全性,容易受到“重放攻
擊”(Replay attack)的威脅。黑客可以截獲“PSK”的數據,像復讀機那樣反復向服務器發(fā)送。解決的辦法是只允許安全的 GET/HEAD 方法(參見第 10 講),在消息里加入時間戳、“nonce”驗證,或者“一次性票證”限制重放。
小結
- 可以有多種硬件和軟件手段減少網絡耗時和計算耗時,讓 HTTPS 變得和 HTTP 一樣快,最可行的是軟件優(yōu)化;
- 應當盡量使用 ECDHE 橢圓曲線密碼套件,節(jié)約帶寬和計算量,還能實現“False Start”;
- 服務器端應當開啟“OCSP Stapling”功能,避免客戶端訪問 CA 去驗證證書;
- 會話復用的效果類似 Cache,前提是客戶端必須之前成功建立連接,后面就可以用“Session ID”“Session Ticket”等憑據跳過密鑰交換、證書驗證等步驟,直接開始加密通信。
課下作業(yè)
-
你能比較一下“Session ID”“Session Ticket”“PSK”這三種會話復用手段的異同
嗎? -
你覺得哪些優(yōu)化手段是你在實際工作中能用到的?應該怎樣去用?
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-eJIzqxV9-1618498415328)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618423348610.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Dr00u5uQ-1618498415328)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618423357164.png)]
==========
290-遷移到HTTPS
1/遷移的必要性
如果你做移動應用開發(fā)的話,那么就一定知道,Apple、Android、某信等開發(fā)平臺在2017 年就相繼發(fā)出通知,要求所有的應用必須使用 HTTPS 連接,禁止不安全的 HTTP。
在臺式機上,主流的瀏覽器 Chrome、Firefox 等也早就開始“強推”HTTPS,把 HTTP 站點打上“不安全”的標簽,給用戶以“心理壓力”。
Google 等搜索巨頭還利用自身的“話語權”優(yōu)勢,降低 HTTP 站點的排名,而給 HTTPS更大的權重,力圖讓網民只訪問到 HTTPS 網站。
這些手段都逐漸“擠壓”了純明文 HTTP 的生存空間,“遷移到 HTTPS”已經不是“要不
要做”的問題,而是“要怎么做”的問題了。HTTPS 的大潮無法阻擋,如果還是死守著HTTP,那么無疑會被沖刷到互聯網的角落里。
2、遷移的顧慮
據我觀察,阻礙 HTTPS 實施的因素還有一些這樣、那樣的顧慮,我總結出了三個比較流行的觀點:“慢、貴、難”。
所謂**“慢”**,是指慣性思維,拿以前的數據來評估 HTTPS 的性能,認為 HTTPS 會增加服務器的成本,增加客戶端的時延,影響用戶體驗。
所謂**“貴”**,主要是指證書申請和維護的成本太高,網站難以承擔。
所謂的**“難”**,是指 HTTPS 涉及的知識點太多、太復雜,有一定的技術門檻,不能很快上手。
為了推廣 HTTPS,很多云服務廠商都提供了一鍵申請、價格低廉的證
書,而且還出現了專門頒發(fā)免費證書的 CA,其中最著名的就是“Let’s Encrypt”。
3.申請證書
要把網站從 HTTP 切換到 HTTPS,首先要做的就是為網站申請一張證書。
大型網站出于信譽、公司形象的考慮,通常會選擇向傳統(tǒng)的 CA 申請證書,例如
DigiCert、GlobalSign,而中小型網站完全可以選擇使用“Let’s Encrypt”這樣的免費證書,效果也完全不輸于那些收費的證書。
**“Let’s Encrypt”**一直在推動證書的自動化部署,為此還實現了專門的 ACME 協議
(RFC8555)。有很多的客戶端軟件可以完成申請、驗證、下載、更新的“一條龍”操作,比如 Certbot、acme.sh 等等,都可以在“Let’s Encrypt”網站上找到,用法很簡單,相關的文檔也很詳細,幾分鐘就能完成申請,所以我在這里就不細說了。
不過我必須提醒你幾個注意事項。
第一,申請證書時應當同時申請 RSA 和 ECDSA 兩種證書,在 Nginx 里配置成雙證書驗證,這樣服務器可以自動選擇快速的橢圓曲線證書,同時也兼容只支持 RSA 的客戶端。
第二,如果申請 RSA 證書,私鑰至少要 2048 位,摘要算法應該選用 SHA-2,例如SHA256、SHA384 等。
第三,出于安全的考慮,“Let’s Encrypt”證書的有效期很短,只有 90 天,時間一到就會過期失效,所以必須要定期更新。你可以在 crontab 里加個每周或每月任務,發(fā)送更新請求,不過很多 ACME 客戶端會自動添加這樣的定期任務,完全不用你操心。
4.配置HTTPS
定了證書,接下來就是配置 Web 服務器,在 443 端口上開啟 HTTPS 服務了。
這在 Nginx 上非常簡單,只要在“l(fā)isten”指令后面加上參數“ssl”,再配上剛才的證書文件就可以實現最基本的 HTTPS。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-97voIkn4-1618498415329)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618449334322.png)]
為了提高 HTTPS 的安全系數和性能,你還可以強制 Nginx 只支持 TLS1.2 以上的協議,打開“Session Ticket”會話復用。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-yuQaJGnb-1618498415329)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618449359504.png)]
密碼套件的選擇方面,我給你的建議是以服務器的套件優(yōu)先。這樣可以避免惡意客戶端故意選擇較弱的套件、降低安全等級,然后密碼套件向 TLS1.3“看齊”,只使用 ECDHE、AES和 ChaCha20,支持“False Start”。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Sbnk4zzw-1618498415330)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618449383133.png)]
如果你的服務器上使用了 OpenSSL 的分支 BorringSSL,那么還可以使用一個特殊的“等價密碼組”(Equal preference cipher groups)特性,它可以讓服務器配置一組“等價”的密碼套件,在這些套件里允許客戶端優(yōu)先選擇,比如這么配置:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3nh7JVw8-1618498415331)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618449411916.png)]
如果客戶端硬件沒有 AES 優(yōu)化,服務器就會順著客戶端的意思,優(yōu)先選擇與 AES“等價”的 ChaCha20 算法,讓客戶端能夠快一點。
全部配置完成后,你可以訪問“SSLLabs”網站https://www.ssllabs.com/,測試網站的安全程度,它會模擬多種客戶端發(fā)起測試,打出一個綜合的評分。
5.服務器名稱指示
配置 HTTPS 服務時還有一個“虛擬主機”的問題需要解決。
在 HTTP 協議里,多個域名可以同時在一個 IP 地址上運行,這就是“虛擬主機”,Web
服務器會使用請求頭里的 Host 字段(參見第 9 講)來選擇。
但在 HTTPS 里,因為請求頭只有在 TLS 握手之后才能發(fā)送,在握手時就必須選擇“虛擬主機”對應的證書,TLS 無法得知域名的信息,就只能用 IP 地址來區(qū)分。所以,最早的時候每個 HTTPS 域名必須使用獨立的 IP 地址,非常不方便。
那么怎么解決這個問題呢?
這還是得用到 TLS 的“擴展”,給協議加個SNI(Server Name Indication)的“補充條款”。它的作用和 Host 字段差不多,客戶端會在“Client Hello”時帶上域名信息,這樣服務器就可以根據名字而不是 IP 地址來選擇證書。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-58sSZx3z-1618498415332)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618449625440.png)]
Nginx 很早就基于 SNI 特性支持了 HTTPS 的虛擬主機,但在 OpenResty 里可還以編寫Lua 腳本,利用 Redis、MySQL 等數據庫更靈活快速地加載證書。
6.重定向跳轉
現在有了 HTTPS 服務,但原來的 HTTP 站點也不能馬上棄用,還是會有很多網民習慣在地址欄里直接敲域名(或者是舊的書簽、超鏈接),默認使用 HTTP 協議訪問。
所以,我們就需要用到第 18 講里的“重定向跳轉”技術了,把不安全的 HTTP 網址用 301或 302“重定向”到新的 HTTPS 網站,這在 Nginx 里也很容易做到,使
用“return”或“rewrite”都可以。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Mhqgv6Un-1618498415332)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618449690347.png)]
但這種方式有兩個問題。一個是重定向增加了網絡成本,多出了一次請求;另一個是存在安全隱患,重定向的響應可能會被“中間人”竄改,實現“會話劫持”,跳轉到惡意網站。
不過有一種叫“HSTS”(HTTP 嚴格傳輸安全,HTTP Strict Transport Security)的技術可以消除這種安全隱患。HTTPS 服務器需要在發(fā)出的響應頭里添加一個“Strict-Transport-Security”的字段,再設定一個有效期,
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Pb7rZa45-1618498415333)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618449761842.png)]
這相當于告訴瀏覽器:我這個網站必須嚴格使用 HTTPS 協議,在半年之內(182.5 天)都不允許用 HTTP,你以后就自己做轉換吧,不要再來麻煩我了。
有了“HSTS”的指示,以后瀏覽器再訪問同樣的域名的時候就會自動把 URI 里
的“http”改成“https”,直接訪問安全的 HTTPS 網站。這樣“中間人”就失去了攻擊
的機會,而且對于客戶端來說也免去了一次跳轉,加快了連接速度。
如果在實驗環(huán)境的配置文件里用“add_header”指令添加“HSTS”字段:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-NF0hcp4O-1618498415334)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618449822810.png)]
那么 Chrome 瀏覽器只會在第一次連接時使用 HTTP 協議,之后就會都走 HTTPS 協議。
小結
今天我介紹了一些 HTTPS 遷移的技術要點,掌握了它們你就可以搭建出一個完整的HTTPS 站點了。
但想要實現大型網站的“全站 HTTPS”還是需要有很多的細枝末節(jié)的工作要做,比如使用CSP(Content Security Policy)的各種指令和標簽來配置安全策略,使用反向代理來集中“卸載”SSL,話題太大,以后有機會再細談吧。
-
從 HTTP 遷移到 HTTPS 是“大勢所趨”,能做就應該盡早做;
-
升級 HTTPS 首先要申請數字證書,可以選擇免費好用的“Let’s Encrypt”;
-
配置 HTTPS 時需要注意選擇恰當的 TLS 版本和密碼套件,強化安全;
-
原有的 HTTP 站點可以保留作為過渡,使用 301 重定向到 HTTPS。
課下作業(yè)
-
結合你的實際工作,分析一下遷移 HTTPS 的難點有哪些,應該如何克服?
-
參考上一講,你覺得配置 HTTPS 時還應該加上哪些部分?
-
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zgIzKUL4-1618498415334)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618450394347.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-NknMx1dk-1618498415335)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1618450406549.png)]
瀏覽器:我這個網站必須嚴格使用 HTTPS 協議,在半年之內(182.5 天)都不允許用 HTTP,你以后就自己做轉換吧,不要再來麻煩我了。
有了“HSTS”的指示,以后瀏覽器再訪問同樣的域名的時候就會自動把 URI 里
的“http”改成“https”,直接訪問安全的 HTTPS 網站。這樣“中間人”就失去了攻擊
的機會,而且對于客戶端來說也免去了一次跳轉,加快了連接速度。
如果在實驗環(huán)境的配置文件里用“add_header”指令添加“HSTS”字段:
[外鏈圖片轉存中…(img-NF0hcp4O-1618498415334)]
那么 Chrome 瀏覽器只會在第一次連接時使用 HTTP 協議,之后就會都走 HTTPS 協議。
小結
今天我介紹了一些 HTTPS 遷移的技術要點,掌握了它們你就可以搭建出一個完整的HTTPS 站點了。
但想要實現大型網站的“全站 HTTPS”還是需要有很多的細枝末節(jié)的工作要做,比如使用CSP(Content Security Policy)的各種指令和標簽來配置安全策略,使用反向代理來集中“卸載”SSL,話題太大,以后有機會再細談吧。
-
從 HTTP 遷移到 HTTPS 是“大勢所趨”,能做就應該盡早做;
-
升級 HTTPS 首先要申請數字證書,可以選擇免費好用的“Let’s Encrypt”;
-
配置 HTTPS 時需要注意選擇恰當的 TLS 版本和密碼套件,強化安全;
-
原有的 HTTP 站點可以保留作為過渡,使用 301 重定向到 HTTPS。
課下作業(yè)
-
結合你的實際工作,分析一下遷移 HTTPS 的難點有哪些,應該如何克服?
-
參考上一講,你覺得配置 HTTPS 時還應該加上哪些部分?
-
[外鏈圖片轉存中…(img-zgIzKUL4-1618498415334)]文章來源:http://www.zghlxwxcb.cn/news/detail-753508.html
[外鏈圖片轉存中…(img-NknMx1dk-1618498415335)]文章來源地址http://www.zghlxwxcb.cn/news/detail-753508.html
到了這里,關于HTTPS安全相關-通信安全的四個特性-ssl/tls的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!