不常見的遠端主機已強制關閉連線

TLS 握手:Server Hello & Client Hello

遠端主機已強制關閉一個現存的連線

Server A 一直有一隻運行的很正常的 API 提供給 Server B 和 Server C 呼叫,在某一天忽然 Server B 就呼叫失敗了,同一時間 Server C 以及我的 local 環境仍然可以正常使用那隻 API。查看 Server B log 後發現顯示的錯誤是:

1
2
基礎連接已關閉: 傳送時發生未預期錯誤,遠端主機已強制關閉一個現存的連線。
The underlying connection was closed: An unexpected error occurred on a send.

由於是比較古老的服務了,最近一段時間都沒有修改過兩邊的程式碼,所以先排除了改壞了的可能性。把錯誤訊息拿去 google 後,看到通常是因為終止 TLS 1.0、1.1 的服務所導致,只要加上這段程式碼就可以運行了:

1
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Client Hello & Server Hello

剛好最近重新拾起網路協定的相關書籍閱讀中,書裡有一些使用 Wireshark 的範例,抱持著將就試試看的心態,就打開了 Wireshark 來研究看看到底從我 local 端發送出去的請求和 Server B 到底有甚麼不同。

左邊為 local 端,右邊為 Server B

從上面這張截圖的比較可以看到,左邊 local 端有出現 Client Hello 和 Server Hello,但右邊 Server B 卻只出現了 Client Hello。但這兩個互相說哈囉的東西是什麼?

TLS 交握

在網際網路的事件中,應該很多人都聽說過三項交握,全名應該是 TCP 三項交握(TCP Three-Way Handshake),透過這個過程建立連線。

但是這個連線建立後是沒有加密的狀態,因此要透過 TLS 交握 來確保雙方能安全地交換加密金鑰,並確定加密的協定版本和加密算法。詳細的步驟是:

  1. 客戶端發送 ClientHello 訊息,告知伺服器客戶端這邊支援的 TLS 版本以及密碼套件。
  2. 伺服器回應 ServerHello 訊息,選擇使用的加密算法和協定版本,並傳送伺服器證書等資訊來證明身份。
  3. 雙方交換加密金鑰和一些安全參數,完成加密通訊的準備。
  4. 客戶端和伺服器確認所有訊息交換無誤後,TLS 握手結束,通信開始進入加密的數據傳輸階段。

由於 TLS 的目的就是確保資料在傳輸過程中的機密性、完整性及身份驗證,只要有一個步驟缺失就代表無法建立安全的連線,因此連線就被中斷。從剛剛的截圖可以看到 Server B 確實沒有等到 ServerHello 的訊息,為了確定是不是這個問題,我決定要分別看看這三台 Server 的 TLS 版本以及密碼套件有哪些。

檢查允許的密碼套件:Qualys Labs

Qualys Labs 這個網站主要是針對 SSL 安全性做的掃描,掃描出的內容剛好包含我們所需要的密碼套件清單。操作的方式也很簡單:

1. 點選 Test your server

2. 在中間的 Hostname 輸入你想測試的網站

3. 選擇它掃描後的你的主機 IP,進去看報告

4. 往下滑,找到 Cipher Suites 的區塊,這邊就是這台 server 可用的密碼套件清單

透過這個網站的比對,我確定了這次 Server B 遇到的問題:由於那陣子剛做完弱點掃描,Server A 被掃出了 Weak SSL Protocol 的問題,所以我使用 IIS Crypto 把一些不安全的過時協議關閉,但 Server B 太過古老,沒辦法支援新的協議,這就導致了這次的問題,Server B 只能使用不安全的密碼套件,但 Server A 不允許使用,在沒辦法挑出可用套件的情況下,自然也就沒辦法回覆 ServerHello 的訊息。

參考資料

Built with Hugo
Theme Stack designed by Jimmy