1. 程式人生 > >HTTPS從認識到線上實戰全記錄

HTTPS從認識到線上實戰全記錄

目錄

前言

首發於我的個人部落格我的部落格園,轉載請註明出處,謝謝。

關於HTTPS,基本上你想知道的都在這裡了(當然僅限入門)。本文原標題《HTTPS原理與實踐》,下圖是本文配套PPT的目錄截圖:

原理篇

認識HTTPS

先說一下,本文可能有些地方由於描述不到位或者我本人理解錯誤而出現不準確內容,有錯誤歡迎指正!

什麼是HTTPS

HTTPS全稱Hyper Text Transfer Protocol over Secure Socket Layer,直譯過來就是通過SSL實現的超文字傳輸協議,簡單來講就是加密版的HTTP協議,也就是HTTP+SSL/TLS

為什麼需要加密版的HTTP呢,因為我們都知道,HTTP是明文傳輸的,因此使用HTTP協議傳輸隱私資訊非常不安全,很容易在傳輸過程中被竊取,或者通訊內容被人篡改冒充,使用HTTPS可以避免這些問題。

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。

HTTPS的優點

從底層分析HTTPS有以下3大優點:

  1. 防竊聽:資訊被加密了,第三方拿不到密碼,所以可以防竊聽;
  2. 防篡改:還是因為資訊被加密了,如果執意篡改的話,客戶端無法解密不說,而且資料完整性校驗這一關也過不了;
  3. 防冒充:防止攻擊者冒充他人身份參與通訊,比如HTTPS的雙向認證;

從實際出發來看,HTTPS主要有以下優點:

  1. 防止私密資訊洩露,防止資訊被篡改;
  2. 有助於SEO,百度、谷歌均明確表示會優先收錄、展示HTTPS站點的內容;
  3. 完全杜絕運營商HTTP劫持問題;
  4. 有效解決運營商DNS劫持問題,降低網站被劫持的風險;
  5. HTTPS的小綠鎖表示可以提升使用者對網站信任程度(當然不是說有小綠鎖的都是安全的);
  6. 可以有效防止山寨、映象網站等;
  7. 為未來升級HTTP/2做準備,HTTP/2必須基於HTTPS部署;

下面單獨對3和4說一下。

運營商HTTP劫持我們都知道,經常莫名奇妙的在自己網站上看到各種惡意的噁心廣告,檢視程式碼發現被注入了一些奇奇怪怪的js,這其實就是HTTP劫持,啟用了HTTPS之後,我們傳輸的內容都是加密的,運營商想篡改內容都沒轍。

為什麼HTTPS能夠有效的解決DNS劫持呢?在域名被劫持的情況下,客戶端訪問的實際上是攻擊者的IP,客戶端通過這個IP找到攻擊者的伺服器,要求建立HTTPS通訊,因為攻擊者沒有真實伺服器的證書和私鑰(想要申請這個域名的證書必須驗證自己是這個域名的所有者,攻擊者做不到這一點),把偽造或自簽名的證書提供給客戶端,是得不到瀏覽器的認可的,瀏覽器會彈出不安全的警告。但是使用者執意要訪問我們也沒辦法,所以才用了有效解決而不是徹底解決這一詞。

另外,就近看的話,越來越多的場合強制要求https(比如ios、微信小程式等等都要求https),從長遠看,升級HTTPS是大勢所趨,一次升級,永久受益。

HTTPS的缺點

  • 伺服器效能下降,開啟HTTPS會增加記憶體、CPU、網路頻寬的開銷,特別是非對稱加密這一塊;
  • 訪問速度下降,HTTP連線的建立需要3次握手,HTTPS還需要加上ssl的幾次握手(具體是幾次沒去考究,有說是9次),當然下降主要是在第一次建立連線的時候,後面正常通訊速度一般沒啥變化;
  • 除了握手部分外,所有資訊傳輸之後瀏覽器和伺服器都要進行加密解密,又是一筆額外的開銷;
  • 申請證書需要一筆花費,當然現在免費證書也很容易申請到,這個不算明顯缺點;

一句話概括就是:效能和速度下降,但是具體下降多少呢,這個不太好講,可以延伸閱讀:HTTPS 要比 HTTP 多用多少伺服器資源?

HTTPS原理

HTTPS主要分為單向認證和雙向認證,99%的場景都只需要單向認證,雙向認證我們後面再來講。

小明和小紅的故事

在介紹HTTPS原理之前,我們先來假設,假如讓我們自己設計一套加密方案該如何實現呢?為了更好理解,我們用人來舉個栗子:

