書接上文:HTTPS 基礎原理和設定 - 2,接下來介紹:
重要部分來了。如何使用這些選項並設定NGINX?
這裡有一些基本的原語(或叫做指令),你可以使用:ssl_certificate
、ssl_certificate_key
、ssl_protocols
和ssl_ciphers
。
在開始之前: NGINX 處理 TLS 的方式是使用 OpenSSL,我相信你已經在新聞中聽說過這個庫。它因 Heartbleed 和其他一些漏洞而聞名。它確實是最廣泛使用的內建加密庫。這是 NGINX 用於加密的。
因此,在伺服器上要做的一件事是檢查正在使用的 OpenSSL 版本。你可能不想使用 0.9.8 之類的版本。你希望在1.0.1p 或 1.0.2 範圍內使用,因為多年來他們已經修復了許多 bug。你永遠不知道下一個 OpenSSL 漏洞什麼時候出現,但至少現在它是非常可靠的(1.0.1p)。它還擁有所有現代加密演演算法。
所以,當你在 NGINX 中設定你的伺服器部分時,ssl_certificate
就是你的證書鏈。這是你的證書加上所有的信任鏈一直到根證書。然後你還需要提供你的私鑰。
ssl_certificate_key
就是你的私鑰。
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /path/to/signed_cert_plus_intermediates;
ssl_certificate_key /path/to/private_key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
ssl_dhparam /path/to/dhparam;
# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
}
你還可以新增一些與對談恢復有關的額外選項。如前所述,當你第一次建立 TLS 連線時,需要額外的兩次往返,因為你必須完成整個握手和交換證書。如果你以前連線過一個使用者端,並且他們已經快取了對談傳輸所使用的金鑰,那麼你可以只恢復該對談。這是一個稱為對談恢復的特性。
你只需要一個超時來說明你希望將對談保留多長時間,以及這些對談的快取可以有多大。在本例中,預設是 10 MB 的對談;那應該夠你用很長時間了。共用快取是首選,因為這樣你就可以在所有 NGINX worker 之間共用它們。
例如,如果你的一個 worker 是最初建立連線的那個,而第二個連線被建立到另一個 NGINX worker,你仍然可以恢復連線。還有另一個選項叫做「session ticket」。它只在 Chrome 核心瀏覽器和 Firefox 中使用,但本質上是一樣的。你必須生成一個隨機的 48 位元組檔案,但我建議暫時只使用對談快取。
作為一個非常明顯的下一步,你必須列出希望支援的協定和密碼。在這種情況下,上文是 Mozilla 推薦的密碼,以及從 1.2 版到 1.3 版的 TLS 協定。
我提到過你如何協商你選擇的密碼; 你可以選擇使用者端的選擇或伺服器的選擇。最好選擇伺服器的選擇。這裡有一個指令: ssl_prefer_server_ciphers
——始終開啟它。
如果你有多個站點,並且它們使用相同的證書,那麼你實際上可以分解 HTTP 定義。你可以在頂層使用 SSL 證書,在底層使用不同的伺服器。這裡你需要記住的一件事是如果你有 example.com 和 example.org ,你必須有一個證書對這兩個名字都有效,這樣才能工作。
ssl_certificate multiSAN.crt;
ssl_certificate_key multiSAN.key;
server {
listen 443 ssl;
server_name www.example.com;
...
}
server {
listen 443 ssl;
server_name www.example.org;
...
}
以上基本上就是為 NGINX 設定 HTTPS。
更高階的話題是:如何使用 NGINX 作為其他 HTTPS 服務的代理?
我們稱之為後端加密。所以,你的訪客存取你的 NGINX 伺服器是完全加密的。NGINX 背後發生了什麼? 在這種情況下,NGINX 必須充當瀏覽器存取你的後端服務。
這可以在 NGINX 中以類似的方式設定。也有類似於 ssl_protocols
和 ssl_ciphers
的指令; 在本例中,你將它放在一個代理下。NGINX 作為使用者端將使用 proxy_ssl_protocols
和 proxy_ssl_cipher
指令。
http {
server {
proxy_ssl_protocols TLSv1.2 TLSv1.3; # 協定
proxy_ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; # 密碼套件
proxy_ssl_trusted_certificate /etc/ssl/certs/trusted_ca_cert.crt; # 受信任的 CA
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_session-reuse on;
}
}
我建議使用完全相同的密碼套件和協定集。這裡的主要區別是使用者端對伺服器進行身份驗證。所以,在瀏覽器的情況下,你有一組你信任的證書頒發機構,而 NGINX 作為使用者端,你也需要一組你信任的證書頒發機構。
你可以使用兩種不同的理念來實現這一目標,一種是建立你自己的內部證書頒發機構並在內部管理它。這有點棘手,但它更便宜,也更容易管理,因為你可以為任何服務頒發證書,並將它們頒發給你擁有並完全控制的證書頒發機構。在這種情況下,proxy_ssl_trusted_certificate
將被設定為你的證書頒發機構。
或者,你可以使用我在上一篇文章中描述的相同技術。你可以為你所有的服務購買證書,然後如果你的NGINX需要信任它們,它可以信任瀏覽器信任的同一套證書頒發機構。
對於 Ubuntu,磁碟上有一個列表,裡面包含了幾乎所有平臺的所有證書。但是,如果你正在構建一組需要相互通訊的大型服務,那麼就很難為這些域頒發證書。你必須向證書頒發機構證明所有權才能實際獲得證書。
我推薦內部 CA 機制。最困難的部分是——如何保證證書頒發機構的安全? 如何保證證書頒發機構的私鑰的安全? 你可以通過使用離線計算機和特殊管理員來實現這一點,但無論哪種情況,都存在一些挑戰。
NGINX 設定了 HTTPS。如何檢查它的設定是否正確?
SSL Labs 是人們最喜歡的網站檢查工具之一。SSL Labs 是 Qualys 運營的一個網站; 你只要輸入你的域名,它就會執行所有型別的瀏覽器,所有型別的 SSL 連線,它會告訴你哪些設定正確,哪些設定錯誤。
在本例中,我們檢查了一個名為 badSSL.com 的網站,它列舉了所有可能導致 HTTPS 設定混亂的不同方法。你可以用 SSL Labs 掃描每一個,它會告訴你每一個有什麼問題。在本例中,給出的等級是 C,因為它支援 SSL v3.0。
這裡還提到了其他一些東西,你們可以修改,但在我如何設定 NGINX 的描述中,如果你這樣設定,你基本上會得到 A。這意味著證書協定支援、金鑰交換和密碼強度都是頂級的。
這對網際網路網站非常有效; 如果你有防火牆或 NGINX 後面的服務,CloudFlare 構建了這個叫做 CFSSL 掃描的工具。你可以在內部基礎架構中使用它; 它是開源的,在 cloudflare/cfssl: CFSSL: Cloudflare's PKI and TLS toolkit (github.com)上。它將做本質上與 SSL Labs 相同的事情,只是在你的基礎設施內。它會告訴你什麼是對的,什麼是錯的。
之前提到過得到 A 的方法,那麼 A+ 呢?事實證明,SSL Labs 就會給一個 A+,當你有了一個叫做 HSTS (Hypertext Strict Transport Security, 超文字嚴格傳輸安全) 的特性。
本質上,這是一個 HTTP 頭,你可以新增到你的請求,告訴瀏覽器總是通過 HTTPS 存取這個站點。即使他們最初是通過 HTTP 存取的,也總是重定向到 HTTPS。
然而,這實際上有一點危險,因為如果你的 SSL 設定中斷或證書過期,那麼存取者將無法存取該站點的純 HTTP 版本。你還可以做一些更高階的事情。就是將你的站點新增到預載入列表中。Chrome 和火狐瀏覽器都有一個列表,所以如果你註冊了,他們就永遠不會通過 HTTP 存取你的網站。
SSL Labs 將給你一個 A+ 如果其他一切正確的。你需要正確地設定 includeSubdomains
的 HSTS(這意味著它適用於所有子域名),並且它必須有至少 6 個月的有效期,這使得它非常危險。這是因為如果你改變了你的設定,瀏覽器將會記住這六個月。所以你必須保持你的 HTTPS 設定正常工作。
這是一件好事,因為它可以防止任何人在中間修改它。使用 HSTS,瀏覽器甚至不會有機會存取你的 HTTP 端,因此人們不會在這方面干擾你的站點。所以 HSTS 是一個非常可靠的方法。
正如我提到的,有幾個風險:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /path/to/signed_cert_plus_intermediates;
ssl_certificate_key /path/to/private_key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
ssl_dhparam /path/to/dhparam;
# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (15768000 seconds)
add_header Strict-Transport-Security "max-age=15768000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
# replace with the IP address of your resolver
resolver 127.0.0.1;
}
要設定它,只需在 NGINX 的伺服器設定中新增一個標頭檔案,上面寫著 Strict-Transport-Security
,並給它一個最大時間(max-age
)。在本例中,它被設定為6個月(這是預載入列表所需的最低時間)。你還可以在這裡新增其他指令,如:includeSubdomains和preload,這意味著可以接受這個指令並將其新增到預載入列表中。這就是得到 A+ 的方法。
這是一些人喜歡使用的另一個附加功能,它實際上可以幫助加快連線速度。
正如我前面提到的,建立一個TLS連線需要有很多來回的。我沒有提到的是,這些證書不僅可以過期失效,還可以被吊銷。
因此,如果你丟失了你的私鑰,出現了漏洞,或者有其他人非法擁有了你的私鑰,那麼你必須去你的證書頒發機構並復原這個金鑰。有幾種機制可以告訴瀏覽器證書已被吊銷; 它們都有點粗略,但最流行的是 OCSP(Online Certificate Status Protocol,線上證書狀態協定)。
發生的情況是: 當瀏覽器收到證書時,它還必須檢查它是否被吊銷了。於是它聯絡了證書頒發機構,問「這個證書還有效嗎?」他們會回答「是」或「不是」。這本身就是另一組連線,你需要查詢 CA 的 DNS,你需要連線到 CA,這對你的網站來說是額外的減速。
HTTPS 不只需要三次往返,你還需要 OCSP。因此,OCSP 裝訂允許伺服器獲取證書未過期的證明。在後臺,獲取這個表示「是的,證書是好的」的 OCSP 響應,然後將它放入握手中。這樣使用者端就不需要實際接觸 CA 並獲取它。
完整 HTTPS 網站存取過程範例如下:
設定了 OCSP Stapling,上文的 5-9
步可以省略,這可以節省約 30% 的存取一個 HTTPS 網站的連線時間。
見上文(4.4 NGINX 設定 HSTS),用 NGINX 也很容易設定。有一個 OCSP Stapling 的指令。裝訂驗證(Stapling verify)是指在裝訂證書之後對其進行驗證。正如我前面(2.2 受信任的 CA 的選項)提到的,使用代理,你必須信任 CA。你可以從 CA 獲得一個檔案,並通過可信證書部分新增到該檔案中。
以上就是設定 NGINX 和 OCSP 裝訂、HSTS 和 SSL 代理的方法。
正如我提到的,在2008年, TLS v1.2 是最新和最好的。近期,他們推出了新版本,TLS v1.3。
HTTPS 是一個不斷變化的領域,我們的設定及最佳實踐可能也需要進行相應調整。
三人行, 必有我師; 知識共用, 天下為公. 本文由東風微鳴技術部落格 EWhisper.cn 編寫.