Apache HTTP Server 版本2.2
這個(gè)問題的解決方案是簡單而且直接的,只是為了給讀者做做練習(xí)。
-- 標(biāo)準(zhǔn)教科書
由于SSL、HTTP、Apache三者共同對請求進(jìn)行處理,這使得在支持SSL的web服務(wù)器上實(shí)現(xiàn)特殊的安全制約變得不那么簡單。本節(jié)介紹了普通情況下的解決方案,作為找出最終方案的第一步。采用這些方案以前,先要盡量地去理解,不了解其限制和相關(guān)性就貿(mào)然使用是最糟糕的了。
可以這樣建立一個(gè)僅使用SSLv2協(xié)議及其密碼算法的服務(wù)器:
SSLProtocol -all +SSLv2
SSLCipherSuite SSLv2:+HIGH:+MEDIUM:+LOW:+EXP
如下設(shè)置為僅使用最強(qiáng)的七種密碼算法:
SSLProtocol all
SSLCipherSuite HIGH:MEDIUM
這個(gè)功能被稱為以服務(wù)器為網(wǎng)關(guān)的加密(Server Gated Cryptography[SGC]),在隨mod_ssl發(fā)布的README.GlobalID
文檔中有詳細(xì)說明。簡單地說就是:服務(wù)器擁有一個(gè)由來自Verisign的一個(gè)特殊的CA證書簽發(fā)的服務(wù)器身份證,從而在對外瀏覽器上實(shí)現(xiàn)高強(qiáng)度加密。其過程如下:瀏覽器使用對外密碼進(jìn)行連接,服務(wù)器返回其全局ID身份證,瀏覽器校驗(yàn)后在后繼HTTP通訊產(chǎn)生之前提升其密碼組,F(xiàn)在的問題是:如何允許這樣的提升,而又強(qiáng)制性地使用高強(qiáng)度加密。換句話說就是:瀏覽器必須在開始連接時(shí)就使用高強(qiáng)度加密,或者提升到高強(qiáng)度加密,但是維持對外密碼是不允許的。以下巧妙地解決了這個(gè)問題:
# 允許在初始握手階段使用所有的密碼,以允許對外服務(wù)器通過SGC功能提升密碼組
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
<Directory /usr/local/apache2/htdocs>
# 但是最終會(huì)拒絕所有沒有提升密碼組的瀏覽器
SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128
</Directory>
顯然,不能使用服務(wù)器全局設(shè)置SSLCipherSuite
,它會(huì)限制密碼為強(qiáng)類型。但是,mod_ssl允許重配置針對目錄的密碼組,并自動(dòng)進(jìn)行一個(gè)帶有服從新配置的SSL參數(shù)的重協(xié)商。因此,其解決方案成了:
# 在一般情況下的處理是寬松的
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
<Location /strong/area>
# 但對于 https://hostname/strong/area/ 及其以下的內(nèi)容要求高強(qiáng)度密碼
SSLCipherSuite HIGH:MEDIUM
</Location>
如果你了解你的用戶群體(比如:一個(gè)封閉的用戶組),正如在一個(gè)Intranet中,則可以使用一般的證書認(rèn)證。所有要做的事情只是,建立由你自己的CA證書簽發(fā)的客戶證書ca.crt
,并依此證書校驗(yàn)客戶。
# require a client certificate which has to be directly
# signed by our CA certificate in ca.crt
SSLVerifyClient require
SSLVerifyDepth 1
SSLCACertificateFile conf/ssl.crt/ca.crt
這又要用到mod_ssl
提供的針對目錄的重配置功能:
SSLVerifyClient none
SSLCACertificateFile conf/ssl.crt/ca.crt
<Location /secure/area>
SSLVerifyClient require
SSLVerifyDepth 1
</Location>
其關(guān)鍵在于對客戶證書的各個(gè)組成部分進(jìn)行驗(yàn)證,一般就是指驗(yàn)證 Distinguished Name (DN) 的全部或部分。有基于mod_auth_basic
和基于SSLRequire
類型的兩種方法以驗(yàn)證。第一種方法適合用于客戶完全屬于不同類型,并為所有客戶建立了密碼數(shù)據(jù)庫的情形;第二種方法適用于客戶都屬于一個(gè)被編碼寫入DN的公共分級的一部分的情形,因?yàn)槠ヅ淇蛻魰?huì)更容易。
第一種方法:
SSLVerifyClient none <Directory /usr/local/apache2/htdocs/secure/area> SSLVerifyClient require SSLVerifyDepth 5 SSLCACertificateFile conf/ssl.crt/ca.crt SSLCACertificatePath conf/ssl.crt SSLOptions +FakeBasicAuth SSLRequireSSL AuthName "Snake Oil Authentication" AuthType Basic AuthBasicProvider file AuthUserFile /usr/local/apache2/conf/httpd.passwd require valid-user </Directory>
/C=DE/L=Munich/O=Snake Oil, Ltd./OU=Staff/CN=Foo:xxj31ZMTZzkVA /C=US/L=S.F./O=Snake Oil, Ltd./OU=CA/CN=Bar:xxj31ZMTZzkVA /C=US/L=L.A./O=Snake Oil, Ltd./OU=Dev/CN=Quux:xxj31ZMTZzkVA
第二種方法:
SSLVerifyClient none <Directory /usr/local/apache2/htdocs/secure/area> SSLVerifyClient require SSLVerifyDepth 5 SSLCACertificateFile conf/ssl.crt/ca.crt SSLCACertificatePath conf/ssl.crt SSLOptions +FakeBasicAuth SSLRequireSSL SSLRequire %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \ and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} </Directory>
假設(shè)Intranet客戶的IP地址是192.160.1.0/24,Intranet站點(diǎn)子區(qū)域的URL是/subarea
,則可以在HTTPS虛擬主機(jī)以外這樣配置(以同時(shí)作用于HTTPS和HTTP):
SSLCACertificateFile conf/ssl.crt/company-ca.crt <Directory /usr/local/apache2/htdocs> # subarea以外的區(qū)域只允許來自Intranet的訪問 Order deny,allow Deny from all Allow from 192.168.1.0/24 </Directory> <Directory /usr/local/apache2/htdocs/subarea> # 在subarea以內(nèi),允許所有來自Intranet的訪問, # 但對來自Internet的訪問,僅允許HTTPS+Strong-Cipher+Password # 或者HTTPS+Strong-Cipher+Client-Certificate # 如果使用了HTTPS,則確保使用高強(qiáng)度加密 # 同時(shí)允許客戶以基本認(rèn)證的形式認(rèn)證 SSLVerifyClient optional SSLVerifyDepth 1 SSLOptions +FakeBasicAuth +StrictRequire SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 # 強(qiáng)制來自Internet的客戶使用HTTPS RewriteEngine on RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.[0-9]+$ RewriteCond %{HTTPS} !=on RewriteRule .* - [F] # 允許網(wǎng)絡(luò)訪問和基本認(rèn)證 Satisfy any # 控制網(wǎng)絡(luò)訪問 Order deny,allow Deny from all Allow 192.168.1.0/24 # HTTP基本認(rèn)證 AuthType basic AuthName "Protected Intranet Area" AuthBasicProvider file AuthUserFile conf/protected.passwd Require valid-user </Directory>