小明(客戶端)暗戀小紅(服務端),想給小紅寫信,但是又怕信在郵遞的過程中被人偷看,所以他把信裝在一個盒子裡鎖起來,信雖然是安全了,但是小紅就算收到了打不開啊,把鑰匙給小紅寄過去?萬一鑰匙也被人偷去了怎麼辦?

就在這時,小紅想到了一個辦法:小紅把一個沒有上鎖的盒子寄給小明(鑰匙在小紅這),小明把鑰匙放進去再鎖上(小明可以鎖盒子,但是一旦鎖上了就連自己都打不開了),然後把這個裝有鑰匙的盒子寄回給小紅,因為小紅有鑰匙,所以能開啟盒子拿到裡面的鎖信件盒子的鑰匙,再然後就能看到小明給她寫的信了。同時,小紅想回信的話,也可以把信裝在這個盒子裡寄回去,因為這是小明的盒子,他自己肯定還有一把鎖,所以他也能開啟,從此,小明和小紅就可以任意的寫信私通而不用擔心其他人能看到了!

但是,如何保證小紅寄送過來的未上鎖盒子不被別人調包呢?這個等到我們介紹完HTTPS原理之後我們再回過頭來看這個問題。

單向認證

下面這張圖是網上比較常見的一張圖:

這個應該算是精簡版,省略了一些細節,但是對於理解https的核心原理部分足夠了。下面這張圖可能更全面(圖片來源於這裡,感謝作者)

具體過程如下:

  1. 瀏覽器訪問一個https地址,同時向服務端傳送支援的SSL協議版本、支援的加密演算法、一個客戶端生成的隨機數(用於稍後生成"對話金鑰")等。
  2. 服務端給客戶端返回要使用的SSL協議版本號、加密演算法、一個伺服器生成的隨機數(也同樣用於稍後生成"對話金鑰"),另外還有一個最重要的,返回伺服器端的證書,即公鑰證書;
  3. 客戶端收到伺服器迴應以後,首先驗證證書是否合法,如果證書不是可信機構頒佈、或者證書中的域名與實際域名不一致、或者證書已經過期、或者返回的公鑰不能正確解開返回證書中的數字簽名,就會向訪問者顯示一個警告,由其選擇是否還要繼續通訊。如果證書沒有問題,客戶端就會從證書中取出伺服器的公鑰繼續;
  4. 客戶端向服務端傳送自己所能支援的對稱加密方案(注意是對稱加密),供伺服器端進行選擇;
  5. 伺服器端在客戶端提供的加密方案中選擇加密程度最高的加密方式;
  6. 伺服器將選擇好的加密方案通過明文方式返回給客戶端;
  7. 客戶端接收到服務端返回的加密方式後,使用該加密方式生成產生一個隨機金鑰(後續用作通訊過程中對稱加密的金鑰),然後將該隨機數用用證書中的公鑰加密發給服務端;
  8. 伺服器收到客戶端返回的加密資訊後,使用自己的私鑰進行解密,獲得最終的對稱加密金鑰。至此,客戶端和服務端都得到一個隨機金鑰,並且這個金鑰別人沒法知道;
  9. 在接下來的會話中,伺服器和客戶端將會使用該密碼進行對稱加密解密,保證通訊過程中資訊的安全。

至於為什麼會有三個隨機數來生成最終的對稱加密金鑰,主要是為了進一步增大金鑰的隨機性,這裡有一段不錯的解釋:

不管是客戶端還是伺服器,都需要隨機數,這樣生成的金鑰才不會每次都一樣。由於SSL協議中證書是靜態的,因此十分有必要引入一種隨機因素來保證協商出來的金鑰的隨機性。
對於RSA金鑰交換演算法來說,pre-master-key本身就是一個隨機數,再加上hello訊息中的隨機,三個隨機數通過一個金鑰匯出器最終匯出一個對稱金鑰。
pre master的存在在於SSL協議不信任每個主機都能產生完全隨機的隨機數,如果隨機數不隨機,那麼pre master secret就有可能被猜出來,那麼僅適用pre master secret作為金鑰就不合適了,因此必須引入新的隨機因素,那麼客戶端和伺服器加上pre master secret三個隨機數一同生成的金鑰就不容易被猜出了,一個偽隨機可能完全不隨機,可是是三個偽隨機就十分接近隨機了,每增加一個自由度,隨機性增加的可不是一。

需要特別注意的是,以上握手階段全部用的是HTTP協議明文傳輸的。

回到小明和小紅的故事

介紹完HTTPS原理之後,我們再來回到小明和小紅的故事來加深理解。看起來讓小紅寄未上鎖盒子的方案很完美,但是,假如小紅寄過來的盒子被人調包了呢?調包的話開啟情書的鑰匙就被別人拿走了。所以這時候需要有一家在江湖上比較有威望的鏢局(假設叫龍門鏢局)來幫忙押送小紅的盒子,當小明收到盒子時,如果是鏢局親自送過來的、並且說是小紅寄的盒子,那麼小明就認為這是小紅的盒子(小明很信任這家鏢局),前面我們說了,這家鏢局在江湖上很有威望,為了自己的聲譽它必須保證每一趟鏢都沒問題。有人又會問了,幹嘛不直接讓鏢局把信送過去呢?因為小明寫信不可能只寫一封,而且每封情書都讓鏢局來押送成本太大,而且鏢局比郵局流程更繁瑣,更費時間,如果小明收到一個沒聽過的鏢局送過來的聲稱是小紅寄的盒子,那麼他不會相信。

上面例子中,小明是瀏覽器,小紅是伺服器,鏢局是頒發證書的CA(後面會提到),沒聽過的鏢局就是不受信任的根證書,鏢就是證書,信被別人看了叫HTTP明文洩露,信被別人改了叫HTTP劫持,信上的地址被人改了叫DNS劫持,小明寄給小紅的盒子是對稱加密(因為雙方都有鑰匙,都能開啟),小紅寄給小明的沒鎖的盒子可以看做是非對稱加密(因為所有人都可以拿它加密東西,但是一旦加密了就打不開,只有小紅一個人有鑰匙),鏢局自己幹壞事自毀前程就等同於沃通的故事,等等。

雙向認證

雙向認證和單向認證原理基本差不多,主要區別是除了客戶端需要認證服務端以外,服務端對客戶端也需要認證。什麼場景下需要驗證客戶端呢?比如一些銀行業務,銀行會要求客戶必須在電腦上插入它們簽發的U盾之類的東西,或者安裝什麼控制元件,這裡就類似客戶端證書的概念,沒有這個證書的人無法使用銀行提供的業務。

雙向認證我沒有去親自嘗試,可以參考這篇文章

下面還是上面那位網友畫的雙向認證圖,我沒有仔細考究,先貼在這裡:

引申思考

如何保證公鑰不被篡改

將公鑰放在數字證書中。只要證書是可信的,公鑰就是可信的。

那如何保證證書可信呢?證書的生成都是由國際頂級認證機構簽發的,簽發的時候必須驗證你是不是這個域名的所有者,只有是才給你簽發證書(證書和域名一一掛鉤),所以理論上其他人無法偽造你的證書(只是理論上),即使偽造了,瀏覽器在載入的時候會進行域名校驗,如果證書中的域名和實際域名不匹配,瀏覽器是會警告的。

問題又來了,瀏覽器怎麼知道你的證書是不是合法的國際頂級認證機構簽發的呢?作業系統和瀏覽器都內建了一些他們認為可信任的國際頂級認證機構(CA,後面會提到),只有他們簽發的證書瀏覽器才信任。

為何正式傳輸時使用對稱加密

因為非對稱加密很慢,而且傳輸普通內容時雙方都已經拿到了隨機又沒有其他人知道的密碼,所以普通的對稱加密足矣。

CA

何為CA

CA(Certificate Authority),即證書認證機構,它的作用就是提供證書(即伺服器證書,由域名、公司資訊、序列號和簽名信息組成)加強服務端和客戶端之間資訊互動的安全性,以及證書運維相關服務。任何個體/組織都可以扮演 CA 的角色,難的是你要能得到全世界各大作業系統、瀏覽器等的預設信任,能得到他們的預設信任,你也可以自己開一家CA公司了,這類證書通常叫做根證書。瀏覽器預設信任的 CA 大廠商有很多,比如 Symantec賽門鐵克、ComodoGodaddyGolbalSign(百度微博等都是它簽發的) 和 Digicert

如何檢視作業系統內建了哪些CA呢?Internet選項->內容->證書->受信任的根證書頒發機構:

想讓你的https網站預設情況下就被全世界瀏覽器信任你必須使用它們簽發的證書,大部分都是要錢的,當然也有免費的。

很多人一開始應該有和我一樣的疑問,我升級我的https,憑啥要到別人那裡花錢買證書(即使有免費的也不爽)?,看到這裡我想不用再多解釋你應該懂了。

CA如果作惡怎麼辦

CA必須是絕對公平公正不作惡的,否則一旦暴露出來一些醜聞,立即會被各大瀏覽器和廠商拉入黑名單不再信任,或者各種降級處理,帶來的後果甚至可能是殺身之禍,比如被360收購的沃通的下場:谷歌宣佈開始全面封殺使用沃通CA證書網站,信譽破產的惡果

沃通的主要罪狀有五個:

  1. 祕密收購自己的根CA公司startcom;
  2. 只要有子域名的許可權就可以得到頂級域名的許可權,這個很危險,比如github是開放子域名給任何使用者的;
  3. 偽造證書籤署日期;
  4. 簽署多個相同序列號證書;
  5. 郵件恐嚇使用其它免費證書的使用者說他們的證書不安全;

