OS X 網路堆棧忽略 IGMP 成員資格查詢
我們有一個遠端站點,Mac 沒有響應IGMP 成員資格查詢,但 Windows 框會響應。因此,大約 10 分鐘後,支持 IGMP 的網路交換機會切斷到 Mac 的多播流。
這是 Wireshark 的螢幕截圖,顯示了該問題:
第一個數據包是應用程序請求網路開始允許從 239.255.20.1 到 Mac 的 IGMP 數據包。然後您會看到,此後大約每 125 秒,配置為 IGMP 查詢器 (10.1.254.254) 的網路交換機會詢問我們是否仍然對該流感興趣。注意明顯缺乏回應。
以下是本地網路上發生的情況,用於比較:
在這裡,大約每 95 秒,IGMP 查詢器 (172.20.0.2) 會詢問我們是否還需要該流,而相關的 Mac (172.20.0.144) 會說:“是的,繼續發送它。”
防火牆在 GUI 中的問題 Mac 上已關閉,我已在命令行中對其進行了驗證:
$ /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 防火牆被禁用。(狀態 = 0) $ /usr/libexec/ApplicationFirewall/socketfilterfw --getblockall 阻止所有禁用! $ /usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode 隱身模式已禁用 $ /usr/libexec/ApplicationFirewall/socketfilterfw --getappblocked /Applications/mumblemutter.app/... 該應用程序不是防火牆的一部分
應用程序無關緊要,因為堆棧會在組加入後處理 IGMP 查詢。
問題 Mac 正在執行 10.11.5,但我不敢相信通過升級到絕對最新版本可以解決問題,因為這意味著基於 BSD 的作業系統在 2016 年正在修復其網路堆棧中的嚴重錯誤。可能,但非常低機率。
問題出現在第一個數據包擷取中,您會注意到 IGMP 組加入數據包是 IGMPv2 數據包,但來自 IGMP 查詢器的響應都是 v3。
這看起來不錯,因為 macOS 已經支持 IGMPv3 很長時間了,但是如果你深入研究 Darwin 開源核心中的 IGMP 實現,
igmp_input_v3_query()
你會發現這段程式碼很有啟發性:/* * Discard the v3 query if we're in Compatibility Mode. * The RFC is not obviously worded that hosts need to stay in * compatibility mode until the Old Version Querier Present * timer expires. */ if (igi->igi_version != IGMP_VERSION_3) { ...etc...
這意味著 macOS 遵守IGMPv3 規範,並將任何看到 IGMPv2 數據包的網路介面置於“兼容模式”,這意味著它既不會確認 IGMPv3 數據包,也不會在該網路介面上使用 IGMPv3。就上面的程式碼而言,將介面標記為
igi_version = 2
,所以我們將打這個測試並忽略 v3 組成員資格查詢,因為在這個網路上說 v3 是不安全的理論,以免 v2 設備無法理解什麼是繼續。我看到了三種可行的補救措施:
- 讓負責網路的人員重新配置他們的交換機,以將 IGMPv2 查詢發送回請求 IGMPv2 組加入的客戶端。
- 完全關閉 IGMP 感知網路交換機中的 IGMPv3 支持,以便它們僅發送 IGMPv2 成員資格查詢。
- 監控網路中的 IGMPv2 數據包,找到它們的來源,並修復、升級或刪除它們。如果無法使網路直通 v3,請使用 #1 或 #2。
這不是您可以通過更改應用程式碼來解決的問題。該
IP_ADD_MEMBERSHIP
選項不setsockopt()
包含版本號,因此該應用無法要求 IGMPv3。這個決定取決於堆棧。雖然可能存在會影響這一點的作業系統設置,但只有在 macOS IGMP 實現與我們在
igmp.c
上面連結中看到的不同時才會出現這種情況。如果您在 Windows 機器上嗅探網路的 IGMP,您將看到它以 v3 響應響應 IGMPv3 成員資格查詢,儘管網路上存在 v2。因此,它違反了 RFC;雖然一些網路管理員會說,“好吧,它有效,不是嗎?”正確的回應必須是因為你不能強迫 macOS 也無視 RFC,解決方案仍然是修復網路。