Networking

來自網關 VM 的神秘“需要分段”拒絕

  • June 23, 2015

我一直在解決一個嚴重的 WAN 速度問題。我修復了它,但為了他人的利益:

通過 WireShark、記錄和簡化配置,我將其範圍縮小到一些奇怪的行為,從網關執行 DNAT 到內部網路上的伺服器。網關(一個 CentOS 機器)和伺服器都在同一個 VMware ESXi 5 主機上執行(事實證明這很重要)。

這是發生的一系列事件 - 非常一致 - 當我嘗試使用直接連接到網關 WAN 端的測試客戶端從 DNAT 後面的 HTTP 伺服器下載文件時(繞過此處通常使用的實際 Internet 連接) :

  1. 通常的TCP連接建立(SYN、SYN ACK、ACK)正常進行;網關正確地重新映射伺服器的 IP 雙向。
  2. 客戶端使用 HTTP GET 發送單個 TCP 段,這也被正確地 DNATted 到目標伺服器。
  3. 伺服器通過網關發送一個 1460 字節的 TCP 段,其中包含 200 響應和部分文件。線路上的幀大小為 1514 字節 - 有效負載為 1500。該段應該穿過網關,但沒有。
  4. 伺服器通過網關發送第二個 1460 字節 TCP 段,繼續文件。同樣,連結有效負載為 1500 字節。該段也不會越過網關,並且永遠不會被考慮在內。
  5. 網關將 ICMP 類型 3 程式碼 4(目標不可達 - 需要分段)數據包發送回伺服器,引用事件 3 中發送的數據包。ICMP 數據包指示下一跳 MTU 為 1500。 這似乎是無意義的,因為網路是 1500 字節的干淨,並且 3 和 4 中的連結有效負載已經在規定的 1500 字節限制內。伺服器可以理解地忽略此響應。(最初,ICMP 已被過度使用的防火牆丟棄,但已修復。)
  6. 經過相當長的延遲(在某些配置中,從伺服器重複 ACK),伺服器決定重新發送來自事件 3 的段,僅此一次。除了 IP 標識欄位和校驗和之外,該幀與事件 3 中的幀相同。它們的長度相同,新的幀仍然設置了 Don’t Fragment 標誌。 然而,這一次,網關很高興地將段傳遞給客戶端 - 一個片段 - 而不是發送 ICMP 拒絕。
  7. 客戶端對此進行確認,然後傳輸繼續,儘管速度非常緩慢,因為後續段經歷了大致相同的模式,即被拒絕、超時、重新發送然後通過。

如果客戶端移動到區域網路,可以直接訪問伺服器,客戶端和伺服器就可以正常工作。

這種奇怪的行為會因目標伺服器看似無關的細節而發生不可預測的變化。

例如,在 Server 2003 R2 上,如果啟用了 Windows 防火牆(即使它允許 HTTP 和所有 ICMP),7MB 的測試文件將需要超過 7 小時的時間來傳輸,而問題根本不會出現,而且自相矛盾的是,拒絕永遠不會如果 Windows 防火牆被禁用*,則首先由網關發送。*另一方面,在 Server 2008 R2 上,禁用 Windows 防火牆沒有任何影響,但傳輸雖然仍然受到損害,但比啟用防火牆的 Server 2003 R2 上的傳輸速度要快得多。(我認為這是因為 2008 R2 使用了更智能的超時啟發式算法和 TCP 快速重傳。)

更奇怪的是,如果在目標伺服器上安裝了 WireShark,問題就會消失。因此,為了診斷問題,我必須在單獨的 VM 上安裝 WireShark 以觀察 LAN 端的網路流量(出於其他原因,這可能是一個更好的主意。)

ESXi 主機版本為 5.0 U2。

我終於明白了這一點。原來這是 VMware 在目標伺服器的虛擬 NIC 中實現 TCP 分段解除安裝的問題。

伺服器的 TCP/IP 堆棧會向 NIC 發送一個大塊,期望 NIC 將其分解為受限於鏈路 MTU 的 TCP 段。但是,VMware 決定將其保留在一個很大的部分,直到 - 好吧,我不確定什麼時候。

當它到達網關 VM 的 TCP/IP 堆棧時,它似乎實際上停留了一大段,這引發了拒絕。

一個重要的線索隱藏在生成的 ICMP 數據包中:被拒絕數據包的 IP 標頭指示大小為 2960 字節 - 比它似乎正在拒絕的實際數據包大得多。如果它結合了迄今為止發送的兩個段的數據,這也正是一個 TCP 段線上路上的大小。

使問題難以診斷的一件事是,傳輸的數據實際上被分割成1500 字節的幀,而 WireShark 在另一個 VM 上執行(連接到一個單獨的混雜埠組上的同一個 vSwitch)可以看到。我真的不確定為什麼網關 VM 看到一個數據包,而 WireShark VM 看到兩個。FWIW,網關沒有啟用大接收解除安裝 - 我可以理解是否啟用。WireShark VM 執行的是 Windows 7。

我認為 VMware 延遲分段的邏輯是,如果數據要從物理 NIC 流出,則可以利用 NIC 的實際硬體解除安裝。然而,在發送到另一個 VM 之前,它似乎無法分割,並且在這方面不一致。我已經看到其他地方提到的這種行為是一個 VMware 錯誤。

解決方案只是關閉目標伺服器中的 TCP 分段解除安裝。該過程因作業系統而異,但fwiw:

在 Windows 中,在連接的屬性、正常選項卡或網路選項卡上,點擊適配器旁邊的“配置…”,然後查看高級選項卡。對於 Server 2003 R2,它以“IPv4 TCP 分段解除安裝”的形式給出。對於 Server 2008 R2,它是“大型發送解除安裝 (IPv4)”。

該解決方案有點雜亂無章,並且可能會影響某些環境中的性能,因此我仍然會接受任何更好的答案。

您不能刪除需要 ICMP 分段的消息。它們是 pMTU 發現所必需的,這是 TCP 正常工作所必需的。請 LART 防火牆管理員。

根據透明規則,充當防火牆的包過濾路由器允許設置了不分段 (DF) 位的傳出 IP 包,不得阻止傳入的 ICMP 目標不可達/需要分段錯誤,以響應出站包到達防火牆內的主機,因為這會通過生成合法流量的主機破壞符合標準的路徑 MTU 發現使用。– 防火牆要求 - RFC2979(重點在原文)

十多年來,這種配置一直被認為從根本上被破壞了。ICMP 不是可選的。

引用自:https://serverfault.com/questions/500448