Nginx 單IP下 配置多個server https 的問題


咱們的負載均衡架構是這樣的: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 * 包含),可能會出現奇怪的問題,我是遇到過的。

相關文章
相關標籤/搜索