Thursday, April 25, 2024

一個IP地址綁定多個SSL/TLS證書

支持多域名虛擬主機SSL/TLS認證的技術:SNI

早期的SSLv2根據經典的公鑰基礎設施PKI(Public Key Infrastructure)設計,它默認認為:一台服務器(或者說一個IP)只會提供一個服務,所以在SSL/TLS握手時,服務器端可以確信客戶端申請的是哪張證書。

但是讓人萬萬沒有想到的是,虛擬主機大力發展起來了,這就造成了一個IP會對應多個域名的情況。解決辦法有一些,例如申請泛域名證書,對所有*.yourdomain.com的域名都可以認證,但如果你還有一個yourdomain.net的域名,那就不行了。

在HTTP協議中,請求的域名作為主機頭(Host)放在HTTP Header中,所以服務器端知道應該把請求引向哪個域名,但是早期的SSL做不到這一點,因為在SSL握手的過程中,根本不會有Host的信息,所以服務器端通常返回的是配置中的第一個可用證書。因而一些較老的環境,可能會產生多域名分別配好了證書,但返回的始終是同一個。

既然問題的原因是在SSL握手時缺少主機頭信息,那麼補上就是了。

SNI(Server Name Indication)定義在RFC 4366,是一項用於改善SSL/TLS的技術,在SSLv3/TLSv1中被啟用。它允許客戶端在發起SSL握手請求時(具體說來,是客戶端發出SSL請求中的ClientHello階段),就提交請求的Host信息,使得服務器能夠切換到正確的域並返回相應的證書。

要使用SNI,需要客戶端和服務器端同時滿足條件,幸好對於現代瀏覽器來說,大部分都支持SSLv3/TLSv1,所以都可以享受SNI帶來的便利。

附:支持SNI的瀏覽器、服務器、庫

Browsers with support for TLS server name indication

Internet Explorer 7 or later, on Windows Vista or higher. Does not work on Windows XP, even Internet Explorer 8.
Mozilla Firefox 2.0 or later
Opera 8.0 or later (the TLS 1.1 protocol must be enabled)
Opera Mobile at least version 10.1 beta on Android[citation needed] Google Chrome (Vista or higher. XP on Chrome 6 or newer. OS X 10.5.7 or higher on Chrome 5.0.342.1 or newer)
Safari 2.1 or later (Mac OS X 10.5.6 or higher and Windows Vista or higher)
Konqueror/KDE 4.7 or later
MobileSafari in Apple iOS 4.0 or later
Android default browser on Honeycomb or newer
Windows Phone 7[citation needed] MicroB on Maemo

Servers

Apache 2.2.12 or later using mod_ssl(or alternatively with experimental mod_gnutls)
Cherokee if compiled with TLS support
Versions of lighttpd 1.4.x and 1.5.x with patch, or 1.4.24+ without patch
Nginx with an accompanying OpenSSL built with SNI support
LiteSpeed 4.1 or later
Pound 2.6 or later
Apache Tomcat on Java 7 or later
Microsoft Internet Information Server IIS 8

Libraries

Mozilla NSS 3.11.1 client-side only
OpenSSL
0.9.8f (released 11 Oct 2007) – not compiled in by default, can be compiled in with config option ‘–enable-tlsext’
0.9.8j (released 07 Jan 2009) through 1.0.0 (released 29 March 2010) – compiled in by default
GNU TLS
libcurl / cURL since 7.18.1 (released 30 Mar 2008) when compiled against an SSL/TLS toolkit with SNI support
Python 3.2 (ssl, urllib and httplib modules)
Qt 4.8
Oracle Java 7 JSSE

參考資料:
http://blog.hesey.net/2012/02/sni-for-multi-domain-ssl-tls.html
http://serverfault.com/questions/109800/multiple-ssl-domains-on-the-same-ip-address-and-same-port
http://stackoverflow.com/questions/17981341/apache-sni-multiple-ssl-certificates-on-one-ip-address

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.