想要配置一個HTTPS服務器吃嘿,必須啟用在server塊中l(wèi)isten端口的ssl礼殊,同時使用server_certificate和private_key指令指定相關文件浇垦。
server {
listen 443 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的master進程是可讀取的谚赎。私鑰可以與證書交替存儲在同一個文件中。
ssl_certificate www.example.com.cert;
ssl_certificate_key www.example.com.cert;
在這種情況下诱篷,文件訪問權限也應該受到限制壶唤。盡管證書和密鑰存儲在一個文件中,但只有證書被發(fā)送到客戶機棕所。
指令ssl_protocols和ssl_ciphers可以用來限制連接只包括SSL/TLS的強版本和加密算法闸盔。默認情況下,nginx使用ssl_protocols TLSv1 TLSv1.1 TLSv1.2
和ssl_ciphers HIGH:!aNULL:!MD5
橙凳,所以沒必要顯示配置他們蕾殴,但是要注意nginx的不同版本他們對應的默認值可能是不一樣的。下面會講到岛啸。
HTTPS服務器性能優(yōu)化
SSL操作會消耗CPU資源钓觉,其中,SSL握手最為突出坚踩。因此荡灾,要提高HTTPS服務器的性能,就要最小化每個客戶端連接SSL操作的次數(shù)瞬铸。nginx對此有兩種應對方式批幌。
- 啟用keepalive,使得通過一個連接可以發(fā)送多個請求嗓节,而不是一個連接一個請求
- 重用ssl session荧缘,對于并行和后續(xù)連接,避免SSL握手
ssl_session_cache
ssl_session_timeout 默認5m
worker_processes auto;
http {
# shared 在worker進程間共享
# SSL
# 10m/10M 10兆內(nèi)存空間(megabyte)
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server {
listen 443 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中間證書
對于由知名證書頒發(fā)機構簽署的證書拦宣,有的瀏覽器可能會不認同截粗,有的瀏覽器會毫無問題地接受。出現(xiàn)這種情況是因為中間證書鸵隧,頒發(fā)機構使用中間證書對服務器證書進行了簽名绸罗,而中間證書不在已知受信任證書頒發(fā)機構的證書庫中。為了解決這種問題豆瘫,頒發(fā)機構提供了一組鏈接的證書珊蟀,這些證書鏈接已簽名的服務器證書。如下命令外驱,服務器證書必須出現(xiàn)在鏈接證書之前育灸。
$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt
如果服務器證書在鏈接證書之后腻窒,nginx會啟動失敗,并展示以下錯誤信息磅崭。
SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
(SSL: error:0B080074:x509 certificate routines:
X509_check_private_key:key values mismatch)
生成的文件應作為ssl_certificate指令的參數(shù)定页。
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.chained.crt;
ssl_certificate_key www.example.com.key;
...
}
一個HTTP/HTTPS服務器例子
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
...
}
基于名稱的HTTPS服務器
當在一個ip地址上配兩個或兩個以上的HTTPS服務器,會出現(xiàn)一個常見的問題绽诚。
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
使用這個配置,客戶端不管請求的域名是www.example.com
還是www.example.org
杭煎,只會收到www.example.com.crt
證書恩够。因為在建立SSL連接的時候,服務器名稱是未知的羡铲,這種情況下蜂桶,IP地址一樣,nginx會選擇一個默認服務器也切,也就是第一個扑媚,來處理請求,所以客戶端收到的總是第一個服務器的證書雷恃〗桑可以通過配置不同IP地址來規(guī)避這個問題。
server {
listen 192.168.1.1:443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 192.168.1.2:443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
除此之外倒槐,解決方法還有擁有多個域名的證書和SNI(Server Name Indication)
可以匹配多個域名的證書
- 擁有多個全稱域名的證書
全稱域名的長度是有限制的
# 這種證書旬痹,可以提升作用域,不必寫在server里
ssl_certificate common.crt;
ssl_certificate_key common.key;
server {
listen 443 ssl;
server_name www.example.com;
...
}
server {
listen 443 ssl;
server_name www.example.org;
...
}
- 通配符域名證書
與在服務器名稱中講的不一致讨越,這里的通配符只能匹配一個部分两残。比如*.example.org,只能匹配www.example.org
把跨,而不能匹配example.org
或者www.sub.example.org
人弓。
SNI(Server Name Indication)
SNI允許在SSL握手的時候,客戶端傳遞一個服務器名稱給服務器着逐。這種情況下崔赌,即使多個HTTPS服務器使用同一個IP,只要服務器名稱不同滨嘱,nginx就知道使用哪個服務器了峰鄙。這是一種更常用的解決方法。現(xiàn)在大多數(shù)瀏覽器都支持SNI太雨。
注意:SNI只傳遞域名吟榴,不應該是IP
為了在nginx中使用sni,必須在構建nginx二進制文件的openssl庫以及在運行時動態(tài)鏈接到的庫中都支持它囊扳。OpenSSL從0.9.8f版本開始支持SNI吩翻,前提OpenSSL使用配置選項 --enable-tlsext
構建兜看。自從0.9.8j這個配置選項是默認的。如果nginx是支持SNI的狭瞎,使用 nginx -V
如下细移。
$ nginx -V
...
TLS SNI support enabled
...
但是,如果支持SNI的nginx動態(tài)鏈接的OpenSSL庫不支持SNI熊锭,將會有如下警告弧轧。
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.7.14 開始支持在listen指令中指定ssl參數(shù)
- 0.5.23 開始支持SNI
- 0.5.6 開始支持shared SSL session cached
- 1.9.1 開始默認的SSL協(xié)議是TLSv1, TLSv1.1, and TLSv1.2(如果由OpenSSL支持)
- 0.7.65,0.8.19以后碗殷,默認的SSL協(xié)議是 SSLv3, TLSv1, TLSv1.1, and TLSv1.2(如果由OpenSSL支持)
- 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之后代乃,默認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