沃通為何要偽造簽署日期呢?

由於如今的運算能力越來越強,SHA1 雜湊演算法的可靠性越來越不夠了。一些主流的瀏覽器,如果發現2016元旦之後簽署的 CA 證書,依然採用 SHA1,會給出警告。沃通為了幫證書申請人規避瀏覽器警告,故意把簽署日期偽造成2015年底。

頂級證書私鑰洩露怎麼辦

如果頂級證書的私鑰洩露,那麼帶來的後果是災難性的,只能各大瀏覽器和作業系統通過更新補丁的方式來吊銷洩密的根證書,洩露之後一般這家CA公司離倒閉不遠了,也不是沒有這樣的例子:

荷蘭CA供應商DigiNotar因為黑客入侵事件而成為萬眾矚目的焦點,它發行的證書被眾多瀏覽器開發商和作業系統開發商宣佈為不受信任。現在,這家失去信任的CA宣告破產。疑似伊朗黑客在7月中旬入侵了DigiNotar伺服器,發行了531個偽造證書,包括了Google、微軟、雅虎、Twitter、Facebook、中情局、軍情六處和摩薩德等。DigiNotar在7月19日發現了入侵,但直到8月份外界才知道入侵事件。DigiNotar的母公司VASCO承認損失慘重。

SSL證書

證書的種類

SSL 證書按大類一般可分為DV SSLOV SSLEV 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(其實好像並沒有統一的區分方法,有的證書不會寫):

證書的格式

一般來說,主流的 Web 服務軟體,通常都基於 OpenSSL 和 Java 兩種基礎密碼庫。

  • TomcatWeblogicJBossWeb服務軟體,一般使用JDK自帶的Keytool工具,生成Java Keystore(JKS)格式的證書檔案。
  • ApacheNginxWeb服務軟體,一般使用OpenSSL工具提供的密碼庫,生成 .key.crt等格式的證書檔案。
  • IBM 的 Web 服務產品,如 Websphere、IBM Http Server(IHS)等,一般使用 IBM 產品自帶的 iKeyman 工具,生成 KDB 格式的證書檔案。
  • 微軟的IIS使用Windows自帶的證書庫生成pfx格式的證書檔案。

詳見下圖:

每種格式之間都可以相互轉換,轉換方法可以參考阿里雲給出的幫助文件,在騰訊雲申請證書的時候會自動幫你生成4種伺服器各自需要的格式,非常方便。

證書的收費與免費

不是說收費的證書就一定比免費證書好,只不過現階段各CA機構為了自己的盈利目的,免費證書一般都有一些限制,比如只支援單域名,子域名太多的話需要挨個申請。

實踐篇

本文全部以nginx配置為例,其它Web伺服器配置請自行google,或者參考這篇不錯的文章:SSL證書安裝指引

第一步,生成證書

首先我們需要得到一張證書,可以申請免費的,也可以自制,本地測試時一般自制證書。

申請免費證書

免費證書一般有下面幾種:

  • Let's Encrypt:獲得Mozilla、微軟等主要瀏覽器廠商的根授信,出現的目的就是為了推廣HTTPS,缺點是隻有3個月有效期,過期需續簽;
  • TrustAsia亞洲誠信;
  • StartSSL免費DV證書:因醜聞被主流瀏覽器封殺,一般不建議;
  • Wosign(沃通)免費DV證書:同上,被各大瀏覽器封殺,基本可以無視了;

我們一般不需要自己直接和它們打交道,國內的雲服務提供商一般都有免費的證書申請,這裡操作會更簡單一點。

先宣告一下,這裡不是打廣告,如果有更好用的,歡迎大家推薦。阿里雲之前有一款免費的SSL證書申請,但是現在好像下線了,騰訊雲有一款TrustAsia的免費證書,又拍雲說是有2款免費證書,而且可以自動續簽,但是試了一下發現必須把域名繫結到它們的CNAME才行,所以想想還是放棄了:

最後我用的是騰訊雲免費SSL證書,有一款TrustAsia的免費證書,缺點是有效期只有1年(到期應該可以重新申請),且不支援泛域名,如果子域名很多的話比如挨個申請,很麻煩,大家有更好用的歡迎推薦:

申請很簡單,簡單填寫資料,然後驗證域名身份,快的話2-3分鐘內就能成功申請到:

成功後可以把證書下載到本地,內建了ApacheIISNginxTomcat的4種證書格式,很方便。

申請到的證書:

自制證書

