天天看點

HTTPS從認識到線上實戰全記錄生成CA私鑰生成CA根證書,-day指定證書有效期生成服務端私鑰生成證書請求檔案生成最終證書檔案,-day指定證書有效期IP.1 = 127.0.0.1生成服務端私鑰生成證書請求檔案生成最終證書檔案,-day指定證書有效期

  1. 前言

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

[TOC]

  1. 原理篇

認識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賽門鐵克、Comodo、Godaddy、GolbalSign(百度微網誌等都是它簽發的) 和 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 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(其實好像并沒有統一的區分方法,有的證書不會寫):

證書的格式

一般來說,主流的 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種伺服器各自需要的格式,非常友善。

證書的收費與免費

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

  1. 實踐篇

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

第一步,生成證書

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

申請免費證書

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

•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種證書格式,很友善。

申請到的證書:

自制證書

雖然有很多途徑可以申請到免費的證書,但一般都是單域名(不支援泛域名),限制太多,本地調試極不友善,是以我們希望本地開發時能夠使用我們自己簽發的證書。下面我們就來自己實踐一下如何從頭開始自制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.crt和client.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(混合内容),不同浏覽器對不同類型的混合内容處理方式不一樣,這裡我們隻講主流浏覽器。現代浏覽器(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之後,綠色回來了:

域名不比對

我們還是用前面的例子,假如把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最麻煩的可能就是這一步了,特别是對于曆史悠久的大網站,當然小網站就另當别論了。