ping6.net

IPv6 MTUとPath MTU Discovery:フラグメンテーション問題の回避

IPv6でPath MTU Discoveryがどのように機能するか、ルーターがパケットをフラグメント化できない理由、MTU関連の接続問題のトラブルシューティング方法を学びます。

ping6.net2024年12月14日4 min read
IPv6MTUPMTUDフラグメンテーションネットワーキングトラブルシューティング

パケットフラグメンテーションは、すべてを壊すまで気づかない問題の1つです。

TL;DR - 要点まとめ

重要ポイント:

  • IPv6ルーターはフラグメント化できない:送信元ホストがPath MTU Discovery経由ですべてのフラグメンテーションを処理する必要
  • ICMPv6タイプ2をブロックしない:Packet Too BigメッセージはPMTUDに不可欠
  • 最小MTUは1280バイト:すべてのIPv6リンクがこれをサポートする必要、フォールバックとして使用
  • トンネルはMTUを削減:カプセル化オーバーヘッドを考慮(6in4:20バイト、VPN:40-80バイト)
  • MSSクランピングを使用:PMTUDが失敗した場合にTCPがより小さいセグメントを使用するよう強制

ジャンプ: PMTUDブラックホール | MTU問題の診断 | ファイアウォール設定


IPv6でMTUがより重要な理由#

IPv6はルーターベースのフラグメンテーションを完全に削除しました。IPv4では、ルーターが次のホップに対して大きすぎるパケットを受信した場合、それをフラグメント化できます。IPv6ルーターはそれができません—パケットをドロップし、ICMPv6「Packet Too Big」メッセージを送信元に送り返します。

送信元ホストがすべてのフラグメンテーションを担当します。この設計決定はルーターのパフォーマンスを向上させ、プロトコルを簡素化しますが、エンドポイントに負担を移し、Path MTU Discovery(PMTUD)を重要にします。

PMTUDが失敗すると、接続が不可解にハングします。TCPハンドシェイクは完了しますが、データ転送が停止します。HTTP要求がタイムアウトします。SSHセッションが認証後にフリーズします。これらは古典的なMTUブラックホールの症状です。

IPv6最小MTU#

すべてのIPv6リンクは少なくとも1280バイトをサポートする必要があります。これは最小MTUであり、交渉の余地はありません。リンクが1280バイトパケットを処理できない場合、IPv6準拠ではありません。

ほとんどのネットワークは1500バイト(標準イーサネットMTU)を使用し、40バイトのIPv6ヘッダーと1460バイトのペイロードのためのスペースを提供します。これはIPv4の典型的なTCP MSS 1460と同等です。

トンネルとカプセル化プロトコルは利用可能なMTUを減らします。IPv6-in-IPv4(6in4)、6to4、またはISATAPを実行している場合、外部ヘッダーにバイトを失います。VPN、IPsec、GRE、VXLANはすべてMTUスペースを消費します。

遭遇する一般的なMTU値:

  • 1500:標準イーサネット
  • 1480:PPPoE(PPPオーバーヘッドのために8バイト失う)
  • 1460:6in4トンネル(IPv4ヘッダーのために20バイト失う)
  • 1420:PPPoE上の6in4
  • 1280:最小IPv6 MTU、フォールバック値
  • 9000:ジャンボフレーム(データセンターネットワーク)

Path MTU Discoveryの仕組み#

PMTUDは、フラグメンテーションなしで送信元と宛先の間のパスを通過できる最大のパケットサイズを決定します。

プロセスは簡単です:

  1. ホストが現在のMTUでパケットを送信
  2. パスに沿ったルーターがより小さいMTUを持つ場合、パケットをドロップ
  3. ルーターがICMPv6タイプ2「Packet Too Big」メッセージを送信元に送り返す
  4. メッセージに次ホップのMTUが含まれる
  5. ホストがパスMTUを減らして再送信
  6. パケットがパス全体を通過するまでプロセスが繰り返される

「Packet Too Big」メッセージ(ICMPv6タイプ2、コード0)は、メッセージペイロードにMTU値を含みます。これにより、送信元はパケットが大きすぎるだけでなく、正確にどれだけ大きくできるかを知ることができます。

ICMPv6メッセージの様子は次のとおりです:

ICMPv6 Packet Too Big:
  Type:2
  Code:0
  MTU:1280
  [元のパケットヘッダー、最小MTUまで]

ホストは、通常10分後に期限切れになるエントリを持つパスMTUキャッシュを維持します(RFC 8201推奨)。ネットワークパスが変更された場合、期限切れになるまで古いキャッシュエントリが問題を引き起こす可能性があります。

PMTUDブラックホール#

システムはICMPv6タイプ2メッセージがブロックされたときに壊れます。これにより、パケットがサイレントに消える「PMTUDブラックホール」が作成されます。

一般的な原因:

過度に慎重なファイアウォール: 管理者はセキュリティリスクとして扱い、すべてのICMPトラフィックをブロックすることがあります。これは間違っています。ICMPv6はIPv6動作に不可欠であり、pingのようなオプションの診断プロトコルではありません。

