原文地址:https://cshihong.github.io/2019/05/09/SSL%E5%8D%8F%E8%AE%AE%E8%AF%A6%E8%A7%A3/
SSL VPN可參考:SSL VPN技術原理
SSL簡介
SSL和TLS:
SSL (Secure Sockets Layer)安全套接層。是由Netscape公司於1990年開發,用於保障Word Wide Web(WWW)通訊的安全。主要任務是提供私密性,信息完整性和身份認證。1994年改版為SSLv2,1995年改版為SSLv3.
TLS(Transport Layer Security)安全傳輸層協議,)用於在兩個通信應用程序之間提供保密性和數據完整性。該標准協議是由IETF於1999年頒布,整體來說TLS非常類似SSLv3,只是對SSLv3做了些增加和修改。
SSL協議介紹:
SSL是一個不依賴於平台和運用程序的協議,位於TCP/IP協議與各種應用層協議之間,為數據通信提高安全支持。
SSL加密知名協議:
HTTP over SSL:
簡寫https,加密網頁瀏覽是設計SSL的初衷,HTTP也是第一個使用SSL保障安全的應用層協議。
當Netscape在它的Navigator里面運用HTTP over SSL的時候,使用https://來標識HTTP over SSL,因此我常見的https的全稱就是HTTP over SSL。后來HTTPS在RFC2818被標准化。HTTPS工作在443端口,而HTTP默認工作在80端口。
Email over SSL:
類似於HTTP over SSL,郵件協議例如:
- SMTP,POP3、IMAP也能支持SSL。
- SMTP over TLS的標准文檔在RFC2487
- POP3和IMAP over TLS的標准化文檔在RFC2595.
SSL原理詳解
SSL協議結構:
SSL的體系結構中包含兩個協議子層,其中底層是SSL記錄協議層(SSL Record Protocol Layer);高層是SSL握手協議層(SSL HandShake Protocol Layer)。
SSL協議主要分為兩層:
-
SSL記錄協議層的作用是為高層協議提供基本的安全服務。SSL記錄協議針對HTTP協議進行了特別的設計,使得超文本的傳輸協議HTTP能夠在SSL運行。紀錄封裝各種高層協議,具體實施壓縮解壓縮、加密解密、計算和校驗MAC等與安全有關的操作。
-
SSL握手協議層包括SSL握手協議(SSL HandShake Protocol)、SSL密碼參數修改協議(SSL Change Cipher Spec Protocol)和SSL告警協議(SSL Alert Protocol)。握手層的這些協議用於SSL管理信息的交換,允許應用協議傳送數據之間相互驗證,協商加密算法和生成密鑰等。
SSL握手協議的作用是協調客戶和服務器的狀態,使雙方能夠達到狀態的同步。
其中最重要的是記錄協議和握手協議:
- SSL記錄協議:它建立在可靠的傳輸(如TCP)之上,為高層協議提供數據封裝、壓縮、加密等基本功能。
- SSL握手協議:它建立在SSL記錄協議之上,用於在實際的數據傳輸開始之前,通訊雙方進行身份認證、協商加密算法、交換加密密鑰等。
SSL建立階段與IPSec VPN類比的話:
可以分為兩個大階段:
(1)SSL建立的第一階段:Handshake phase(握手階段):
- 協商加密算法
- 認證服務器
- 建立用於加密和MAC(Message Authentication Code)用的密鑰
該階段類似於IPSec VPN IKE的作用。
(2)SSL建立第二階段:Secure data transfer phase(安全的數據傳輸階段):
- 在已經建立的SSL連接里安全的傳輸數據。
該階段類似於IPSec VPN ESP的作用
SSL原理(SSL建立)握手協議總過程:
在用SSL進行通信之前,首先要使用SSL的Handshake協議在通信兩端握手,協商數據傳輸中要用到的相關安全參數(如加密算法、共享密鑰、產生密鑰所要的材料等),並對對端的身份進行驗證。
SSL的建立過程總共有13個包,第一次建立至少需要9個包。
SSL建立第一階段:
客戶端首先發送ClientHello消息到服務端,服務端收到ClientHello消息后,再發送ServerHello消息回應客戶端。
ClientHello
握手第一步是客戶端向服務端發送 Client Hello 消息,這個消息里包含了一個客戶端生成的隨機數 Random1、客戶端支持的加密套件(Support Ciphers)和 SSL Version 等信息。
ClientHello中涉及到的消息具體如下:
-
客戶端版本
按優先級列出客戶端支持的協議版本,首選客戶端希望支持的最新協議版本。
-
客戶端隨機數Random
-
會話ID(Session id)
如果客戶端第一次連接到服務器,那么這個字段就會保持為空。上圖中該字段為空,說明這是第一次連接到服務器。
如果該字段不為空,說明以前是與服務器有連接的,在此期間,服務器將使用Session ID映射對稱密鑰,並將Session ID存儲在客戶端瀏覽器中,為映射設置一個時間限。如果瀏覽器將來連接到同一台服務器(在時間到期之前),它將發送Session ID,服務器將對映射的Session ID進行驗證,並使用以前用過的對稱密鑰來恢復Session,這種情況下不需要完全握手。也叫作SSL會話恢復。后面會有介紹。
-
加密套件:
客戶端會給服務器發送自己已經知道的密碼套件列表,這是由客戶按優先級排列的,但完全由服務器來決定發送與否。TLS中使用的密碼套件有一種標准格式。上面的報文中,客戶端發送了74套加密套件。服務端會從中選出一種來作為雙方共同的加密套件。
-
壓縮方法:
為了減少帶寬,可以進行壓縮。但從成功攻擊TLS的事例中來看,其中使用壓縮時的攻擊可以捕獲到用HTTP頭發送的參數,這個攻擊可以劫持Cookie,這個漏洞我們稱為CRIME。從TLS 1.3開始,協議就禁用了TLS壓縮。
-
擴展包:
其他參數(如服務器名稱,填充,支持的簽名算法等)可以作為擴展名使用。
這些是客戶端問候的一部分,如果已收到客戶端問候,接下來就是服務器的確認,服務器將發送服務器問候。
ServerHello
收到客戶端問候之后服務器必須發送服務器問候信息,服務器會檢查指定諸如TLS版本和算法的客戶端問候的條件,如果服務器接受並支持所有條件,它將發送其證書以及其他詳細信息,否則,服務器將發送握手失敗消息。
如果接受,第二步是服務端向客戶端發送 Server Hello 消息,這個消息會從 Client Hello 傳過來的 Support Ciphers 里確定一份加密套件,這個套件決定了后續加密和生成摘要時具體使用哪些算法,另外還會生成一份隨機數 Random2。注意,至此客戶端和服務端都擁有了兩個隨機數(Random1+ Random2),這兩個隨機數會在后續生成對稱秘鑰時用到。
ServerHello中涉及到的具體參數:
-
服務器版本Version:
服務器會選擇客戶端支持的最新版本。
-
服務器隨機數Random:
服務器和客戶端都會生成32字節的隨機數。用來創建加密密鑰。
-
加密套件:
服務器會從客戶端發送的加密套件列表中選出一個加密套件。
-
會話ID(Session ID):
服務器將約定的Session參數存儲在TLS緩存中,並生成與其對應的Session id。它與Server Hello一起發送到客戶端。客戶端可以寫入約定的參數到此Session id,並給定到期時間。客戶端將在Client Hello中包含此id。如果客戶端在此到期時間之前再次連接到服務器,則服務器可以檢查與Session id對應的緩存參數,並重用它們而無需完全握手。這非常有用,因為服務器和客戶端都可以節省大量的計算成本。
在涉及亞馬遜和谷歌等流量巨大的應用程序時,這種方法存在缺點。每天都有數百萬人連接到服務器,服務器必須使用Session密鑰保留所有Session參數的TLS緩存。這是一個巨大的開銷。
為了解決這個問題,在擴展包里加入了Session Tickets, 在這里,客戶端可以在client hello中指定它是否支持Session Ticket。然后,服務器將創建一個新的會話票證(Session Ticket),並使用只有服務器知道的經過私鑰加密的Session參數。它將存儲在客戶端上,因此所有Session數據僅存儲在客戶端計算機上,但Ticket仍然是安全的,因為該密鑰只有服務器知道。
此數據可以作為名為Session Ticket的擴展包含在Client Hello中。
-
壓縮算法:
如果支持,服務器將同意客戶端的首選壓縮方法。
-
擴展包
這個階段之后,客戶端服務端知道了下列內容:
- SSL版本
- 密鑰交換、信息驗證和加密算法
- 壓縮方法
- 有關密鑰生成的兩個隨機數。
SSL建立第二階段:
服務器向客戶端發送消息。
服務器啟動SSL握手第2階段,是本階段所有消息的唯一發送方,客戶機是所有消息的唯一接收方。該階段分為4步:
- 證書:服務器將數字證書和到根CA整個鏈發給客戶端,使客戶端能用服務器證書中的服務器公鑰認證服務器。
- 服務器密鑰交換(可選):這里視密鑰交換算法而定
- 證書請求:服務端可能會要求客戶自身進行驗證。
- 服務器握手完成:第二階段的結束,第三階段開始的信號
Certificate消息(可選)—第一次建立必須要有證書
一般情況下,除了會話恢復時不需要發送該消息,在SSL握手的全流程中,都需要包含該消息。消息包含一個X.509證書,證書中包含公鑰,發給客戶端用來驗證簽名或在密鑰交換的時候給消息加密。
這一步是服務端將自己的證書下發給客戶端,讓客戶端驗證自己的身份,客戶端驗證通過后取出證書中的公鑰。
Server Key Exchange(可選)
根據之前在ClientHello消息中包含的CipherSuite信息,決定了密鑰交換方式(例如RSA或者DH),因此在Server Key Exchange消息中便會包含完成密鑰交換所需的一系列參數。
因為這里是DH算法,所以需要發送服務器使用的DH參數。RSA算法不需要這一步。
在Diffie-Hellman中,客戶端無法自行計算預主密鑰; 雙方都有助於計算它,因此客戶端需要從服務器獲取Diffie-Hellman公鑰。
由上圖可知,此時密鑰交換也由簽名保護。
Certificate Request(可選)——可以是單向的身份認證,也可以雙向認證
這一步是可選的,如果在對安全性要求高的常見可能用到。服務器用來驗證客戶端。服務器端發出Certificate Request消息,要求客戶端發他自己的證書過來進行驗證。該消息中包含服務器端支持的證書類型(RSA、DSA、ECDSA等)和服務器端所信任的所有證書發行機構的CA列表,客戶端會用這些信息來篩選證書。
Server Hello Done
該消息表示服務器已經將所有信息發送完畢,接下來等待客戶端的消息。
SSL建立第三階段:
客戶端收到服務器發送的一系列消息並解析后,將本端相應的消息發送給服務器。
客戶機啟動SSL握手第3階段,是本階段所有消息的唯一發送方,服務器是所有消息的唯一接收方。該階段分為3步:
- 證書(可選):為了對服務器證明自身,客戶要發送一個證書信息,這是可選的,在IIS中可以配置強制客戶端證書認證。
- 客戶機密鑰交換(Pre-master-secret):這里客戶端將預備主密鑰發送給服務端,注意這里會使用服務端的公鑰進行加密。
- 證書驗證(可選),對預備秘密和隨機數進行簽名,證明擁有(a)證書的公鑰。
Certificate(可選)
如果在第二階段服務器端要求發送客戶端證書,客戶端便會在該階段將自己的證書發送過去。服務器端在之前發送的Certificate Request消息中包含了服務器端所支持的證書類型和CA列表,因此客戶端會在自己的證書中選擇滿足這兩個條件的第一個證書發送過去。若客戶端沒有證書,則發送一個no_certificate警告。
Client Key exchange
根據之前從服務器端收到的隨機數,按照不同的密鑰交換算法,算出一個pre-master,發送給服務器,服務器端收到pre-master算出main master。而客戶端當然也能自己通過pre-master算出main master。如此以來雙方就算出了對稱密鑰。
如果是RSA算法,會生成一個48字節的隨機數,然后用server的公鑰加密后再放入報文中。如果是DH算法,這是發送的就是客戶端的DH參數,之后服務器和客戶端根據DH算法,各自計算出相同的pre-master secret.
本消息在給服務器發送的過程中,使用了服務器的公鑰加密。服務器用自己的私鑰解密后才能得到pre-master key.(向服務器證明自己的確持有客戶端證書私鑰。)
Certificate verify(可選)
只有在客戶端發送了自己證書到服務器端,這個消息才需要發送。其中包含一個簽名,對從第一條消息以來的所有握手消息的HMAC值(用master_secret)進行簽名。
SSL建立第四階段:
完成握手協議,建立SSL連接。
客戶機啟動SSL握手第4階段,使服務器結束。該階段分為4步,前2個消息來自客戶機,后2個消息來自服務器。
建立起一個安全的連接,客戶端發送一個Change Cipher Spec消息,並且把協商得到的CipherSuite拷貝到當前連接的狀態之中。然后,客戶端用新的算法、密鑰參數發送一個Finished消息,這條消息可以檢查密鑰交換和認證過程是否已經成功。其中包括一個校驗值,對客戶端整個握手過程的消息進行校驗。服務器同樣發送Change Cipher Spec消息和Finished消息。握手過程完成,客戶端和服務器可以交換應用層數據進行通信。
ChangeCipherSpec :
編碼改變通知,表示隨后的信息都將用雙方商定的加密方法和密鑰發送(ChangeCipherSpec是一個獨立的協議,體現在數據包中就是一個字節的數據,用於告知服務端,客戶端已經切換到之前協商好的加密套件(Cipher Suite)的狀態,准備使用之前協商好的加密套件加密數據並傳輸了)。
是一條事件消息。
Clinet Finished:
客戶端握手結束通知, 表示客戶端的握手階段已經結束。這一項同時也是前面發送的所有內容的hash值,用來供服務器校驗(使用HMAC算法計算收到和發送的所有握手消息的摘要,然后通過RFC5246中定義的一個偽函數PRF計算出結果,加密后發送。此數據是為了在正式傳輸應用數據之前對剛剛握手建立起來的加解密通道進行驗證。)
Server Finished:
服務端握手結束通知。
- 使用私鑰解密加密的Pre-master數據,基於之前(Client Hello 和 Server Hello)交換的兩個明文隨機數 random_C 和 random_S,計算得到協商密鑰:enc_key=Fuc(random_C, random_S, Pre-Master);
- 計算之前所有接收信息的 hash 值,然后解密客戶端發送的 encrypted_handshake_message,驗證數據和密鑰正確性;
- 發送一個 ChangeCipherSpec(告知客戶端已經切換到協商過的加密套件狀態,准備使用加密套件和 Session Secret加密數據了)
- 服務端也會使用 Session Secret 加密一段 Finish 消息發送給客戶端,以驗證之前通過握手建立起來的加解密通道是否成功。
根據之前的握手信息,如果客戶端和服務端都能對Finish信息進行正常加解密且消息正確的被驗證,則說明握手通道已經建立成功,接下來,雙方可以使用上面產生的Session Secret對數據進行加密傳輸了。
消息驗證代碼(HMAC)和TLS數據完整性:
當服務器或客戶端使用主密鑰加密數據時,它還會計算明文數據的校驗和(哈希值),這個校驗和稱為消息驗證代碼(MAC)。然后在發送之前將MAC包含在加密數據中。密鑰用於從數據中生成MAC,以確保傳輸過程中攻擊者無法從數據中生成相同的MAC,故而MAC被稱為HMAC(哈希消息認證碼)。另一方面,在接收到消息時,解密器將MAC與明文分開,然后用它的密鑰計算明文的校驗和,並將其與接收到的MAC進行比較,如果匹配,那我們就可以得出結論:數據在傳輸過程中沒有被篡改。
幾個重要的secret key:
PreMaster secret
PreMaster Secret是在客戶端使用RSA或者Diffie-Hellman等加密算法生成的。它將用來跟服務端和客戶端在Hello階段產生的隨機數結合在一起生成 Master Secret。PreMaster secret前兩個字節是TLS的版本號,這是一個比較重要的用來核對握手數據的版本號。服務端需要對密文中解密出來對的PreMaster版本號跟之前Client Hello階段的版本號進行對比,如果版本號變低,則說明被串改,則立即停止發送任何消息。
Master secret
由於最后通過交換,客戶端和服務端都會有Pre-master和隨機數,這個隨機數將作為后面產生Master secret的種子,結合PreMaster secret,客戶端和服務端將計算出同樣的Master secret。
為了保證信息的完整性和機密性,SSL需要有六個加密密鑰:四個密鑰和兩個IV。為了信息的可信性,客戶端需要一個密鑰(HMAC),為了加密要有一個密鑰,為了分組加密要一個IV,服務器也是如此。SSL需要的密鑰是單向的,不同於那些在其他方向的密鑰。如果在一個方向上有攻擊,這種攻擊在其他方向是沒影響的。生成過程如下:
主密鑰是由一系列的Hash值組成。
1
2> master_secret = PRF(pre_master_secret,“master secret”,ClientHello.random + ServerHello.random)[0..47];
>
根據要求,有4個密鑰用於加密和驗證每個消息的完整性,他們是:
- 客戶端寫入加密密鑰:客戶端用來加密數據,服務器用來解密數據。
- 服務器寫入加密密鑰:服務器用來加密數據,客戶端用來解密數據。
- 客戶端寫入MAC密鑰:客戶端用來創建MAC,服務器用來驗證MAC。
- 服務器寫入MAC密鑰:服務器用來創建MAC,客戶端用來驗證MAC。
SSL會話恢復:
會話恢復是指只要客戶端和服務器已經通信過一次,它們就可以通過會話恢復的方式來跳過整個握手階段二直接進行數據傳輸。
SSL采用會話恢復的方式來減少SSL握手過程中造成的巨大開銷。
為了加快建立握手的速度,減少協議帶來的性能降低和資源消耗(具體分析在后文),TLS 協議有兩類會話緩存機制:
- 會話標識 session ID: 由服務器端支持,協議中的標准字段,因此基本所有服務器都支持,服務器端保存會話ID以及協商的通信信息,Nginx 中1M 內存約可以保存4000個 session ID 機器相關信息,占用服務器資源較多;
- 會話記錄 session ticket :t需要服務器和客戶端都支持,屬於一個擴展字段,支持范圍約60%(無可靠統計與來源),將協商的通信信息加密之后發送給客戶端保存,密鑰只有服務器知道,占用服務器資源很少。
- 二者對比,主要是保存協商信息的位置與方式不同,類似與 http 中的 session 與 cookie。二者都存在的情況下,(nginx 實現)優先使用 session_ticket。
會話恢復具體過程(Session ID機制):
- 如果客戶端和服務器之間曾經建立了連接,服務器會在握手成功后返回 session ID,並保存對應的通信參數在服務器中;
- 如果客戶端再次需要和該服務器建立連接,則在 client_hello 中 session ID 中攜帶記錄的信息,發送給服務器;
- 服務器根據收到的 session ID 檢索緩存記錄,如果沒有檢索到貨緩存過期,則按照正常的握手過程進行;
- 如果檢索到對應的緩存記錄,則返回 change_cipher_spec 與 encrypted_handshake_message 信息,兩個信息作用類似,encrypted_handshake_message 是到當前的通信參數與 master_secret的hash 值;
- 如果客戶端能夠驗證通過服務器加密數據,則客戶端同樣發送 change_cipher_spec 與 encrypted_handshake_message 信息;
- 服務器驗證數據通過,則握手建立成功,開始進行正常的加密數據通信。
會話恢復具體過程( session ticket):
- 如果客戶端和服務器之間曾經建立了連接,服務器會在 new_session_ticket 數據中攜帶加密的 session_ticket 信息,客戶端保存;
- 如果客戶端再次需要和該服務器建立連接,則在 client_hello 中擴展字段 session_ticket 中攜帶加密信息,一起發送給服務器;
- 服務器解密 sesssion_ticket 數據,如果能夠解密失敗,則按照正常的握手過程進行;
- 如果解密成功,則返回 change_cipher_spec 與 encrypted_handshake_message 信息,兩個信息作用與 session ID 中類似;
- 如果客戶端能夠驗證通過服務器加密數據,則客戶端同樣發送 change_cipher_spec與encrypted_handshake_message 信息;
- 服務器驗證數據通過,則握手建立成功,開始進行正常的加密數據通信。
SSL記錄協議:
SSL記錄協議主要用來實現對數據塊的分塊、加密解密、壓縮與解壓縮、完整性檢查及封裝各種高層協議。
每個SSL記錄主要包含以下信息:
- 內容類型
- 協議版本號,目前有2.0和3.0版本
- 記錄數據的長度
- 數據由載荷
- 散列算法計算消息認證代碼
- 將消息分割為多個片段;
- 對每個片段進行壓縮
- 加上片段編號(防止重放攻擊)計算消息驗證碼MAC值(保證數據完整性),追加在壓縮片段
- 對稱密碼加密;
- 加上數據類型、版本號、壓縮后的長度組成的報頭, 就是最終的報文數據;
應用數據傳輸:
在所有的握手階段都完成之后,就可以開始傳送應用數據了。應用數據在傳輸之前,首先要附加上MAC secret,然后再對這個數據包使用write encryption key進行加密。在服務端收到密文之后,使用Client write encryption key進行解密,客戶端收到服務端的數據之后使用Server write encryption key進行解密,然后使用各自的write MAC key對數據的完整性包括是否被串改進行驗證。
首先明確一個概念:非對稱加密算法
非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那么只有用對應的公開密鑰才能解密。
HTTPS協議中,前面的握手過程,服務器會將公鑰發給客戶端,客戶端驗證后生成一個密鑰用公鑰加密后發送給服務器,成功后建立通信。
通信過程客戶端將請求數據用得到的公鑰加密后,發給服務器,服務器用私鑰解密。服務器用客戶端給的密鑰加密響應報文,發回給客戶端,客戶端用自己存的密鑰解密。
忽略掉其他例如確定協議和版本號之類的環節,提煉出來的重要環節如下:
公私玥A用於非對稱式加密,密鑰B只用於普通的對稱式加密。
簡而言之就是這樣,那么問題來了:你作為一個中間人,你沒有服務器私鑰A,是不能解密客戶端發送的內容的,如果你沒有客戶端自己生成的密鑰B,所以你也不能解密客戶端發過去的內容的。
請注意:這兩個私鑰都是兩端各自保存,而私鑰A是只保存在服務器上,從不對外發送的。
結果就是,你收發的數據,他都能看到——————但是他不能解密,看不懂。
這只是最普通的劫持HTTP的方式,HTTPS就是為了解決題主所說的這個中間人攻擊而產生的,然而題主並沒有去理解HTTPS的工作原理,而用HTTP的原始思路繼續去思考HTTPS,所以題主這個方法是完全不可行的。
繼續往下想,或許有人會覺得:
如果你自己簽發一對非對稱式公私鑰C,還有密鑰D,然后作為一個中間人。在一開始的通信環節,用公私鑰C替代公私鑰A,用密鑰D替代密鑰B。這樣分發給對應的服務器和客戶端,這樣他們發給自己的信息,自己都能解密。然后自己再用真正的公鑰A把解密后的信息重新加密發給服務器騙取響應報文,把響應報文用密鑰B(前面客戶端用公鑰C加密后,被中間人用私鑰C解密的刀)重新加密發回給客戶端騙取新的請求報文。
這樣豈不是可以瞞天過海?
那么在圖中所示的驗證環節,因為你的證書是自己簽發的,所以證書跟指紋拿去去系統里可信頒發機構的證書那一對,肯定對不上。
例如我用Fiddler給自己簽發了個證書,因為頒發者不在系統受信任證書頒發機構里,會直接報警:
如果你要假冒其他機構頒發證書,因為你沒有頒發機構的密鑰,那么你頒發的證書,結果指紋肯定沒辦法對上,還是一樣會報警。
系統信任的頒發機構一般都是權威的大機構,當然你也可以自己導入自己信任的機構的證書,用來驗證簽名。如果要實現HTTPS下的中間人攻擊,你應該讓自己的根證書進入系統里,讓自己成為裁判。
這是HTTPS中間人攻擊中最難也是最簡單的一點——畢竟用戶很好騙。
你可以這么做,或者跟上一張圖證書中的第三第四行所示的那么做。
還有人就說了,我可以讓用戶回落到HTTP協議啊,中間人用HTTPS跟服務器通信,然后用HTTP跟客戶端通信——要知道大部分用戶在地址欄輸入URL時,並沒有指定協議的習慣,都是打www開頭而不是打https://開頭,能用HTTPS全是Web Server上80端口301 Location到HTTPS的功勞。
看起來似乎中間人充當了一個替換頁面里HTTPS資源到HTTP的反向代理,好像可行性還是很高。
但是只要利用HSTS(HTTP Strict Transport Security,RFC6797)就可以解決這個問題。通過在HTTP Header中加入Strict-Transport-Security的聲明,告訴瀏覽器在一定時間內必須通過HTTPS協議訪問本域名下的資源。
這種情況下,只要用戶曾經在安全網絡環境下訪問過一次某站,中間人在指定時間內也無法讓其回落到HTTP。
原文地址:https://www.zhihu.com/question/22795329