咱們的負載均衡架構是這樣的:nginx
請求 —> 網絡 —> LVS集羣 —> Nginx 集羣 —> APP 瀏覽器
LVS使用FULLNAT模式,每臺Nginx 機器只有一個IP(內網IP),LVS也是把流量轉到這個IP。若是Nginx想對多個域名使用https,好比兩個域名 wandoujia.com 和 wandoulabs.com ,是可能有問題的。服務器
看下面的配置(兩個server寫在不一樣文件中,用 include * 加載):網絡
server {架構
listen 80;負載均衡
listen 443 ssl;orm
server_name test.wandoujia.com;server
ssl_certificate wandoujia.crt;ip
ssl_certificate_key wandoujia.key;ssl
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
server {
listen 80;
listen 443 ssl;
server_name test.wandoulabs.com;
ssl_certificate wandoulabs.crt;
ssl_certificate_key wandoulabs.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
這樣你訪問 https://test.wandoujia.com 或者 https://test.wandoulabs.com,均可能報證書有問題,這是爲何。
事實上,SSL運行在TCP之上(SSL/TLS協議),ssl經過四次握手 和服務器(這裏是Nginx,LVS純轉發,可忽略)的IP + PORT(443)創建ssl鏈接,創建鏈接以後瀏覽器纔會發送HTTP請求。因此在Nginx收到HTTP請求以後才知道Host,才知道轉到哪一個server 去處理,因此在SSL鏈接創建的時候Nginx是不知道用哪一個 Server 的SSL配置的,在這種狀況下,Nginx會使用它加載到的第一個SSL配置(需驗證)。固然若是你在listen 443的後面加上 default_server,Nginx就會使用此SSL配置,即:
listen 443 default_server ssl;
那麼對於單域名的https,我更喜歡把SSL配置寫在http配置裏,在server只須要加上 listen 443 ssl;,相似:
http {
...
ssl_certificate wandoujia.crt;
ssl_certificate_key wandoujia.key;
#ssl_certificate wandoulabs.crt;
#ssl_certificate_key wandoulabs.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
server {
listen 80;
listen 443 ssl;
server_name test.wandoujia.com;
...
}
#server {
# listen 80;
# listen 443 ssl;
# server_name test.wandoulabs.com;
# ...
#}
那麼怎麼才能實現多域名的 https 呢,是有辦法的,叫作 TLS Server Name Indication extension(SNI, RFC 6066),它容許瀏覽器在SSL握手的時候發送請求的server name,也就是 Host,這樣 Nginx 就能找到對應server 的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).
一樣,在服務器端 openssl 要支持SNI,編譯的時候加上–enable-tlsext 便可,不過從 0.9.8j 版本開始編譯的時候默認會加。openssl 支持了SNI,Nginx 才能夠work,確認是否OK:
$ ./nginx -V
...
TLS SNI support enabled
...
因此,若是想要實現多域名https,要確認你的Nginx 支持 TLS SNI support,而後在server 單獨配置SSL, 可是要注意,某些瀏覽器會有問題,並且由於Nginx加載server 的順序不一樣(特別是每一個server在同一目錄的不一樣文件中,而後在nginx.conf主配置文件中用 include * 包含),可能會出現奇怪的問題,我是遇到過的。