ステートフルインスペクションの問題: 一部のファイアウォールはICMPv6エラーメッセージを既存の接続に適切に関連付けず、未要請トラフィックとしてドロップします。

レート制限: セキュリティデバイスはICMPv6をレート制限し、ビジー期間中に正当なPMTUDメッセージをドロップする可能性があります。

NAT64ゲートウェイ: IPv6とIPv4間の変換は、ゲートウェイがICMPメッセージを適切に変換しない場合、PMTUD情報を失う可能性があります。

PMTUDブラックホールの症状:

  • TCP接続が確立される(SYN、SYN-ACK、ACKが完了)
  • 小さなパケットが機能する(DNSクエリ、SSHログインバナー)
  • 大きなパケットが失敗する(ファイル転送、ボディ付きHTTP POST、認証後のSSHインタラクティブセッション)
  • エラーメッセージなし、タイムアウトのみ
  • 問題が断続的に見える(パケットサイズに依存)

MTU問題の診断#

pingから始めます。特定のサイズのパケットを送信してパスMTUをテストします:

# 1280バイト(最小MTU)でテスト
ping6 -M do -s 1232 2001:db8::1
 
# 1500バイト(標準イーサネット)でテスト
ping6 -M do -s 1452 2001:db8::1
 
# 1280バイトのペイロードでテスト
ping6 -c 5 -s 1280 2001:db8::1

-M doフラグはフラグメンテーションを禁止します(フラグメント化しない)。-s引数はペイロードサイズを指定します—ICMPv6ヘッダーに8バイト、IPv6ヘッダーに40を追加して、合計パケットサイズを取得します。

1452バイトが失敗するが1232が成功する場合、パスMTUは1280と1500の間です。正確な値を見つけるために2分探索します:

# 1400を試す
ping6 -M do -s 1352 2001:db8::1
 
# 1450を試す
ping6 -M do -s 1402 2001:db8::1

tracerouteを使用してMTUがどこで変更されるかを特定します:

traceroute6 -n 2001:db8::1

次に、各ホップに個別にMTUをテストします。大きなパケットが失敗し始めるホップが問題のポイントです。

TCP接続の場合、実際の動作を観察します:

# パケットをキャプチャ
tcpdump -i eth0 -n 'ip6 and (icmp6 or tcp)'

以下を探します:

  • 初期ハンドシェイク後のTCP再送信
  • ICMPv6タイプ2メッセージ(PMTUDが機能している場合に現れるはず)
  • ICMPv6タイプ2の不在(ブロックまたはブラックホールを示す)

最新のツールはこれを自動化できます。MTRはtracerouteとパケットサイズテストを組み合わせます:

# 1400バイトパケットでテスト
mtr -6 -s 1400 2001:db8::1

TCP MSSクランピング#

MSS(Maximum Segment Size)は、相手がどれだけのデータを各セグメントで送信できるかを伝えるTCPオプションです。MSS = MTU - IPヘッダー - TCPヘッダー。

IPv6の場合:MSS = MTU - 40(IPv6) - 20(TCP) = MTU - 60

標準1500バイトMTUの場合:MSS = 1440

MSSクランピングは、PMTUDに依存せずにMTU問題を回避するために、TCP接続により低いMSS値の使用を強制します。これは、トンネルまたはPPPoE接続を終端するルーターで一般的です。

Linuxでのクランピング:

# IPv6のMSSを1280にクランプ
ip6tables -t mangle -A FORWARD \
  -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --set-mss 1220

値1220は、ヘッダーのために1280 MTUマイナス60バイトを考慮します。

1492 MTUのPPPoEの場合:

ip6tables -t mangle -A FORWARD \
  -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --set-mss 1432

MSSクランピングはTCPにのみ影響します。UDP、SCTP、その他のプロトコルは依然としてPMTUDまたはアプリケーションレベルのフラグメンテーションに依存します。

ファイアウォール設定#

PMTUDが機能するためには、ファイアウォールがICMPv6タイプ2メッセージを許可する必要があります。これは本番IPv6ネットワークにとって交渉の余地がありません。

IPv6動作に必要な最小限のICMPv6タイプ:

  • タイプ1:Destination Unreachable
  • タイプ2:Packet Too Big(PMTUD)
  • タイプ3:Time Exceeded
  • タイプ4:Parameter Problem
  • タイプ133-137:近隣探索プロトコル

PMTUDのためのiptablesルール:

# ICMPv6 Packet Too Bigを許可
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 2 -j ACCEPT
ip6tables -A OUTPUT -p ipv6-icmp --icmpv6-type 2 -j ACCEPT
ip6tables -A FORWARD -p ipv6-icmp --icmpv6-type 2 -j ACCEPT

より良いアプローチ—すべての必要なICMPv6を許可:

# 確立されたICMPv6を許可
ip6tables -A INPUT -p ipv6-icmp -m state --state ESTABLISHED,RELATED -j ACCEPT
 
