為您解碼網(wǎng)站建設的點點滴滴
發(fā)表日期:2016-07 文章編輯:小燈 瀏覽次數(shù):2461
編譯自:
[configuring_https_servers][1]
[1]: http://nginx.org/en/docs/http/configuring_https_servers.html
目錄:
配置 HTTPS 服務,必須為 listen 指令加上 ssl 參數(shù),并指定服務器的證書和私鑰:
server { listen443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; ... }
服務器證書將被發(fā)送給每個連接服務器的客戶端。私鑰必須在服務器端保存,應該為私鑰添加嚴格的訪問限制,nginx 主進程必須對其有讀權限。私鑰可以和證書存放在同一個文件中:
ssl_certificate www.example.com.cert; ssl_certificate_key www.example.com.cert;
這個文件當然也應該加上嚴格的權限設置。雖然證書和私鑰被存放在同一個文件中,但只有證書會被發(fā)送給客戶端。
使用 ssl_protocols 指令 和 ss_chiphers 指令,可設置加密連接使用高安全性的協(xié)議版本以及加密性強的算法(SSL/TLS協(xié)議)。nginx 默認使用 “ssl_protocols TLSv1 TLSv1.1 TLSv1.2” 以及 “ssl_ciphers HIGH:!aNULL:!MD5”,它們分別指定了默認的協(xié)議版本和加密算法,所以這些算法不需要顯式地指定。要注意的是,這兩個指令的默認值已經(jīng)多次發(fā)生改變(詳見 “兼容性” 小節(jié))。
[listen][2] 指令
[2]: http://nginx.org/en/docs/http/ngx_http_core_module.html#listen
[server][3] 指令
[3]: http://nginx.org/en/docs/http/ngx_http_core_module.html#server
[server certificate][4] 指令
[4]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate
[private key][5] 指令
[5]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_key
[ssl_protocols][6] 指令
[6]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols
[ss_chiphers][7] 指令
[7]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers
處理 SSL 連接會消耗額外的 CPU 資源。在多處理器系統(tǒng)上,應設置對應CPU核心個數(shù)的 worker 進程。(參考:worker_processes)
建立 SSL 連接的握手階段是最消耗 CPU 的,有兩種方法可最小化建立每個 SSL 連接所需要的握手操作次數(shù):
SSL 連接的會話參數(shù)被保存在 SSL 會話緩存中,該緩存被所有的 worker 進程共享,可使用 ssl_session_cache 指令對其進行配置。1MB SSL 會話可容納約 4000 個會話。
默認的緩存超時為 5 分鐘,可使用 ssl_session_timeout 指令進行調整。
下面是一個 SSL 優(yōu)化配置樣例,假設系統(tǒng)擁有的 CPU 核心總數(shù)為 10個,為其配置 10 MB 的共享會話緩存:
worker_processes auto;http { ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;server { listen443 ssl; server_name www.example.com; keepalive_timeout 70;ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; ...
[ssl_session_cache][9]
[9]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_cache
[ssl_session_timeout][10]
[10]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_timeout
有時會出現(xiàn)這樣的情況,對一個由知名 CA 簽發(fā)的證書,一些瀏覽器發(fā)出警告,而另一些瀏覽器會接受。這是因為簽發(fā)該證書的 CA 使用了一個 intermediate certificate 簽發(fā)證書,這個 intermediate certificate 沒有包含在跟隨瀏覽器一起分發(fā)的證書庫中。為應對這個問題,CA 提供了 a bundle of chained certificate ,可將該證書與你的服務器證書合并成一個文件。在這個文件中,服務器的證書必須位于 chained certificate 的前面:
$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt
使用它作為 ssl_certificate 指令的參數(shù):
server { listen443 ssl; server_name www.example.com; ssl_certificate www.example.com.chained.crt; ssl_certificate_key www.example.com.key; ... }
如果順序顛倒了,把服務器證書放在了 chained certificate 的后面,nginx 不能成功啟動,并且顯示如下錯誤消息:
SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed(SSL: error:0B080074:x509 certificate routines: X509_check_private_key:key values mismatch)
這是因為 nginx 發(fā)現(xiàn)服務器的私鑰和 chained certificate 的第一個證書不匹配造成的。
當瀏覽器收到 intermediate certificates 時,一般都會將它存儲下來。所以瀏覽器可能在第一次收到 intermediate certificates 時發(fā)出警告,但存儲下來之后再次收到時就不會發(fā)出警告了。
要確定一個 web 服務器是否發(fā)送了完整的 certificate chain,可使用 openssl 命令:
$ openssl s_client -connect www.godaddy.com:443 ... Certificate chain0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc/OU=MIS Department/CN=www.GoDaddy.com/serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=079692871 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07969287i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority2 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authorityi:/L=ValiCert Validation Network/O=ValiCert, Inc./OU=ValiCert Class 2 Policy Validation Authority/CN=http://www.valicert.com//emailAddress=info@valicert.com ... Server certificate -----BEGIN CERTIFICATE-----...
在此例中的 Certificate chain 中,#0號證書的對象 (“s”) 的證書頒發(fā)者是 (“i”),#0證書的 (“i”) 同時又是 #1 號證書的對象 (“s”);#1號證書頒發(fā)者 (“i”) 是 #2號證書的對象 (“s”),#2號證書的頒發(fā)者 (“i”) 是知名 CA “ValiCert, Inc”,這個 CA 的證書是存儲在隨瀏覽器分發(fā)的內建證書庫中的。
如果服務器發(fā)送給客戶端的證書沒有包含 certificate chain,上面的信息只會顯示 #0 號服務器證書。
建立一個可同時處理 HTTP 和 HTTPS 請求的 web 服務器:
server { listen80; listen443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ... }Note: nginx 0.7.14 版之前,不支持像上面這樣單獨將某個監(jiān)聽套接字設置為 SSL 連接。 只能在 server 區(qū)塊中使用 ssl {on|off} 指令,定義整個 server 提供 HTTPS 服務, 因此不能設置可同時處理 HTTP/HTTPS 請求的 server 區(qū)塊。現(xiàn)在不建議在新版本的 nginx中使用 ssl 指令,建議使用 ssl 參數(shù)。
基于名稱的 HTTPS 服務器。
子目錄:
如何設置監(jiān)聽于一個 IP 地址的多個 HTTPS 服務器?
server { listen443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ... }server { listen443 ssl; server_name www.example.org; ssl_certificate www.example.org.crt; ... }
雖然在這樣的配置中為兩個 server 設置了不同的證書,但是當使用瀏覽器訪問該 web 站點時,無論訪問的主機名是 www.example.com 還是 www.example.org,瀏覽器都將收到同一個服務器證書:服務器的默認證書。在這里的默認證書是 www.example.com.crt。
這是由 SSL 協(xié)議的行為所決定的。SSL 連接建立于 TCP/IP 連接之上,SSL 連接在握手的階段,會收到由 nginx 服務器發(fā)送的服務器證書,SSL 連接建完成之時,瀏覽器還沒有發(fā)送 HTTP 請求給 nginx,因此 nginx 無法在建立 SSL 連接時得知瀏覽器所請求的是哪一個虛擬主機,因此,nginx 只能發(fā)送默認的服務器證書給瀏覽器。
對于這個問題,最老的方法,也是最 robust 的方法,是為每個 HTTPS 服務設置獨立的 IP 地址:
server { listen192.168.1.1:443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ... }server { listen192.168.1.2:443 ssl; server_name www.example.org; ssl_certificate www.example.org.crt; ... }
有多種方式可實現(xiàn)在多個 HTTPS servers 之間共享一個 IP 地址,但這些方法都有各自的缺點。
一種方法是在證書的 SubjectAltName 字段中設置多個主機名,比如設置兩個主機名:www.example.com 和 www.example.org。缺點是 SubjectAltName 字段的長度是有限制的。
另一種方法是在證書中設置“通配主機名”,比如 *.example.org,但它只能匹配一個名字區(qū)域的主機名,比如,它不能匹配 example.org 和 www.sub.example.org。
以上兩種方法可以結合使用,也就是在證書的 SubjectAltName 字段中同時包含多個 “準確主機名” 和 “通配主機名”。比如同時包含:example.org 和 *.example.org。
對于這種在多個 HTTPS servers 之間共享一個 IP 地址的應用場景,最好在配置中,將服務器的證書和私鑰放到 http 區(qū)塊中,使得所有的 server 區(qū)塊可繼承該配置:
ssl_certificate common.crt; ssl_certificate_key common.key;server { listen443 ssl; server_name www.example.com; ... }server { listen443 ssl; server_name www.example.org; ... }
對于實現(xiàn)在多個 HTTPS servers 之間共享一個 IP 地址,或者說基于同一個 IP 地址運行多個 HTTPS server,一種更為通用的解決方案是使用 TLS Server Name Indication extension (SNI, RFC 6066)。
通過 SNI 可允許瀏覽器在與 web 服務器進行 SSL 握手的階段,將所請求的 server name 傳遞給服務器,這樣服務器就能夠為這個 SSL 連接選擇對應的證書。
但是 SNI 對瀏覽器的版本有要求,目前支持 SNI 的瀏覽器版本如下:
Opera 8.0; MSIE 7.0 (but only on Windows Vista or higher); Firefox 2.0 and other browsers using Mozilla Platform rv:1.8.1; Safari 3.2.1 (Windows version supports SNI on Vista or higher); and Chrome (Windows version supports SNI on Vista or higher, too).Note: 在 SNI 中只能傳遞 domain names(域名)。如果一個訪問請求中包含有 IP 地址, 一些瀏覽器會錯誤地將服務器的 IP 地址當做所請求的主機名傳遞給服務器。因此,不能 完全依賴 SNI。
為了在 nginx 中使用 SNI,要求兩種函數(shù)庫支持 SNI:一是 nginx 編譯時使用的 OpenSSL 庫,二是 nginx 在運行時動態(tài)鏈接的庫。OpenSSL 從 0.9.8f 版開始支持 SNI(要求 OpenSSL 在編譯時使用了 “--enable-tlsext” 選項)。從 0.9.8j 版開始,該選擇是默認的選項。如果 nginx 編譯進了對 SNI 的支持,那么使用 nginx -V 命令查看時,可看到:
$ nginx -V ... TLS SNI support enabled ...
附上譯者的測試:
[root@lamp1 ~]# nginx -V nginx version: nginx/1.10.1 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC) built with OpenSSL 1.0.1e-fips 11 Feb 2013 TLS SNI support enabled ...
如果 SNI-enabled nginx 動態(tài)鏈接不支持 SNI 的 OpenSSL 庫,nginx 將顯示如下警告:
nginx was built with SNI support, however, now it is linked dynamically to an OpenSSL library which has no tlsext support, therefore SNI is not available
從 0.8.21 和 0.7.62 開始,可使用 nginx -V 顯示 SNI 支持狀態(tài)信息。
從 0.7.14 開始,nginx 支持在 listen 指令中使用 ssl 參數(shù),而且在 0.8.21 之前,ssl 參數(shù)只能和 default 參數(shù)一起使用。
從 0.5.32 開始支持 SNI。
從 0.5.6 開始支持 SSL 會話緩存。
從 1.9.1 開始,默認的 SSL 協(xié)議為 TLSv1, TLSv1.1, and TLSv1.2 (if supported by the OpenSSL library)
從 0.7.65, 0.8.19 開始,到 1.9.1 之前,默認的 SSL 協(xié)議為 SSLv3, TLSv1, TLSv1.1, and TLSv1.2 (if supported by the OpenSSL library)。
0.7.64, 0.8.18 及之前,默認的 SSL 協(xié)議為 SSLv2, SSLv3, and TLSv1。
從 1.0.5 開始,默認的 SSL 加密算法為 “HIGH:!aNULL:!MD5”。
0.7.65, 0.8.20 之后,1.0.5 之前,默認的 SSL 加密算法為 “HIGH:!ADH:!MD5”。
0.8.19: 默認的 SSL 加密算法為 “ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM”。
0.7.64, 0.8.18 及之前,默認的 SSL 加密算法為 “ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP”。
written by Igor Sysoev
edited by Brian Mercer
版權信息:
本文編譯自 nginx.org 的部分,遵循其原來的 licence 聲明: 2-clause BSD-like license
日期:2018-04 瀏覽次數(shù):6767
日期:2017-02 瀏覽次數(shù):3441
日期:2017-09 瀏覽次數(shù):3664
日期:2017-12 瀏覽次數(shù):3535
日期:2018-12 瀏覽次數(shù):4829
日期:2016-12 瀏覽次數(shù):4587
日期:2017-07 瀏覽次數(shù):13650
日期:2017-12 瀏覽次數(shù):3517
日期:2018-06 瀏覽次數(shù):4270
日期:2018-05 瀏覽次數(shù):4449
日期:2017-12 瀏覽次數(shù):3562
日期:2017-06 瀏覽次數(shù):3987
日期:2018-01 瀏覽次數(shù):3949
日期:2016-12 瀏覽次數(shù):3918
日期:2018-08 瀏覽次數(shù):4431
日期:2017-12 瀏覽次數(shù):3714
日期:2016-09 瀏覽次數(shù):6411
日期:2018-07 瀏覽次數(shù):3214
日期:2016-12 瀏覽次數(shù):3235
日期:2018-10 瀏覽次數(shù):3389
日期:2018-10 瀏覽次數(shù):3485
日期:2018-09 瀏覽次數(shù):3584
日期:2018-02 瀏覽次數(shù):3602
日期:2015-05 瀏覽次數(shù):3527
日期:2018-09 瀏覽次數(shù):3310
日期:2018-06 瀏覽次數(shù):3437
日期:2017-02 瀏覽次數(shù):3877
日期:2018-02 瀏覽次數(shù):4343
日期:2018-02 瀏覽次數(shù):4179
日期:2016-12 瀏覽次數(shù):3578
Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.