在 IIS 上調試客戶端證書問題
我們設置了一個 2008R2 IIS 伺服器,其中一個站點配置為需要客戶端證書。我們的測試客戶端不工作,我們正在嘗試調試原因。
在此過程中,我們設置了一個新的 Server 2008 R2 機器(是的,我知道它很舊,但這是執行該軟體的機器)來嘗試複製或確定排除故障的方法。
我們正在研究的一種方法是 TLS 握手。測試應用程序是用 .NET 編寫的,並且
System.Diagnostics
啟用了適當的調試,這會將以下條目放在日誌文件中:System.Net 資訊:0:
$$ 22724 $$SecureChannel#48979325 - 我們有使用者提供的證書。伺服器已指定 10 個頒發者。尋找與任何頒發者匹配的證書。
我們看不到這個發行者列表,所以我們破解了 OpenSSL。執行以下命令:
openssl s_client -connect win2k8r2-1.hsl10690.test:443 -state -no_ticket -servername win2k8r2-1.hsl10690.test
導致輸出表明:
[...] -----END CERTIFICATE----- subject=/CN=testcert.hsl10690.test issuer=/CN=Internal Dev CA 1 --- No client certificate CA names sent --- SSL handshake has read 1013 bytes and written 329 bytes [...]
所以我們有一個不匹配的地方,微軟堆棧聲明伺服器指定了 10 個頒發者,但 OpenSSL 報告伺服器沒有發送任何 CA 名稱。
對於實時系統,System.Diagnostics 日誌報告伺服器指定的 130 多個頒發者,但 OpenSSL 仍然返回零。
我們認為問題在於我們提供的客戶端證書與其中一個頒發者不匹配(但我們已經驗證了根在伺服器的信任庫中,並且我們已經在伺服器之外驗證了證書)。在實時伺服器上,我們在“伺服器已指定… ”消息之後的日誌中看到了這一點:
System.Net Information: 0 : [36484] SecureChannel#33675143 - We have user-provided certificates. The server has specified 133 issuer(s). Looking for certificates that match any of the issuers. ProcessId=20372 DateTime=2018-12-20T13:33:39.9042036Z System.Net Information: 0 : [36484] SecureChannel#33675143 - Left with 0 client certificates to choose from. ProcessId=20372 DateTime=2018-12-20T13:33:39.9052036Z
在進行測試時,如果一切正常,它會說:
System.Net Information: 0 : [22724] SecureChannel#48979325 - We have user-provided certificates. The server has specified 10 issuer(s). Looking for certificates that match any of the issuers. ProcessId=22100 DateTime=2018-12-21T13:52:23.3718249Z System.Net Information: 0 : [22724] SecureChannel#48979325 - Selected certificate: [Version] V3 [Subject]
我們如何找出伺服器返回了哪些證書,如果我們發現頒發者從列表中失去,是什麼阻止了根被包含在內?我不排除我們錯過了一些明顯的東西,但我們還沒有看到它。
我們終於找到了答案:錯誤是 KB931125。一篇部落格文章將 KB 描述為僅用於客戶端目標,但被發送到伺服器,導致 IIS 發送的 CA 列表被截斷。它並沒有真正解釋為什麼我們無法使用 OpenSSL 看到傳輸的 CA 列表,但最終它確實讓我們找到了根本原因。
部落格文章指向另一篇 MSDN 文章,該文章更詳細地描述了該問題:
如果 TLS/SSL 伺服器在受信任的根證書列表中包含許多條目,則可能會出現這些問題。如果滿足以下條件,伺服器將向客戶端發送受信任的證書頒發機構列表:
- 伺服器使用傳輸層安全 (TLS)/SSL 協議來加密網路流量。
- 在身份驗證握手過程中需要客戶端證書進行身份驗證。
此受信任證書頒發機構列表表示伺服器可以接受客戶端證書的頒發機構。要由伺服器進行身份驗證,客戶端必須具有證書鏈中存在的證書到伺服器列表中的根證書。這是因為客戶端證書始終是鏈末端的最終實體證書。客戶端證書不是鏈的一部分。
目前,在 Windows Server 2008、Windows Server 2008 R2 和 Windows Server 2012 中,Schannel 安全包支持的受信任證書頒發機構列表的最大大小為 16 KB。
還記錄了一個事件日誌條目,上面寫著(我們第一次看到這個時錯過了):
當請求客戶端身份驗證時,此伺服器會向客戶端發送受信任的證書頒發機構列表。客戶端使用此列表來選擇伺服器信任的客戶端證書。目前,該伺服器信任的證書頒發機構太多,以至於列表變得太長。因此,此列表已被截斷。這台機器的管理員應該審查信任的證書頒發機構進行客戶端身份驗證,並刪除那些實際上不需要信任的證書頒發機構。
MSDN 文章確實列出了一個修復:
刪除以下系統資料庫項:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\Certificates
為此,請按照下列步驟操作:
- 啟動系統資料庫編輯器
- 找到以下系統資料庫子項:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\AuthRoot
- 右鍵點擊然後刪除名為“證書”的密鑰