web-dev-qa-db-ja.com

ゲートウェイからの不可解な「フラグメンテーションが必要」拒否VM

私は深刻なWAN=速度の問題をトラブルシューティングしてきました。私はそれを修正しましたが、他の人のために:

WireSharkを使用して、ログを記録し、構成を簡略化することで、DNATを実行するゲートウェイから内部ネットワーク上のサーバーへの奇妙な動作に絞り込みました。ゲートウェイ(CentOSボックス)とサーバーの両方が同じVMware ESXi 5ホストで実行されている(これは重要であることが判明)。

ゲートウェイのWAN=側に直接接続されたテストクライアントを使用して、DNATの背後にあるHTTPサーバーからファイルをダウンロードしようとしたときに、非常に一貫して発生した一連のイベントは次のとおりです(ここで通常使用される実際のインターネット接続をバイパスします):

  1. 通常のTCP接続の確立(SYN、SYN ACK、ACK))は正常に行われ、ゲートウェイはサーバーのIPを双方向で正しく再マップします。

  2. クライアントは単一のTCPセグメントをHTTP GETで送信し、これもターゲットサーバーに正しくDNATされます。

  3. サーバーはゲートウェイを介して1460バイトTCPセグメントに200応答とファイルの一部を送信します。ワイヤ上のフレームのサイズは1514バイト-ペイロードで1500です。このセグメントはゲートウェイを通過しますが、通過しません。

  4. サーバーは2番目の1460バイトを送信しますTCPセグメント、ファイルをゲートウェイ経由で続行します。ここでも、リンクのペイロードは1500バイトです。このセグメントもゲートウェイを通過せず、考慮されません。 。

  5. ゲートウェイは、イベント3で送信されたパケットを引用して、ICMPタイプ3コード4(宛先到達不能-断片化が必要)パケットをサーバーに送り返します。ICMPパケットは、ネクストホップMTUが1500であることを示します。これは無意味に見える、ネットワークは1500バイトでクリーンであり、リンクペイロードは3および4であるすでに指定された1500バイトの制限内にあった。サーバーは当然この応答を無視します。 (元々、ICMPは熱狂的なファイアウォールによってドロップされていましたが、これは修正されました。)

  6. かなりの遅延(および一部の構成では、サーバーからのACKの重複)の後、サーバーは、今回のみ、イベント3からセグメントを再送信することを決定します。 IP識別フィールドとチェックサムを除いて、フレームはイベント3のものと同じです。これらは同じ長さと新しいものまだDo n't Fragmentフラグが設定されています。ただし、今回は、ゲートウェイはICMP拒否を送信する代わりに、セグメントを1つのピースとしてクライアントに転送します。

  7. クライアントはこれにACKを送信し、転送は続行されますが、非常にゆっくりとですが、後続のセグメントはほぼ同じパターンで拒否され、タイムアウトし、再送信されてから通過するためです。

クライアントをサーバーに直接アクセスできるようにLANに移動すると、クライアントとサーバーは正常に連携します。

この奇妙な動作は、ターゲットサーバーの見たところ無関係な詳細に基づいて予期せず変化します。

たとえば、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です。

5
Kevin

ようやくこれの底に着きました。これは、ターゲットサーバーの仮想TCPでのセグメンテーションオフロードのNICセグメンテーションオフロードの実装です。

サーバーのTCP/IPスタックは、NICがこれをTCPセグメントのリンクに制限されたセグメントに分割することを期待しています。 MTUただし、VMwareはこれを1つの大きなセグメントに残すことを決定しました。

ゲートウェイVMのTCP/IPスタックに到達したときに、実際には1つの大きなセグメントに留まり、拒否を引き起こしたようです。

重要な手掛かりが結果のICMPパケットに埋め込まれました。拒否されたパケットのIPヘッダーは2960バイトのサイズを示しました-拒否されているように見える実際のパケットよりもはるかに大きいです。これは、a TCP=セグメントは、これまでに送信された両方のセグメントからのデータを組み合わせた場合、ネットワーク上にあるはずのサイズでもあります。

この問題を診断するのが非常に困難になったのは、送信されたデータが実際にだった別のマシンで実行されているWireSharkまで1500バイトのフレームに分割されたことでしたVM(接続された別の無差別ポートグループの同じvSwitchが表示される可能性があります。ゲートウェイVMが1つのパケットを見たのに、WireShark VMが見た理由2. FWIW、ゲートウェイで大きな受信オフロードが有効になっていない-有効になっているかどうか理解できた。WireSharkVMはWindows 7を実行している。

セグメンテーションを遅らせる際のVMwareのロジックは、データが物理NICから送信される場合、NICの実際のハードウェアオフロードを活用できるようにするためだと思います。ただし、別のVMに送信する前にセグメント化できず、その点で一貫性がないとバグがあるようです。この動作がVMwareのバグとして他で言及されているのを見ました。

解決策は、ターゲットサーバーでTCPセグメンテーションオフロードをオフにすることでした。手順はOSによって異なりますが、fwiw:

Windowsでは、接続のプロパティの[一般]タブまたは[ネットワーク]タブで、アダプタの横にある[構成...]をクリックし、[詳細]タブを確認します。 Server 2003 R2の場合は、「IPv4 TCP Segmentation Offload」と表示されます。Server2008 R2の場合は、「Large Send Offload(IPv4)」です。

このソリューションは少々扱いにくいものであり、一部の環境ではパフォーマンスに影響を与える可能性があるため、より適切な回答を受け入れます。

3
Kevin

ICMPフラグメンテーションが必要なメッセージはドロップできません。これらは、TCPが正しく機能するために必要なpMTU検出に必要です。ファイアウォール管理者にLARTを依頼してください。

透過性ルールにより、Do n't Fragment(DF)ビットが設定された送信IPパケットを許可するファイアウォールとして機能するパケットフィルタリングルーターは、送信パケットへの応答として送信される受信ICMP Destination Unreachable/Fragmentation Neededエラーをブロックしてはならない(MUST NOT)ファイアウォール内部のホスト。これにより、正当なトラフィックを生成するホストによるパスMTUディスカバリの標準に準拠した使用が妨げられます。 - ファイアウォールの要件-RFC2979 (オリジナルを強調)

これは、10年以上にわたって根本的に壊れていると認識されている構成です。 ICMPはオプションではありません。

7
David Schwartz

同じ症状があり、問題はこのカーネルのバグであることが判明しました: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=754294

1
Rob Fisher

Linuxホストでも同じ問題が発生しました。

解決策は、ゲートウェイマシンのネットワークドライバー(vmxnet)でLarge Receive Offload(LRO)を無効にすることでした。

VMware KBを引用するには:

LROは着信ネットワークパケットをより大きなバッファーに再構成し、結果としてより大きく、より少ないパケットをホストまたは仮想マシンのネットワークスタックに転送します。 CPUは、LROが無効になっている場合よりも少ないパケットを処理する必要があるため、ネットワークの使用率が低下します。

http://kb.vmware.com/kb/205514 を参照してください

したがって、ゲートウェイマシンに到着したパケットは、ネットワークドライバーによってマージされ、ネットワークスタックに送信され、MTUよりも大きいパケットをドロップしました...

0
user127779