# 必要なICMPv6タイプを許可
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 1 -j ACCEPT    # Destination Unreachable
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 2 -j ACCEPT    # Packet Too Big
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 3 -j ACCEPT    # Time Exceeded
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 4 -j ACCEPT    # Parameter Problem
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 128 -j ACCEPT  # Echo Request
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 129 -j ACCEPT  # Echo Reply
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 133 -j ACCEPT  # Router Solicitation
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 134 -j ACCEPT  # Router Advertisement
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 135 -j ACCEPT  # Neighbor Solicitation
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 136 -j ACCEPT  # Neighbor Advertisement

レート制限は許容できますが、寛大な制限を設定します:

# レート制限付きでICMPv6を許可
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 2 \
  -m limit --limit 10/sec --limit-burst 20 -j ACCEPT

ICMPv6を完全にブロックしないでください。セキュリティリスクではありません—プロトコル要件です。

トンネルMTUの考慮事項#

トンネルは、カプセル化ヘッダーのオーバーヘッドによって有効MTUを減らします。

一般的なトンネルタイプとオーバーヘッド:

トンネルタイプオーバーヘッド有効MTU(1500から)
6in420バイト1480
6to420バイト1480
6rd20バイト1480
ISATAP20バイト1480
GRE24バイト1476
IPsec50-70バイト1430-1450
WireGuard60バイト1420
OpenVPN40-80バイト1420-1460

問題を回避するためにトンネルMTUを明示的に設定します:

# 6in4トンネル
ip tunnel add tun6in4 mode sit remote 203.0.113.1 local 198.51.100.1
ip link set tun6in4 mtu 1480
ip link set tun6in4 up

WireGuardの場合:

[Interface]
MTU = 1420

一部のトンネルプロトコルはMTU検出をサポートしていますが、明示的な設定の方がより信頼性があります。

ジャンボフレームとデータセンター#

データセンターネットワークは、バルク転送のスループットを向上させるために、しばしば9000バイトMTU(ジャンボフレーム)を使用します。

インターフェースでジャンボフレームを有効にします:

ip link set eth0 mtu 9000

パス内のすべてのスイッチとルーターがジャンボフレームをサポートすることを確認してください。1500バイトMTUを持つ1つのデバイスがボトルネックになります。

PMTUDは依然として適用されます。パケットがジャンボフレームネットワークからインターネットに向かう場合、1500以下に減らす必要があります。

テストと検証#

ホストのMTU設定を確認します:

ip -6 link show

各インターフェースのMTU値を探します。

現在のパスMTUキャッシュをチェック:

ip -6 route get 2001:db8::1

出力はその宛先のキャッシュされたMTUを表示します。

さまざまなパケットサイズでエンドツーエンドの接続をテスト:

for size in 1232 1352 1402 1452; do
  echo "Testing $size bytes:"
  ping6 -M do -s $size -c 3 2001:db8::1
done

netcatを使用してTCP MSSネゴシエーションをテスト:

# サーバー
nc -6 -l 8080
 
# クライアント
nc -6 2001:db8::1 8080

tcpdumpでパケットをキャプチャし、SYNパケットのMSS値を確認します。

一般的なシナリオと修正#

問題: ウェブページの読み込みが遅い、画像が失敗する 原因: ファイアウォールがICMPv6タイプ2をブロックしているためのPMTUDブラックホール 修正: ICMPv6タイプ2を許可するようにファイアウォールを設定

問題: SSHが接続するがログイン後にフリーズする 原因: MTUが大きすぎる、PMTUDが機能していない 修正: クライアントインターフェースでMTUを減らすか、ルーターでMSSクランピングを有効にする

問題: VPNが小さな転送には機能するが、大きなファイルでは失敗する 原因: トンネルMTUが正しく設定されていない 修正: カプセル化オーバーヘッドを考慮してトンネルMTUを減らす

問題: IPv6がローカルネットワークでは機能するが、インターネット経由では失敗する 原因: アップストリームルーターがより小さいMTUを持ち、適切に広告していない 修正: ISPに連絡するか、ローカルMTUを1280(最小)に減らす

問題: 一部の宛先は機能するが、他は失敗する 原因: パス固有のMTU問題 修正: pingでテストして機能するMTUを特定し、それに応じてインターフェースを設定

ベストプラクティス#

  1. 常にICMPv6タイプ2を許可 ファイアウォールで
  2. トンネルMTUを明示的に設定 自動検出に依存するのではなく
  3. 最小MTU(1280)でテスト ベースライン接続を確保するため
  4. MSSクランピングを使用 トンネルエンドポイントとPPPoE接続で
  5. PMTUD失敗を監視 トラブルシューティング中にパケットキャプチャで
  6. ネットワークのMTUを文書化 各レイヤー(物理、トンネル、アプリケーション)で
  7. 疑わしい場合は保守的なMTU値を設定 (1280は常に機能する)

関連記事#

パスMTUをテスト

Pingツールを使用して異なるサイズでのパケット配信をテストし、MTRツールを使用してパスに沿ってMTUがどこで変更されるかを特定します。

追加リソース#