在以前, 由於加密方法運作上的限制, 要設定HTTPS一定要佔用一個IP. 後來出現了 Server Name Indication (SNI), 讓多個HTTPS網站能夠共用一個IP. 這邊稍微紀錄一下個人練習的過程.
要讓Apache啟用SNI, 有幾個必要條件:
Server 端:
- 至少需使用 OpenSSL 0.9.8f 及更新的版本
- OpenSSL 需要有啟用 TLS Extension
- Apache 編譯時需要使用上面提到的 OpenSSL, mod_ssl 將會自動偵測並啟用 SNI.
- Apache 執行時也需要使用到上面的 OpenSSL
Client 端:
- 瀏覽器需要有支援 SNI, 大部分常見的瀏覽器其實都有支援了, Firefox, Chrome, Opera, Safari都沒問題
- 但是, 該死的IE需要搭配Vista以上的系統才有支援, 而且需要IE7以上的版本
- 注意一點, IE8 跑在 Windows XP 也是沒有支援 SNI 的, 一定要 Vista 以上 搭配 IE7 以上
這次練習用的環境是:
- FreeBSD 9.0-RELEASE-p3
- Apache 2.2.22
- OpenSSL 0.9.8q
其中 OpenSSL 是 FreeBSD 預設就有的, 所以其實系統一裝好就可以使用, 並不需要額外的設置.
安裝 Apache:
1 2 |
cd /usr/ports/www/apache22 make install clean |
增加這一行到 /etc/rc.conf :
1 |
apache_enable="YES" |
修改 /usr/local/etc/apache22/httpd.conf, 在最後面找到這行並取消註解:
1 |
Include etc/apache22/extra/httpd-ssl.conf |
最後, 修改 httpd-ssl.conf , 大部分都是沿用原本的設定就可以了, 比較需要注意的就是這兩個指令:
- NameVirtualHost , 原本的 httpd-ssl.conf 裡面沒有啟用虛擬網站, 少了這一個設定, 永遠只會連到第一個站台去.
- SSLStrictSNIVHostCheck , 針對不支援 SNI 的瀏覽器, 將此選項設為off, 則會讓瀏覽器連到第一個站台去
以下是 /usr/local/etc/apache22/extra/httpd-ssl.conf 的內容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
Listen 443 AddType application/x-x509-ca-cert .crt AddType application/x-pkcs7-crl .crl SSLPassPhraseDialog builtin SSLSessionCache "shmcb:/var/run/ssl_scache(512000)" SSLSessionCacheTimeout 300 SSLMutex "file:/var/run/ssl_mutex" SSLStrictSNIVHostCheck off NameVirtualHost *:443 <VirtualHost *:443> DocumentRoot "/usr/local/www/apache22/data/1" ServerName site1.myurl.net ServerAdmin you@example.com ErrorLog "/var/log/httpd-error.log" TransferLog "/var/log/httpd-access.log" SSLEngine on SSLProtocol all -SSLv2 SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5 SSLCertificateFile "/usr/local/www/apache22/ssl/site1.crt" SSLCertificateKeyFile "/usr/local/www/apache22/ssl/site1.key" <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> <Directory "/usr/local/www/apache22/cgi-bin"> SSLOptions +StdEnvVars </Directory> BrowserMatch "MSIE [2-5]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 CustomLog "/var/log/httpd-ssl_request.log" \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" </VirtualHost> <VirtualHost *:443> DocumentRoot "/usr/local/www/apache22/data/2" ServerName site2.myurl.net:443 ServerAdmin you@example.com ErrorLog "/var/log/httpd-error.log" TransferLog "/var/log/httpd-access.log" SSLEngine on SSLProtocol all -SSLv2 SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5 SSLCertificateFile "/usr/local/www/apache22/ssl/site2.crt" SSLCertificateKeyFile "/usr/local/www/apache22/ssl/site2.key" <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> <Directory "/usr/local/www/apache22/cgi-bin"> SSLOptions +StdEnvVars </Directory> BrowserMatch "MSIE [2-5]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 CustomLog "/var/log/httpd-ssl_request.log" \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" </VirtualHost> |
看得出來其實並沒有多花什麼功夫, 就成功的啟用 SNI 了. 最後開啟瀏覽器, 輸入網址看看是否兩個站的首頁都正確的顯示, 就完成嘍.
參考資料: