搭建基於 Nginx 的 Https 站點
1. HTTPS 相關的基本概念
什麼是 HTTPS
HTTPS 即 超文本傳輸安全協議(HyperText Transfer Protocol Secure),也被稱作 HTTP Over TLS 或者 HTTP Over SSL,是一種網路安全傳輸協議。在計算機網路中,HTTPS 經由超文本傳輸協議(HTTP)進行通訊,但是利用 SSL/TLS 對封包進行加密。HTTPS 的主要設計目的是提供網路伺服器的身份認證,保證交換資料的隱私和完整性。HTTPS 默認使用的埠是 443。
什麼是 SSL
SSL 即 安全套接字層(Secure Socket Layer),是 Netscape 公司研發,通過數據加密技術來保障互聯網上數據傳輸的安全性。現已被廣泛地用於 Web 瀏覽器與伺服器之間的身份認證和加密數據傳輸。SSL 位於 TCP/IP 協議和各種應用層協議之間,由 SSL 記錄協議 和 SSL 握手協議 兩層組成。目前版本為 3.0。
什麼是TLS
TLS 即 傳輸層安全協議(Transfer Layer Security)用於兩個應用程序之間提供保密性和數據完整性。該協議由兩層組成:TLS 記錄協議和 TLS 握手協議。
SSL 與 TLS 的關係
TLS 是建立在 SSL 3.0 協議規範之上,是 SSL 3.0 的後續版本,可以理解為 SSL 3.1,它是寫入了 RFC 的。通常把 SSL 和 TLS 並稱為 SSL/TLS ,他們兩個可以視為同一個東西的不同版本。但是需要注意的是 在 TLS 與 SSL3.0 之間是存在著顯著差別的,主要是它們所支持的加密演算法不同,因此TLS 與 SSL3.0 不能互操作
SSL/TLS 的主要作用
- 認證用戶和伺服器,確保數據發送到正確的客戶機和伺服器
- 加密數據以防止數據中途被竊取
- 維護數據的完整性,確保數據在傳輸過程中不被改變
HTTPS 和 HTTP 以及 SSL/TLS 的關係
我們知道 HTTP 的數據是明文傳輸的,沒有加密。而明文傳輸有以下風險:HTTPS 可以簡單的理解為 HTTP Over SSL/TLS 即 HTTPS 是建立在 SSL/TLS 之上的 HTTP。而 HTTP 則是直接建立在 TCP 協議之上的。
- 竊聽風險(eavesdropping):第三方可以獲知通信內容
- 篡改風險(tampering):第三方可以篡改通信內容
- 冒充風險(pretending):第三方可以冒充他人身份參與通信
而 HTTPS 則可以通過 SSL/TLS 來解決以上三個問題。SSL/TLS 協議的基本思路是採用 公鑰加密法 ,流程是:客戶端先向伺服器索要公鑰,然後用公鑰加密信息,並發送給伺服器,伺服器收到密文之後再用自己的私鑰解密。
但是這裡面有兩個問題:
1. 如何保證公鑰不被篡改:
將公鑰放在數字證書中,只要證書是可信的,公鑰就是可信的
2. 公鑰加密計算量太大,如何減少耗用的時間?
每一次對話(session),客戶端和伺服器端都生成一個 "對話密鑰"(session key),用它來加密信息。由於 "對話密鑰" 是對稱加密,所以運算速度非常快,而伺服器公鑰只用於加密 "對話密鑰" 本身,這樣就減少了加密運算的消耗時間。
SSL/TLS 協議的具體過程
- 客戶端向伺服器端索要並驗證伺服器證書,並從證書中提取公鑰。
- 雙方協商生成 "對話密鑰"。
- 雙方採用 "對話密鑰" 進行加密通信。
其中上面前兩步又稱為 『握手階段』(handshake),至於握手階段的具體過程請參考:SSL/TLS協議運行機制的概述
2. SSL 證書(SSL Certificate)
什麼是 SSL 證書
SSL 證書是一種數字證書,它是由 數字證書認證機構(Certificate Authority, CA) 頒發的,通常是一個很小的數據文件,這個文件將 密鑰 和 組織(使用證書的組織或個人)的相應信息 綁定在一起。SSL證書需要安裝在伺服器上來激活 HTTPS 協議,從而允許伺服器和瀏覽器之間的安全連接。
SSL 證書綁定的信息有:
- 域名,伺服器名或者主機名
- 組織的認證信息(例如公司名稱)和地址
SSL 證書的種類
- Extended Validation(EV):數字證書認證機構(CA) 頒發 EV 的過程需要嚴格按照 EV Guidelines 進行,頒發之前 CA 會審核申請人對域名的所有權,並對申請人的組織信息進行嚴格的、徹底的審查。EV 提供了最高級別的加密,並使網站所屬的組織能夠向用戶展示組織的認證信息。
- Organization Validation(OV):頒發 OV 之前 CA 會審核申請人對域名的所有權,並對申請人的部分組織信息進行審查。
- Domain Validation(DV):只需要審核申請人對域名的所有權,安全級別最低
申請 SSL 證書
StartSSL是一家比較權威的數字證書認證機構,並且提供免費的 DV Certificate , 註冊賬號並登陸之後就可以申請免費的 DV 證書了。
DV 證書的申請分兩步:
- 驗證域名
- 生成並下載證書
生成證書的時候需要提交一個證書籤名請求(Certificate Signing Request, CSR),CSR可以通過 openssl 命令在 命令行生成:
$ openssl req -newkey rsa:2048 -keyout yourname.key -out yourname.csr
執行上述命令並按照提示輸入相應信息,openssl 會生成兩個文件:yourname.key 和 yourname.csr , 執行 openssl 命令時會提示輸入 PEM Pass Phrase, 這個PEM Pass Phrase 需要自己記住,後面會用到。
CSR 文件是用來提交給 CA 用來生成 SSL 證書的,而 yourname.key 是需要放在伺服器上跟 SSL 證書配合使用的,需要妥善保管,不能泄漏給第三方。
複製 yourname.csr 中的內容,粘貼到上圖所示輸入框中,提交表單,就可以下載生成的 SSL 證書(一個 .crt 文件)了。
3. 配置 Nginx 使網站支持 HTTPS
將上面的三個文件(假設SSL證書叫:yourname.crt)上傳到伺服器上,並移動到 /etc/ssl/private 文件夾中
然後修改 Nginx 配置
server { listen 80 default_server; listen [::]:80 default_server; listen 443 ssl; server_name example.com; ssl_certificate /etc/ssl/private/yourname.crt; ssl_certificate_key /etc/ssl/private/yourname.key;}
檢測 Nginx 配置文件並重啟 Nginx:
$ sudo nginx -t && nginx -s reload
這時候會提示你輸入生成 csr 的時候你輸入的 PEM Pass Phase
每次重啟的時候都輸入 PEM Pass Phase 是很麻煩的,為了可以採用 下面的辦法 來避免輸入它:
備份 yourname.key
$ cp yourname.key yourname_backup.key
生成新的 yourname.key
$ openssl rsa -in yourname_backup.key -out yourname.key[enter the passphrase]
新生成的 yourname.key 裡面沒有 passphrase,這樣重啟 nginx 的時候就不需要每次輸入了。
SSL 默認是使用 SHA-1 演算法加密的,但是 SHA-1 加密演算法的安全級別比較低。
- SHA1 crypto algorithm underpinning Internet security could fall by 2018
- Why Google is Hurrying the Web to Kill SHA-1
為了確保更強的安全性,我們可以採取 迪菲-赫爾曼密鑰交換
首先,進入 /etc/ssl/certs 目錄並生成一個 dhparam.pem
$ cd /etc/ssl/certs $ openssl dhparam -out dhparam.pem 2048 # 如果你的機器性能足夠強大,可以用 4096 位加密
生成完畢後,在 Nginx 的 SSL 配置後面加入
ssl_prefer_server_ciphers on;ssl_dhparam /etc/ssl/certs/dhparam.pem;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";keepalive_timeout 70;ssl_session_cache shared:SSL:10m;ssl_session_timeout 10m;
同時,如果是全站 HTTPS 並且不考慮 HTTP 的話,可以加入 HSTS 告訴你的瀏覽器本網站全站加密,並且強制用 HTTPS 訪問
add_header Strict-Transport-Security max-age=63072000;add_header X-Frame-Options DENY;add_header X-Content-Type-Options nosniff;
或者在 Nginx 中配置將 HTTP 請求全部重定向到 HTTPS
server { listen 80; server_name example.com; return 301 https://example.com$request_uri;}
4. 本文的參考資料
- https://s.how/nginx-ssl
- HTTPS
- SSL/TLS協議運行機制的概述
- Understanding SSL
推薦閱讀:
※部署全站HTTPS有哪些值得分享的經驗和教訓?
※如何評價 Chrome Android 不再選用 ChaCha20 作為首選演算法?