HTTPS从认识到线上实战全记录
https://www.cnblogs.com/liuxianan/p/https.html
前言
關于HTTPS,基本上你想知道的都在這里了(當然僅限入門)。本文原標題《HTTPS原理與實踐》,下圖是本文配套PPT的目錄截圖:
[TOC]
原理篇
2.1.?認識HTTPS
先說一下,本文可能有些地方由于描述不到位或者我本人理解錯誤而出現不準確內容,有錯誤歡迎指正!
2.1.1.?什么是HTTPS
HTTPS全稱Hyper Text Transfer Protocol over Secure Socket Layer,直譯過來就是通過SSL實現的超文本傳輸協議,簡單來講就是加密版的HTTP協議,也就是HTTP+SSL/TLS。
為什么需要加密版的HTTP呢,因為我們都知道,HTTP是明文傳輸的,因此使用HTTP協議傳輸隱私信息非常不安全,很容易在傳輸過程中被竊取,或者通信內容被人篡改冒充,使用HTTPS可以避免這些問題。
2.1.2.?SSL/TLS
為了解決HTTP明文傳輸的風險性,網景公司設計了SSL(Secure Sockets Layer)協議用于對HTTP協議傳輸的數據進行加密,從而就誕生了HTTPS。SSL目前的版本是3.0,被IETF(Internet Engineering Task Force)定義在RFC 6101中,之后IETF對SSL 3.0進行了升級,于是出現了TLS(Transport Layer Security) 1.0,定義在RFC 2246。實際上我們現在的HTTPS都是用的TLS協議,但是由于SSL出現的時間比較早,并且依舊被現在瀏覽器所支持,因此SSL依然是HTTPS的代名詞。
上面一大段話是轉載的,簡單而言就是TLS是SSL的升級版,現在瀏覽器一般用的都是TLS。
2.1.3.?HTTPS的優點
從底層分析HTTPS有以下3大優點:
從實際出發來看,HTTPS主要有以下優點:
下面單獨對3和4說一下。
運營商HTTP劫持我們都知道,經常莫名奇妙的在自己網站上看到各種惡意的惡心廣告,查看代碼發現被注入了一些奇奇怪怪的js,這其實就是HTTP劫持,啟用了HTTPS之后,我們傳輸的內容都是加密的,運營商想篡改內容都沒轍。
為什么HTTPS能夠有效的解決DNS劫持呢?在域名被劫持的情況下,客戶端訪問的實際上是攻擊者的IP,客戶端通過這個IP找到攻擊者的服務器,要求建立HTTPS通信,因為攻擊者沒有真實服務器的證書和私鑰(想要申請這個域名的證書必須驗證自己是這個域名的所有者,攻擊者做不到這一點),把偽造或自簽名的證書提供給客戶端,是得不到瀏覽器的認可的,瀏覽器會彈出不安全的警告。但是用戶執意要訪問我們也沒辦法,所以才用了有效解決而不是徹底解決這一詞。
另外,就近看的話,越來越多的場合強制要求https(比如ios、微信小程序等等都要求https),從長遠看,升級HTTPS是大勢所趨,一次升級,永久受益。
2.1.4.?HTTPS的缺點
- 服務器性能下降,開啟HTTPS會增加內存、CPU、網絡帶寬的開銷,特別是非對稱加密這一塊;
- 訪問速度下降,HTTP連接的建立需要3次握手,HTTPS還需要加上ssl的幾次握手(具體是幾次沒去考究,有說是9次),當然下降主要是在第一次建立連接的時候,后面正常通信速度一般沒啥變化;
- 除了握手部分外,所有信息傳輸之后瀏覽器和服務器都要進行加密解密,又是一筆額外的開銷;
- 申請證書需要一筆花費,當然現在免費證書也很容易申請到,這個不算明顯缺點;
一句話概括就是:性能和速度下降,但是具體下降多少呢,這個不太好講,可以延伸閱讀:HTTPS 要比 HTTP 多用多少服務器資源?
2.1.5.?HTTPS原理
HTTPS主要分為單向認證和雙向認證,99%的場景都只需要單向認證,雙向認證我們后面再來講。
2.1.5.1.?小明和小紅的故事
在介紹HTTPS原理之前,我們先來假設,假如讓我們自己設計一套加密方案該如何實現呢?為了更好理解,我們用人來舉個栗子:
小明(客戶端)暗戀小紅(服務端),想給小紅寫信,但是又怕信在郵遞的過程中被人偷看,所以他把信裝在一個盒子里鎖起來,信雖然是安全了,但是小紅就算收到了打不開啊,把鑰匙給小紅寄過去?萬一鑰匙也被人偷去了怎么辦?
就在這時,小紅想到了一個辦法:小紅把一個沒有上鎖的盒子寄給小明(鑰匙在小紅這),小明把鑰匙放進去再鎖上(小明可以鎖盒子,但是一旦鎖上了就連自己都打不開了),然后把這個裝有鑰匙的盒子寄回給小紅,因為小紅有鑰匙,所以能打開盒子拿到里面的鎖信件盒子的鑰匙,再然后就能看到小明給她寫的信了。同時,小紅想回信的話,也可以把信裝在這個盒子里寄回去,因為這是小明的盒子,他自己肯定還有一把鎖,所以他也能打開,從此,小明和小紅就可以任意的寫信私通而不用擔心其他人能看到了!
但是,如何保證小紅寄送過來的未上鎖盒子不被別人調包呢?這個等到我們介紹完HTTPS原理之后我們再回過頭來看這個問題。
2.1.5.2.?單向認證
下面這張圖是網上比較常見的一張圖:
這個應該算是精簡版,省略了一些細節,但是對于理解https的核心原理部分足夠了。下面這張圖可能更全面(圖片來源于這里,感謝作者)
具體過程如下:
至于為什么會有三個隨機數來生成最終的對稱加密密鑰,主要是為了進一步增大密鑰的隨機性,這里有一段不錯的解釋:
不管是客戶端還是服務器,都需要隨機數,這樣生成的密鑰才不會每次都一樣。由于SSL協議中證書是靜態的,因此十分有必要引入一種隨機因素來保證協商出來的密鑰的隨機性。
對于RSA密鑰交換算法來說,pre-master-key本身就是一個隨機數,再加上hello消息中的隨機,三個隨機數通過一個密鑰導出器最終導出一個對稱密鑰。
pre master的存在在于SSL協議不信任每個主機都能產生完全隨機的隨機數,如果隨機數不隨機,那么pre master secret就有可能被猜出來,那么僅適用pre master secret作為密鑰就不合適了,因此必須引入新的隨機因素,那么客戶端和服務器加上pre master secret三個隨機數一同生成的密鑰就不容易被猜出了,一個偽隨機可能完全不隨機,可是是三個偽隨機就十分接近隨機了,每增加一個自由度,隨機性增加的可不是一。
需要特別注意的是,以上握手階段全部用的是HTTP協議明文傳輸的。
2.1.5.3.?回到小明和小紅的故事
介紹完HTTPS原理之后,我們再來回到小明和小紅的故事來加深理解。看起來讓小紅寄未上鎖盒子的方案很完美,但是,假如小紅寄過來的盒子被人調包了呢?調包的話打開情書的鑰匙就被別人拿走了。所以這時候需要有一家在江湖上比較有威望的鏢局(假設叫龍門鏢局)來幫忙押送小紅的盒子,當小明收到盒子時,如果是鏢局親自送過來的、并且說是小紅寄的盒子,那么小明就認為這是小紅的盒子(小明很信任這家鏢局),前面我們說了,這家鏢局在江湖上很有威望,為了自己的聲譽它必須保證每一趟鏢都沒問題。有人又會問了,干嘛不直接讓鏢局把信送過去呢?因為小明寫信不可能只寫一封,而且每封情書都讓鏢局來押送成本太大,而且鏢局比郵局流程更繁瑣,更費時間,如果小明收到一個沒聽過的鏢局送過來的聲稱是小紅寄的盒子,那么他不會相信。
上面例子中,小明是瀏覽器,小紅是服務器,鏢局是頒發證書的CA(后面會提到),沒聽過的鏢局就是不受信任的根證書,鏢就是證書,信被別人看了叫HTTP明文泄露,信被別人改了叫HTTP劫持,信上的地址被人改了叫DNS劫持,小明寄給小紅的盒子是對稱加密(因為雙方都有鑰匙,都能打開),小紅寄給小明的沒鎖的盒子可以看做是非對稱加密(因為所有人都可以拿它加密東西,但是一旦加密了就打不開,只有小紅一個人有鑰匙),鏢局自己干壞事自毀前程就等同于沃通的故事,等等。
2.1.5.4.?雙向認證
雙向認證和單向認證原理基本差不多,主要區別是除了客戶端需要認證服務端以外,服務端對客戶端也需要認證。什么場景下需要驗證客戶端呢?比如一些銀行業務,銀行會要求客戶必須在電腦上插入它們簽發的U盾之類的東西,或者安裝什么控件,這里就類似客戶端證書的概念,沒有這個證書的人無法使用銀行提供的業務。
雙向認證我沒有去親自嘗試,可以參考這篇文章。
下面還是上面那位網友畫的雙向認證圖,我沒有仔細考究,先貼在這里:
2.1.6.?引申思考
2.1.6.1.?如何保證公鑰不被篡改
將公鑰放在數字證書中。只要證書是可信的,公鑰就是可信的。
那如何保證證書可信呢?證書的生成都是由國際頂級認證機構簽發的,簽發的時候必須驗證你是不是這個域名的所有者,只有是才給你簽發證書(證書和域名一一掛鉤),所以理論上其他人無法偽造你的證書(只是理論上),即使偽造了,瀏覽器在加載的時候會進行域名校驗,如果證書中的域名和實際域名不匹配,瀏覽器是會警告的。
問題又來了,瀏覽器怎么知道你的證書是不是合法的國際頂級認證機構簽發的呢?操作系統和瀏覽器都內置了一些他們認為可信任的國際頂級認證機構(CA,后面會提到),只有他們簽發的證書瀏覽器才信任。
2.1.6.2.?為何正式傳輸時使用對稱加密
因為非對稱加密很慢,而且傳輸普通內容時雙方都已經拿到了隨機又沒有其他人知道的密碼,所以普通的對稱加密足矣。
2.2.?CA
2.2.1.?何為CA
CA(Certificate Authority),即證書認證機構,它的作用就是提供證書(即服務器證書,由域名、公司信息、序列號和簽名信息組成)加強服務端和客戶端之間信息交互的安全性,以及證書運維相關服務。任何個體/組織都可以扮演 CA 的角色,難的是你要能得到全世界各大操作系統、瀏覽器等的默認信任,能得到他們的默認信任,你也可以自己開一家CA公司了,這類證書通常叫做根證書。瀏覽器默認信任的 CA 大廠商有很多,比如?Symantec賽門鐵克、Comodo、Godaddy、GolbalSign(百度微博等都是它簽發的) 和?Digicert。
如何查看操作系統內置了哪些CA呢?Internet選項->內容->證書->受信任的根證書頒發機構:
想讓你的https網站默認情況下就被全世界瀏覽器信任你必須使用它們簽發的證書,大部分都是要錢的,當然也有免費的。
很多人一開始應該有和我一樣的疑問,我升級我的https,憑啥要到別人那里花錢買證書(即使有免費的也不爽)?,看到這里我想不用再多解釋你應該懂了。
2.2.2.?CA如果作惡怎么辦
CA必須是絕對公平公正不作惡的,否則一旦暴露出來一些丑聞,立即會被各大瀏覽器和廠商拉入黑名單不再信任,或者各種降級處理,帶來的后果甚至可能是殺身之禍,比如被360收購的沃通的下場:谷歌宣布開始全面封殺使用沃通CA證書網站,信譽破產的惡果。
沃通的主要罪狀有五個:
沃通為何要偽造簽署日期呢?
由于如今的運算能力越來越強,SHA1 散列算法的可靠性越來越不夠了。一些主流的瀏覽器,如果發現2016元旦之后簽署的 CA 證書,依然采用 SHA1,會給出警告。沃通為了幫證書申請人規避瀏覽器警告,故意把簽署日期偽造成2015年底。
2.2.3.?頂級證書私鑰泄露怎么辦
如果頂級證書的私鑰泄露,那么帶來的后果是災難性的,只能各大瀏覽器和操作系統通過更新補丁的方式來吊銷泄密的根證書,泄露之后一般這家CA公司離倒閉不遠了,也不是沒有這樣的例子:
荷蘭CA供應商DigiNotar因為黑客入侵事件而成為萬眾矚目的焦點,它發行的證書被眾多瀏覽器開發商和操作系統開發商宣布為不受信任?,F在,這家失去信任的CA宣告破產。疑似伊朗黑客在7月中旬入侵了DigiNotar服務器,發行了531個偽造證書,包括了Google、微軟、雅虎、Twitter、Facebook、中情局、軍情六處和摩薩德等。DigiNotar在7月19日發現了入侵,但直到8月份外界才知道入侵事件。DigiNotar的母公司VASCO承認損失慘重。
2.3.?SSL證書
2.3.1.?證書的種類
SSL 證書按大類一般可分為DV SSL?、OV SSL、EV SSL證書,又叫域名型、企業型、增強型證書:
- DV SSL(Domain Validation),域名型SSL證書,證書頒布機構只對域名的所有者進行在線檢查,只要你能證明你是這個域名的所有者就可以給你頒發證書,不會校驗網站的資質,哪怕你是個黃賭毒網站也可以,個人網站、非盈利項目、開源項目等用域名型證書足矣;
- OV SSL(Organization Validation),企業型SSL證書,需要購買者提交組織機構資料和單位授權信等在官方注冊的憑證,證書頒發機構在簽發 SSL 證書前不僅僅要檢驗域名所有權,還必須對這些資料的真實合法性進行多方查驗,只有通過驗證的才能頒發 SSL 證書;
- EV SSL(Extended Validation),增強型SSL證書(EV SSL),驗證流程更加具體詳細,驗證步驟更多,這樣一來證書所綁定的網站就更加的可靠、可信。它跟普通SSL證書的區別是瀏覽器的地址欄變綠,如果是不受信的 SSL 證書則拒絕顯示,如果是釣魚網站,地址欄則會變成紅色,以警示用戶。
不論是 DV、OV 還是 EV 證書,其加密效果都是一樣的,個人網站用DV證書、企業用OV足夠了。
如何查看證書類型?如下圖,百度是OV,github是EV(其實好像并沒有統一的區分方法,有的證書不會寫):
2.3.2.?證書的格式
一般來說,主流的 Web 服務軟件,通常都基于 OpenSSL 和 Java 兩種基礎密碼庫。
- Tomcat、Weblogic、JBoss等Web服務軟件,一般使用JDK自帶的Keytool工具,生成Java Keystore(JKS)格式的證書文件。
- Apache、Nginx等Web服務軟件,一般使用OpenSSL工具提供的密碼庫,生成?.key、.crt等格式的證書文件。
- IBM 的 Web 服務產品,如 Websphere、IBM Http Server(IHS)等,一般使用 IBM 產品自帶的 iKeyman 工具,生成 KDB 格式的證書文件。
- 微軟的IIS使用Windows自帶的證書庫生成pfx格式的證書文件。
詳見下圖:
每種格式之間都可以相互轉換,轉換方法可以參考阿里云給出的幫助文檔,在騰訊云申請證書的時候會自動幫你生成4種服務器各自需要的格式,非常方便。
2.3.3.?證書的收費與免費
不是說收費的證書就一定比免費證書好,只不過現階段各CA機構為了自己的盈利目的,免費證書一般都有一些限制,比如只支持單域名,子域名太多的話需要挨個申請。
實踐篇
本文全部以nginx配置為例,其它Web服務器配置請自行google,或者參考這篇不錯的文章:SSL證書安裝指引。
3.1.?第一步,生成證書
首先我們需要得到一張證書,可以申請免費的,也可以自制,本地測試時一般自制證書。
3.1.1.?申請免費證書
免費證書一般有下面幾種:
- Let's Encrypt:獲得Mozilla、微軟等主要瀏覽器廠商的根授信,出現的目的就是為了推廣HTTPS,缺點是只有3個月有效期,過期需續簽;
- TrustAsia亞洲誠信;
- StartSSL免費DV證書:因丑聞被主流瀏覽器封殺,一般不建議;
- Wosign(沃通)免費DV證書:同上,被各大瀏覽器封殺,基本可以無視了;
我們一般不需要自己直接和它們打交道,國內的云服務提供商一般都有免費的證書申請,這里操作會更簡單一點。
先聲明一下,這里不是打廣告,如果有更好用的,歡迎大家推薦。阿里云之前有一款免費的SSL證書申請,但是現在好像下線了,騰訊云有一款TrustAsia的免費證書,又拍云說是有2款免費證書,而且可以自動續簽,但是試了一下發現必須把域名綁定到它們的CNAME才行,所以想想還是放棄了:
最后我用的是騰訊云免費SSL證書,有一款TrustAsia的免費證書,缺點是有效期只有1年(到期應該可以重新申請),且不支持泛域名,如果子域名很多的話比如挨個申請,很麻煩,大家有更好用的歡迎推薦:
申請很簡單,簡單填寫資料,然后驗證域名身份,快的話2-3分鐘內就能成功申請到:
成功后可以把證書下載到本地,內置了Apache、IIS、Nginx、Tomcat的4種證書格式,很方便。
申請到的證書:
3.1.2.?自制證書
雖然有很多途徑可以申請到免費的證書,但一般都是單域名(不支持泛域名),限制太多,本地調試極不方便,所以我們希望本地開發時能夠使用我們自己簽發的證書。下面我們就來自己實踐一下如何從頭開始自制HTTPS證書。
證書一般都是用openssl來生成,當然也可以用jdk自帶的keytool來生成,但是最終還是要用openssl來轉換格式,所以一般還是推薦用openssl來生成。
3.1.2.1.?安裝openssl
首先當然還是安裝openssl,這里我們只介紹Windows平臺,Linux系統的請參考這里,點擊這里下載Win64位的安裝包:
安裝很簡單,安裝完畢之后為了使用方便,建議配置一下環境變量:
然后就可以隨時隨地執行openssl命令了。
3.1.2.2.?生成CA根證書
我們先生成一個自己的CA根證書ca.crt,然后再用這個根證書生成服務端證書server.crt,有人會問,為啥不直接生成服務端證書呢?因為這樣做的話將來我們只要導入一個CA根證書,其它所有用它生成的證書都默認是可信任的,方便嘛!
好了,說了這么多廢話,下面開始了:
# 生成CA私鑰 openssl genrsa -out ca.key 1024 # 生成CA根證書,-day指定證書有效期 openssl req -new -x509 -key ca.key -out ca.crt -days 365就這么簡單,第二步需要輸入幾個東西,雖然說亂填也可以,但建議按照提示來填,其中Common Name需要特別注意,如果是生成CA證書的話,可以輸入諸如My CA之類的,如果是生成服務端證書的話,必須輸入網站的域名,可以輸入泛域名,如*.haoji.me:
另外,如果報了unable to write 'random state'的錯誤,一般都是因為沒有使用管理員權限打開命令行窗口。
3.1.2.3.?生成服務端證書
和CA證書的生成不同的時,我們需要先生成一個csr證書請求文件文件(CSR,Cerificate Signing Request),有了這個文件之后再利用CA根證書生成最終的證書:
# 生成服務端私鑰 openssl genrsa -out server.key 1024 # 生成證書請求文件 openssl req -new -key server.key -out server.csr # 生成最終證書文件,-day指定證書有效期 openssl x509 -req -days 365 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt操作截圖:
但!是!各位看官先別急著去實踐,以上證書我在Chrome55下測試沒問題,但是Chrome61下測試提示Subject Alternative Name missing錯誤:
The certificate for this site does not contain a Subject Alternative Name extension containing a domain name or IP address.提示必須指定DNS Name或者IP地址,而指定這個必須要用v3的證書。生成v3證書只需要比上面多加2個參數-extfile openssl.cnf -extensions v3_req,但是多了一個額外的配置文件,這個文件里面可以填很多東西(完整配置文件參考這里),我們這里僅僅需要指定subjectAltName即可。
先準備一個名為openssl.cnf的文件,內容如下:
[v3_req] subjectAltName = @alt_names[alt_names] DNS.1 = localhost.com DNS.2 = www.localhost.com DNS.3 = www.test123.com #IP.1 = 127.0.0.1解釋一下,這里的alt_names指的是最終可以訪問的域名或者IP,所以,其實一個證書是可以多個網站同時使用的。被訪問域名只要滿足DNS和IP中的一個,其證書就是合法的。
然后再來重新生成證書,為了對大家產生誤導,我們再來一遍完整的過程:
# 生成服務端私鑰 openssl genrsa -out server.key 1024 # 生成證書請求文件 openssl req -new -key server.key -out server.csr # 生成最終證書文件,-day指定證書有效期 openssl x509 -req -days 365 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -extfile openssl.cnf -extensions v3_req -in server.csr -out server.crt雙擊生成的證書可以看到如下內容:
3.1.2.4.?生成客戶端證書
如果需要實現HTTPS雙向認證,還要按照上述服務端一模一樣的操作再生成一個client.crt和client.key,這里我們就不重述了,90%的場景都是不需要雙向認證的。
3.1.2.5.?導入證書
上述步驟執行完之后生成了如下文件:
我們只需要雙擊ca.crt導入這個自制根證書即可,以后只要是利用這個證書生成證書瀏覽器都會認為是可信任的,這讓我想起了12306干的勾當,如果你能把你這個根證書推廣到全世界的電腦和手機,那么你也可以成立一家CA公司專門賣證書了,哈哈。
導入的時候注意證書存儲位置:
由于這是很敏感的操作,所以操作系統一定會有警告:
3.1.3.?引申話題:12306為啥不申請證書
這個標題在大約在半個月前還是正確的,但是,就在大約半個月前,12306終于買證書了!!!倔強的12306堅持了這么多年推廣自己的證書,終于還是妥協了:
我們還是回到12306沒買證書以前。我們先回憶一下12306的做法,首頁不是https,它在首頁明顯位置放置了一個證書下載鏈接讓我們去下載,真正的購票頁面才開啟了https,沒安裝這個證書瀏覽器就會各種警告。
有很多人都在網上問,12306為啥沒買證書呢?是不舍得花這個錢嗎?當然不是,堂堂鐵老大再怎么虧損多少個億,這點錢還是出得起的,12306無非就是想利用自己絕對壟斷地位推廣自己的SRCA證書而已(12306有一個中鐵數字證書認證中心),至于推廣證書有什么用,這不用我多說吧。
摘抄一段網友的話:
合法證書對于SSL加密通信和通信完整性保護的意義就是合格鑰匙之于鎖的關系,你把山寨CA請到你家瀏覽器的受信任CA列表,就相當于你從大馬路上撿把插著萬能鑰匙的鎖回家裝大門上。門上確實有鎖,沒鑰匙確實進不來你家偷窺(機密性保護)和盜竊(完整性保護),但有萬能鑰匙的人呢?
3.2.?第二步,nginx的ssl模塊安裝
3.2.1.?Windows系統
Windows平臺的nginx.exe一般內置了ssl模塊,無需額外單獨安裝。
3.2.2.?Linux系統
linux系統的nginx一般都是編譯安裝的,如果你第一次安裝nginx的時候已經安裝了ssl模塊的話,這一步可以跳過,如果沒有,繼續往下看。
如何查看有沒有安裝ssl模塊呢?定位到nginx/sbin目錄執行nginx -V查看安裝時的命令,如果有--with-http_ssl_module,說明已經安裝了ssl模塊,那么你可以跳過這一步了。
這里著重要講的是已經上線運行了一段時間的nginx如果安裝新模塊,其實下面的內容在我另外一篇文章中有提到過。
3.2.2.1.?編譯安裝openssl
編譯安裝openssl要很久很久,做好心理準備。
下載openssl-1.0.2n.tar.gz文件放在/home/nginx/下面:
cd /home/nginx tar -zxvf openssl-1.0.2n.tar.gz cd openssl-1.0.2n ./config make & make install3.2.2.2.?重新編譯nginx
nginx安裝新模塊需要整體重新編譯,所以需要知道上一次安裝時的編譯命令,假設nginx安裝在/home/nginx/nginx-1.8.1下面,定位到sbin下面執行./nginx -V(注意V是大寫)后可以查看安裝時使用的命令:
[root@iZ94i7kwlagZ sbin]# ./nginx -V nginx version: nginx/1.8.1 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) built with OpenSSL 1.0.2n 7 Dec 2017 TLS SNI support enabled configure arguments: --prefix=/home/nginx/nginx-1.8.1 --with-pcre=/home/nginx/pcre-8.38 --with-zlib=/home/nginx/zlib-1.2.8 --without-http_ssi_module然后定位到源碼包去重新編譯,根據已有的命令再加上我們這次要安裝的新模塊命令,我這里是--with-openssl=/home/nginx/openssl-1.0.2n --with-http_ssl_module。注意,如果源碼包刪了,重新下載一個版本一致的nginx-1.8.1.tar.gz并解壓,為了區分,我解壓到/home/nginx/temp-nginx-1.8.1:
cd /home/nginx/temp-nginx-1.8.1 ./configure --prefix=/home/nginx/nginx-1.8.1 --with-pcre=/home/nginx/pcre-8.38 --with-zlib=/home/nginx/zlib-1.2.8 --with-openssl=/home/nginx/openssl-1.0.2n --with-http_ssl_module make切記這里僅僅需要make,不需要make install。執行完之后我們在/home/nginx/temp-nginx-1.8.1/objs/下得到了一個新的二進制文件nginx,上面所有操作都是為了得到這個文件,然后將這個文件覆蓋現有nginx文件即可(為了以防萬一,最好備份一下):
cd /home/nginx/nginx-1.8.1/sbin/ ./nginx -s stop # 先停止 cp ./nginx ./nginx.backup # 備份 cd /home/nginx/ cp temp-nginx-1.8.1/objs/nginx nginx-1.8.1/sbin/nginx # 覆蓋然后啟動nginx查看是否正常。
3.3.?第三步,nginx配置
3.3.1.?配置
假設我們有一個www.localhost.com的網站,為了方便測試,把它添加到hosts文件中去。
然后將第一步得到的證書復制到nginx/conf/crt/文件夾下(后面的crt是自己新建的文件夾),編輯nginx.conf:
http {# 省略其它配置server {listen 443; server_name www.localhost.com; ssl on; # 書寫路徑時注意,即使使用了include將conf文件寫到其它目錄,證書路徑依然是相對于nginx.conf而言的,且windows下不能以./開頭 ssl_certificate crt/server.crt; ssl_certificate_key crt/server.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # 使用的協議 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; # 配置加密套件,寫法遵循openssl標準 ssl_prefer_server_ciphers on; location / { root E:/github/test/dist/www; index index.html; } } }最主要就是中間那7行ssl開頭的配置,一般照著寫就可以了,替換一下自己的證書路徑,書寫路徑時注意,即使使用了include將conf文件寫到其它目錄,證書路徑依然是相對于nginx.conf而言的,并且Windows下不能以./開頭,否則會提示文件找不到。
運行nginx -t測試一下是否OK:
D:\GreenSoft\nginx-1.11.8>nginx -t nginx: the configuration file D:\GreenSoft\nginx-1.11.8/conf/nginx.conf syntax is ok nginx: configuration file D:\GreenSoft\nginx-1.11.8/conf/nginx.conf test is successful沒問題就重啟nginx,然后打開瀏覽器測試,一切順利的話你可能已經看到綠色的https前綴了,有木有很雞凍:
特別注意,由于我們還沒有做http自動跳轉處理,測試時一定要主動輸入https://www.localhost.com的完整域名!
3.3.2.?常見問題
3.3.2.1.?Mixed Content
https頁面出現http鏈接的資源我們稱之為Mixed Content(混合內容),不同瀏覽器對不同類型的混合內容處理方式不一樣,這里我們只講主流瀏覽器?,F代瀏覽器(Chrome、Firefox、Safari、Microsoft Edge)基本上都遵守了W3C的Mixed Content規范,將其分為Optionally-blockable和Blockable兩類:
- Optionally-blockable主要是只危險較小的圖片、視頻、音頻等資源,這類資源即使被人篡改也不會有太大的問題,瀏覽器默認會加載,展示在控制臺會打印警告信息,并且https不是綠色的。
- Blockable一般是指除了上述之外所有的被限制加載的http資源,如JS、CSS、iframe等,瀏覽器會直接禁止加載,并且控制臺打印錯誤信息。
所以網站在升級https時需要特別注意,既然要升級就最好要全站升級,不然很容易出現某些資源由于寫死了http://頭導致瀏覽器無法加載的嚴重問題。當然也不是沒有辦法解決,可以通過CSP的upgrade-insecure-requests指令讓網頁所有http資源自動指向https,限于篇幅,本文不對此展開講,讀者可自行了解CSP、HSTS等相關概念。
繼續回到正文,當頁面有http資源時,https不是綠色的:
將所有http鏈接改成https之后,綠色回來了:
3.3.2.2.?域名不匹配
我們還是用前面的例子,假如把nginx中的域名改成www.localhost2.com,同時hosts也改下,但是證書不變,然后再次打開瀏覽器訪問時提示NET::ERR_CERT_COMMON_NAME_INVALID:
所以,DV證書一定要是和域名掛鉤的,域名不匹配瀏覽器會攔截。
3.3.2.3.?根證書不受信任
假如我們前面自制的CA根證書沒有導入到操作系統(模擬時可以從Internet選項里面找到證書入口刪除之前的證書即可),然后瀏覽器會提示NET::ERR_CERT_AUTHORITY_INVALID:
3.3.2.4.?使用SHA-1簽名的證書
SHA-1在許多安全協議中廣泛使用,包括TLS和SSL、PGP、SSH、S/MIME和IPsec。早在2005年,密碼學家就證明SHA-1的破解速度比預期提高了2000倍,雖然破解仍然是極其困難和昂貴的,但隨著計算機變得越來越快和越來越廉價,SHA-1算法的安全性也逐年降低,已被密碼學家嚴重質疑。所以,各大瀏覽器相繼宣布將逐步停止對SHA-1簽名證書的支持。
所以在生成證書時一定要指定-sha256參數。
3.3.2.5.?證書刷新不及時
更換證書時最好重啟一下nginx然后多刷新2次防止未生效折騰半天;
3.4.?第四步,http自動跳轉
網站是升級https了,但是用戶又不知道,而且不輸入協議頭的話瀏覽器默認都是按照http來加載,所以我們還要對http做301自動跳轉處理。
server {listen 80;server_name www.localhost.com;location / { rewrite ^(.*) https://www.localhost.com$document_uri permanent; } }上述自動跳轉配置會自動攜帶URL和參數,例如,訪問?http://www.localhost.com/test.html?a=1?會自動跳轉到?https://www.localhost.com/test.html?a=1?。`
3.5.?第五步,網站代碼改造
這個根據實際網站的不同難易程度會有很大不同,例如,如果你是全站升級https,包括各類子域名,那么很簡單,全文搜索http,批量替換成//開頭即可。但是如果只是部分升級,比如主站升級了,子站沒升級,然后主站頁面又有各種子站的資源鏈接、跳轉等,這就麻煩了,這時候只能手動處理了。特別是針對子域名比較多的網站,免費證書又都不支持泛域名,全部升級需要一個個去生成證書,然后配置,麻煩死了。
另外,為了安全起見,剛開始的時候建議靜態資源的站點(比如圖片,很有可能外站引用了這個圖片鏈接)同時保持http和https都可以訪問,等時間成熟了再下掉或者做301重定向,否則很容易出現某個資源加載不了導致404的問題。
升級https最麻煩的可能就是這一步了,特別是對于歷史悠久的大網站,當然小網站就另當別論了。
其它
4.1.?CSP
CSP,全稱Content Security Policy,意即內容安全策略,有非常多的指令,用來實現各種各樣與頁面內容安全相關的功能,這里介紹2個比較有用的。所有CSP指令都有2種啟用方式,一種是HTTP頭部,一種是<meta>標簽。
4.1.1.?禁用http鏈接
前面說過,對于HTTPS頁面中的圖片等資源瀏覽器默認會加載,僅僅是控制臺給一個警告,因為圖片類資源被劫持通常問題不會太大,但有些頁面按鈕布局等是用圖片做的,圖片被篡改會影響用戶使用,最重要的,頁面只要有一個http的鏈接,地址欄的https就不是綠色的。
可以通過CSP的block-all-mixed-content指令讓頁面進入對Mixed Content的嚴格檢測(Strict Mixed Content Checking)模式。在這種模式下,所有非 HTTPS 資源都被禁止加載,控制臺報錯,https回歸綠色。
HTTP響應頭方式:
Content-Security-Policy: block-all-mixed-contentHTML標簽方式:
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">4.1.2.?強制http指向https
HTTP遷移HTTPS對于一些大型網站來說工作量巨大,難免有疏漏的地方,此時可以讓瀏覽器幫我們做http自動跳轉https這一步。通過upgrade-insecure-requests這個CSP指令,可以讓瀏覽器幫忙做這個轉換,啟用這個策略后,不僅是http靜態資源,http接口調用也會自動轉成https再發出去。
這里只介紹HTML標簽方式:
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">效果如下圖,http的圖片自動變成https:
4.2.?HSTS:防止HTTPS降級劫持
99%的人訪問一個網站都不會主動輸入http前綴,https就更是如此,因為用戶又不知道你的網站是不是https的,所以幾乎所有的https網站都是通過http的301/302自動跳轉的方式來讓用戶進入。注意,由于第一次是http訪問,如果第一次訪問就被劫持那用戶根本到不了https頁面,這就叫https降級劫持。
這個問題可以通過HSTS(HTTP Strict Transport Security)來解決。HSTS是一個響應頭,格式如下:
Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]- max-age,單位是秒,用來告訴瀏覽器在指定時間內這個網站必須通過 HTTPS 協議來訪問,比如說我設置一年,那么一年以內即使用戶輸入http并且被劫持了,瀏覽器依然會以HTTPS的方式來訪問;
- includeSubDomains,可選參數,如果指定這個參數,表明這個網站所有子域名也必須通過 HTTPS 協議來訪問。
- preload,可選參數,是否啟用preload list,關于這個是什么后面再介紹。
注意HSTS這個響應頭是添加到HTTPS響應頭中而不是HTTP響應的,這可能和我們預期的不一樣,如果一個HTTPS網站從來沒被訪問過,那這個HSTS頭永遠生效不了,那怎么辦呢?瀏覽器廠商們為了解決這個問題,提出了一個HSTS Preload List方案:內置一份可以定期更新的啟用HSTS的域名列表,對于列表中的域名,即使用戶之前沒有訪問過,也會使用 HTTPS 協議??雌饋磉@個主意挺餿的,但這也是沒辦法的辦法。想要加入這個列表需要很多強制要求,而且滿足了也不一定能申請成功,我們這里就不細講了。
另外,啟用HSTS必須使用默認的 443 端口;必須使用域名,不能是 IP。而且啟用 HSTS 之后,一旦網站證書錯誤,用戶無法選擇忽略。
建議:只要你不能確保永遠提供 HTTPS 服務,就不要啟用。因為一旦 HSTS 生效,你再想把網站重定向為 HTTP,之前的老用戶會被無限重定向,唯一的辦法是換新域名。
4.3.?Fiddler抓包HTTPS
默認情況下Fiddler不會對HTTPS網站抓包,要啟用的話步驟如下:
Tool?->?Fiddler Options:
然后在IE代理中啟用對HTTPS的代理(默認僅開啟了HTTP):
Fiddler會為每一個網站動態頒發一個*.xxx.com的證書,想要看網站真正證書時需關閉Fiddler:
所以,如果開發時使用Fiddler做代理的話,我們上面那么一大段自己生成證書的步驟可以省略了,哈哈,當然自己掌握了這個過程也不多余。
4.4.?手機抓包HTTPS
需求:手機訪問電腦本機的某個HTTPS網站,而且是用了Fiddler的Willow插件修改了域名的網站。
手機上長按已經連接的WIFI->修改網絡->高級->手動設置代理,代理地址就是你電腦的局域網IP,端口就是上面的8888,保存。
此時直接訪問是不行的,因為Fiddler默認禁用了遠程訪問,開啟方法如下,注意勾選之后必須重啟Fiddler,否則不會生效(開始還以為是防火墻問題):
此時使用手機訪問HTTP網站沒問題,但是訪問HTTPS時會提示證書不受信任,這是因為還沒有安裝Fiddler的根證書(Fiddler對HTTPS進行代理時會使用自己的根證書對每一個訪問的網站動態生成證書,具體細節可以自行百度),手機訪問http://你的IP:8888,點擊頁面的FiddlerRoot certificate鏈接下載安裝證書,安裝成功后即可順利訪問部署在電腦本機的HTTPS網站了。
參考
- SSL證書安裝指引
- 關于啟用 HTTPS 的一些經驗分享(一)
- CHINASSL自2016年1月1日起全面停止簽發SHA-1證書
- Mozilla 將不再信任 WoSign 和 StartCom 頒發的新證書
- 沃通SSL證書事件全程回顧
- 谷歌宣布開始全面封殺使用沃通CA證書網站,信譽破產的惡果
- Let's Encrypt 上線的意義?
- SSL/TLS協議運行機制的概述
- Https單向認證和雙向認證
- httpd設置HTTPS雙向認證
- 主流數字證書都有哪些格式?
- SSL 證書服務,大家用哪家的?
- 細說 CA 和證書
- Content Security Policy Level 2 介紹
- OpenSSL生成v3證書方法及配置文件
轉載于:https://www.cnblogs.com/davidwang456/articles/8192871.html
總結
以上是生活随笔為你收集整理的HTTPS从认识到线上实战全记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中小型研发团队架构实践:电商如何做企业总
- 下一篇: 转变--一个平凡人的2017年总结及20