雖然有很多途徑可以申請到免費的證書,但一般都是單域名(不支援泛域名),限制太多,本地除錯極不方便,所以我們希望本地開發時能夠使用我們自己簽發的證書。下面我們就來自己實踐一下如何從頭開始自制HTTPS證書。

證書一般都是用openssl來生成,當然也可以用jdk自帶的keytool來生成,但是最終還是要用openssl來轉換格式,所以一般還是推薦用openssl來生成。

安裝openssl

首先當然還是安裝openssl,這裡我們只介紹Windows平臺,Linux系統的請參考這裡,點選這裡下載Win64位的安裝包:

安裝很簡單,安裝完畢之後為了使用方便,建議配置一下環境變數:

然後就可以隨時隨地執行openssl命令了。

生成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'的錯誤,一般都是因為沒有使用管理員許可權開啟命令列視窗。

生成服務端證書

和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

雙擊生成的證書可以看到如下內容:

生成客戶端證書

如果需要實現HTTPS雙向認證,還要按照上述服務端一模一樣的操作再生成一個client.crtclient.key,這裡我們就不重述了,90%的場景都是不需要雙向認證的。

匯入證書

上述步驟執行完之後生成了如下檔案:

我們只需要雙擊ca.crt匯入這個自制根證書即可,以後只要是利用這個證書生成證書瀏覽器都會認為是可信任的,這讓我想起了12306乾的勾當,如果你能把你這個根證書推廣到全世界的電腦和手機,那麼你也可以成立一家CA公司專門賣證書了,哈哈。

匯入的時候注意證書儲存位置:

由於這是很敏感的操作,所以作業系統一定會有警告:

引申話題:12306為啥不申請證書

這個標題在大約在半個月前還是正確的,但是,就在大約半個月前,12306終於買證書了!!!倔強的12306堅持了這麼多年推廣自己的證書,終於還是妥協了:

我們還是回到12306沒買證書以前。我們先回憶一下12306的做法,首頁不是https,它在首頁明顯位置放置了一個證書下載連結讓我們去下載,真正的購票頁面才開啟了https,沒安裝這個證書瀏覽器就會各種警告。

有很多人都在網上問,12306為啥沒買證書呢?是不捨得花這個錢嗎?當然不是,堂堂鐵老大再怎麼虧損多少個億,這點錢還是出得起的,12306無非就是想利用自己絕對壟斷地位推廣自己的SRCA證書而已(12306有一箇中鐵數字證書認證中心),至於推廣證書有什麼用,這不用我多說吧。

摘抄一段網友的話:

合法證書對於SSL加密通訊和通訊完整性保護的意義就是合格鑰匙之於鎖的關係,你把山寨CA請到你家瀏覽器的受信任CA列表,就相當於你從大馬路上撿把插著萬能鑰匙的鎖回家裝大門上。門上確實有鎖,沒鑰匙確實進不來你家偷窺(機密性保護)和盜竊(完整性保護),但有萬能鑰匙的人呢?

第二步,nginx的ssl模組安裝

Windows系統

Windows平臺的nginx.exe一般內建了ssl模組,無需額外單獨安裝。

Linux系統

linux系統的nginx一般都是編譯安裝的,如果你第一次安裝nginx的時候已經安裝了ssl模組的話,這一步可以跳過,如果沒有,繼續往下看。

如何檢視有沒有安裝ssl模組呢?定位到nginx/sbin目錄執行nginx -V檢視安裝時的命令,如果有--with-http_ssl_module,說明已經安裝了ssl模組,那麼你可以跳過這一步了。

這裡著重要講的是已經上線運行了一段時間的nginx如果安裝新模組,其實下面的內容在我另外一篇文章中有提到過。

編譯安裝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 install

重新編譯nginx

nginx安裝新模組需要整體重新編譯,所以需要知道上一次安裝時的編譯命令,假設nginx安裝在/home/nginx/nginx-1.8.1下面,定位到sbin下面執行./nginx -V(注意V是大寫)後可以檢視安裝時使用的命令:

[[email protected] 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檢視是否正常。

第三步,nginx配置

配置

假設我們有一個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的完整域名!

常見問題

Mixed Content

https頁面出現http連結的資源我們稱之為Mixed Content(混合內容),不同瀏覽器對不同型別的混合內容處理方式不一樣,這裡我們只講主流瀏覽器。現代瀏覽器(ChromeFirefoxSafariMicrosoft Edge)基本上都遵守了W3CMixed Content規範,將其分為Optionally-blockableBlockable兩類:

  • Optionally-blockable主要是隻危險較小的圖片、視訊、音訊等資源,這類資源即使被人篡改也不會有太大的問題,瀏覽器預設會載入,展示在控制檯會列印警告資訊,並且https不是綠色的。
  • Blockable一般是指除了上述之外所有的被限制載入的http資源,如JSCSSiframe等,瀏覽器會直接禁止載入,並且控制檯列印錯誤資訊。

所以網站在升級https時需要特別注意,既然要升級就最好要全站升級,不然很容易出現某些資源由於寫死了http://頭導致瀏覽器無法載入的嚴重問題。當然也不是沒有辦法解決,可以通過CSPupgrade-insecure-requests指令讓網頁所有http資源自動指向https,限於篇幅,本文不對此展開講,讀者可自行了解CSPHSTS等相關概念。

繼續回到正文,當頁面有http資源時,https不是綠色的:

將所有http連結改成https之後,綠色回來了:

域名不匹配

我們還是用前面的例子,假如把nginx中的域名改成www.localhost2.com,同時hosts也改下,但是證書不變,然後再次開啟瀏覽器訪問時提示NET::ERR_CERT_COMMON_NAME_INVALID

所以,DV證書一定要是和域名掛鉤的,域名不匹配瀏覽器會攔截。

根證書不受信任

假如我們前面自制的CA根證書沒有匯入到作業系統(模擬時可以從Internet選項裡面找到證書入口刪除之前的證書即可),然後瀏覽器會提示NET::ERR_CERT_AUTHORITY_INVALID

使用SHA-1簽名的證書

SHA-1在許多安全協議中廣泛使用,包括TLS和SSL、PGP、SSH、S/MIME和IPsec。早在2005年,密碼學家就證明SHA-1的破解速度比預期提高了2000倍,雖然破解仍然是極其困難和昂貴的,但隨著計算機變得越來越快和越來越廉價,SHA-1演算法的安全性也逐年降低,已被密碼學家嚴重質疑。所以,各大瀏覽器相繼宣佈將逐步停止對SHA-1簽名證書的支援。

使用SHA-1演算法瀏覽器會給出警告

所以在生成證書時一定要指定-sha256引數。

證書重新整理不及時

更換證書時最好重啟一下nginx然後多重新整理2次防止未生效折騰半天;

第四步,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 。`

第五步,網站程式碼改造

這個根據實際網站的不同難易程度會有很大不同,例如,如果你是全站升級https,包括各類子域名,那麼很簡單,全文搜尋http,批量替換成//開頭即可。但是如果只是部分升級,比如主站升級了,子站沒升級,然後主站頁面又有各種子站的資源連結、跳轉等,這就麻煩了,這時候只能手動處理了。特別是針對子域名比較多的網站,免費證書又都不支援泛域名,全部升級需要一個個去生成證書,然後配置,麻煩死了。

另外,為了安全起見,剛開始的時候建議靜態資源的站點(比如圖片,很有可能外站引用了這個圖片連結)同時保持http和https都可以訪問,等時間成熟了再下掉或者做301重定向,否則很容易出現某個資源載入不了導致404的問題。

升級https最麻煩的可能就是這一步了,特別是對於歷史悠久的大網站,當然小網站就另當別論了。

其它

CSP

CSP,全稱Content Security Policy,意即內容安全策略,有非常多的指令,用來實現各種各樣與頁面內容安全相關的功能,這裡介紹2個比較有用的。所有CSP指令都有2種啟用方式,一種是HTTP頭部,一種是<meta>標籤。

禁用http連結

前面說過,對於HTTPS頁面中的圖片等資源瀏覽器預設會載入,僅僅是控制檯給一個警告,因為圖片類資源被劫持通常問題不會太大,但有些頁面按鈕佈局等是用圖片做的,圖片被篡改會影響使用者使用,最重要的,頁面只要有一個http的連結,位址列的https就不是綠色的。

可以通過CSPblock-all-mixed-content指令讓頁面進入對Mixed Content的嚴格檢測(Strict Mixed Content Checking)模式。在這種模式下,所有非 HTTPS 資源都被禁止載入,控制檯報錯,https迴歸綠色。

HTTP響應頭方式:

Content-Security-Policy: block-all-mixed-content

HTML標籤方式:

<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">

強制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

HSTS:防止HTTPS降級劫持

99%的人訪問一個網站都不會主動輸入http字首,https就更是如此,因為使用者又不知道你的網站是不是https的,所以幾乎所有的https網站都是通過http301/302自動跳轉的方式來讓使用者進入。注意,由於第一次是http訪問,如果第一次訪問就被劫持那使用者根本到不了https頁面,這就叫https降級劫持。

這個問題可以通過HSTSHTTP 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,之前的老使用者會被無限重定向,唯一的辦法是換新域名。

Fiddler抓包HTTPS

預設情況下Fiddler不會對HTTPS網站抓包,要啟用的話步驟如下:

Tool -> Fiddler Options

然後在IE代理中啟用對HTTPS的代理(預設僅開啟了HTTP):

Fiddler會為每一個網站動態頒發一個*.xxx.com的證書,想要看網站真正證書時需關閉Fiddler:

所以,如果開發時使用Fiddler做代理的話,我們上面那麼一大段自己生成證書的步驟可以省略了,哈哈,當然自己掌握了這個過程也不多餘。

手機抓包HTTPS

需求:手機訪問電腦本機的某個HTTPS網站,而且是用了FiddlerWillow外掛修改了域名的網站。

手機上長按已經連線的WIFI->修改網路->高階->手動設定代理,代理地址就是你電腦的區域網IP,埠就是上面的8888,儲存。

此時直接訪問是不行的,因為Fiddler預設禁用了遠端訪問,開啟方法如下,注意勾選之後必須重啟Fiddler,否則不會生效(開始還以為是防火牆問題):

此時使用手機訪問HTTP網站沒問題,但是訪問HTTPS時會提示證書不受信任,這是因為還沒有安裝Fiddler的根證書(FiddlerHTTPS進行代理時會使用自己的根證書對每一個訪問的網站動態生成證書,具體細節可以自行百度),手機訪問http://你的IP:8888,點選頁面的FiddlerRoot certificate連結下載安裝證書,安裝成功後即可順利訪問部署在電腦本機的HTTPS網站了。

參考

相關推薦

HTTPS認識線上實戰記錄

目錄 前言 首發於我的個人部落格和我的部落格園,轉載請註明出處,謝謝。 關於HTTPS,基本上你想知道的都在這裡了(當然僅限入門)。本文原標題《HTTPS原理與實踐》,下圖是本文配套PPT的目錄截圖: 原理篇 認識HTTPS 先說一下,本文可能有些地方由於描述不到位或者我本人理解錯誤而出現不準確內容,有錯

Redis Linux 安裝執行實戰記錄

下載Redis 去Redis官網下載最新的Linux包,Redis官方沒有Windows版的下載。 https://redis.io/ 下載後把包上傳到Linux伺服器。 安裝Redis 1、解壓Redis包 > tar -zxvf redis-4.

線上服務器PHP版本編譯安裝升級記錄

update .html ack glib libpng ++ libc epo tar.gz 1.將原來的PHP重命名一下 cd /usr/local/bin/ mv php php.2.9 2.安裝依賴 yum install gcc gcc-c++ libxml

Python3 視頻教程,全網最的視頻教程,爬蟲,入門到實戰

python3 python基礎 入門到 分享 視頻 pst https size 分布式爬蟲 需要聯系我:QQ:1844912514 最新Python基礎班+就業班視頻教程 鏈接: python分布式爬蟲打造搜索引擎鏈接: https://pan.baidu.com/

Docker最教程——理論到實戰(一)

容器是應用走向雲端之後必然的發展趨勢,因此筆者非常樂於和大家分享我們這段時間對容器的理解、心得和實踐。 本篇教程持續編寫了2個星期左右,只是為了大家更好地瞭解、理解和消化這個技術,能夠搭上這波車。 你可以和我們一起討論,我們希望能夠多多交流,多多分享。 如果覺得不錯,請多多點贊,你們的支援是我們前進的最

Docker最教程——理論到實戰(三)

往期連結: https://www.cnblogs.com/codelove/p/10030439.html https://www.cnblogs.com/codelove/p/10036608.html     寫在前面 容器是應用走向雲端之後必然的發展趨勢,因此筆者非常樂

Docker最教程——理論到實戰(四)

變量 參加 屬於 當我 web服務 隔離 方便 當前 context 往期內容鏈接 https://www.cnblogs.com/codelove/p/10030439.html https://www.cnblogs.com/codelove/p/10036608.

抓包神器Charles入門到精通 - 使用招式記錄

簡介 Charles是一款執行在你自己計算機上的web代理與抓包工具。它可以有效地獲取HTTP通訊資訊,主要用於網頁的開發和除錯等,強大又多元功能是每個程式設計師必備的利器,如果免費就完美了。 官網 https://pan.baidu.com/s/1dEBXMil Charles

Docker最教程——理論到實戰(七)

本篇教程持續編寫了3個星期左右並且一直在完善、補充具體的細節和實踐,預計全部完成還需要1到2個月的時間。整個教程完成之後,我們將會出書(目前已聯絡出版社)。在這個過程中,您可以加入我們的QQ群(85318032)一起討論、交流和分享這一塊的技術。根據目前和大家的交流,筆者針對大家的情況進行了

Docker最教程——理論到實戰(七) Docker最教程——理論到實戰(一) Docker最教程——理論到實戰(二) Docker最教程——理論到實戰(三) Docker最教程——理論到實戰(四) Docker最教程——理論到實戰(五) Docker最教程——理論到實戰

在本系列教程中,筆者希望將必要的知識點圍繞理論、流程(工作流程)、方法、實踐來進行講解,而不是單純的為講解知識點而進行講解。也就是說,筆者希望能夠讓大家將理論、知識、思想和指導應用到工作的實際場景和實踐之中,而不是拿著字典寫文章,抱著寶典寫程式碼。至於很多具體的語法、技術細節,除了常用的知識點,筆者更希望大家

Docker最教程——理論到實戰(一) Docker最教程——理論到實戰(一)

Docker最全教程——從理論到實戰(一) 目錄 前言 隨著生產力的發展尤其是彈性架構的廣泛應用(比如微服務),許多一流開發者都將應用託管到了應用容器上,比如Google、微軟、亞馬遜、騰訊、阿里、京東和新浪。   從未來的發展方向來看,容器引擎將會越來越成為主流,哪怕不是彈性架構

Docker最教程——理論到實戰(二) Docker最教程——理論到實戰(二)

Docker最全教程——從理論到實戰(二) Docker和ASP.NET Core Docker 正在逐漸成為容器行業的事實標準,受到 Windows 和 Linux 生態系統領域最重要供應商的支援。 (Microsoft 是支援 Do

Docker最教程——理論到實戰(三) Docker最教程——理論到實戰(三)

Docker最全教程——從理論到實戰(三) 寫在前面 容器是應用走向雲端之後必然的發展趨勢,因此筆者非常樂於和大家分享我們這段時間對容器的理解、心得和實踐。 本教程持續編寫了2個星期左右並且一直在完善、補充具體的細節和實踐,預計全部完成需要1到2個月的時間。由於編寫的過程中極其費時,並且還需要配合做一些

Docker最教程——理論到實戰(五) Docker最教程——理論到實戰(五)

Docker最全教程——從理論到實戰(五) 執行 Docker 應用程式 如果應用程式只有一個容器,則可通過將其部署到 Docker 主機(虛擬機器或物理伺服器)來執行該程式。 但如果應用程式包含多項服務,則可使用單個 CLI 命令 (docker-compose up) 或使用 Visual S

Docker最教程——理論到實戰(四) Docker最教程——理論到實戰(四)

Docker最全教程——從理論到實戰(四) 建立自定義 Docker 映象   建立了Dockerfile之後,需為應用程式中的每項服務建立一個相關映象。如果應用程式由單個服務或 Web 應用程式組成,則只需建立一個映象。 我們可以使用docker build命令來建立映象,例如

Docker最教程——理論到實戰(二)

Docker和ASP.NET Core Docker 正在逐漸成為容器行業的事實標準,受到 Windows 和 Linux 生態系統領域最重要供應商的支援。 (Microsoft 是支援 Docker 的主要雲供應商

Docker最教程——理論到實戰(一)

容器是應用走向雲端之後必然的發展趨勢,因此筆者非常樂於和大家分享我們這段時間對容器的理解、心得和實踐。 本篇教程持續編寫了2個星期左右,只是為了大家更好地瞭解、理解和消化這個技術,能夠搭上這波車。 你可以關注我們的公眾號“magiccodes”給我們留言,也可以加入我們的QQ群(853180

Docker最教程——理論到實戰(八) Docker最教程——理論到實戰(一) Docker最教程——理論到實戰(二) Docker最教程——理論到實戰(三) Docker最教程——理論到實戰(四) Docker最教程——理論到實戰(五) Docker最教程——理論到實戰

在本系列教程中,筆者希望將必要的知識點圍繞理論、流程(工作流程)、方法、實踐來進行講解,而不是單純的為講解知識點而進行講解。也就是說,筆者希望能夠讓大家將理論、知識、思想和指導應用到工作的實際場景和實踐之中,而不是拿著字典寫文章,抱著寶典寫程式碼。至於很多具體的語法、技術細節,除了常用的知識點,筆者更希望大家

-Angular 4.0入門到實戰 打造線上競拍網站-

這個視訊資源應該是我目前看到的比較全面完整的關於angular的視訊,學習還是挺不錯的,下列是課程目錄列表:第1章準備好了嗎,那就開始吧!!!在這一章裡,我們首先會對整個課程的內容做一個簡要的介紹,包括章節的安排,實戰幸例的介紹以及前置知識的介紹等內容。然後我們會從一個比較高

HTTPS配置記錄

前幾天幫腎上[email protected](CSDN唯一一個使用者名稱裡有特殊字元的使用者)部署一個HTTPS,雖然去年寫過用Let’s Encrypt證書部署HTTPS的文章,但是這次略有不同,所以作個記錄吧,順便也把常見的做法都說一說。