【実務・中級編】 IPv4フラグメンテーションと再構築のメカニズム – ネットワーク基礎とWebセキュリティ実践ガイド

ネットワークの深淵を覗く:IPv4フラグメンテーションの「悪夢」とセキュリティの境界線

ネットワークエンジニアとして現場を渡り歩いていると、たまに「どう考えても疎通するはずのパケットが、特定の環境でだけ消える」という不可解な事象に遭遇します。pingは通るのに、大きなペイロードを持つREST APIのレスポンスだけがタイムアウトする。そんな時、十中八九犯人として浮上するのが、今日解説するIPv4フラグメンテーションです。

教科書には「MTUを超えたら分割する」と一行で書かれていますが、実務においてこの処理は、インフラのパフォーマンス低下やセキュリティホールを招く「隠れた爆弾」になり得ます。今日は、パケットがネットワークの荒波の中でどう切り刻まれ、再び姿を取り戻すのか、その泥臭い挙動を紐解いていきましょう。

—

1. パケット分割の舞台裏:なぜ「フラグメンテーション」は起きるのか

ネットワークにはそれぞれ「一度に送れる荷物のサイズ」であるMTU (Maximum Transmission Unit) が決まっています。Ethernetの標準は1500バイトですが、VPNトンネル(IPsecなど)を経由したり、オーバーヘッドが増える環境では、この制限が実質的に小さくなります。

ここで、MTU 1500の経路に1600バイトのパケットが飛び込んできたとしましょう。ルーターは選択を迫られます。「捨てるか、刻むか」。ここで「刻む」選択をした時に発動するのがフラグメンテーションです。

パケットを切り刻む3つの鍵

IPヘッダーにある以下のフィールドが、再構築の「地図」となります。

  • Identification (16bit): どのパケットの断片かを識別するID。同じIDを持つ断片が集まって初めて一つのパケットになります。
  • Flags (3bit):
  • DF (Don't Fragment): 「分割するな」という命令。これがあるとルーターは問答無用でパケットを破棄し、ICMPで「MTU超えたよ」と送信元に伝えます。
  • MF (More Fragments): 「続きがあるよ」という合図。最後の断片以外はすべて1になります。
  • Fragment Offset (13bit): データの先頭から何バイト目から始まっているかを示すインデックス。これにより、バラバラに届いた断片を正しい順序でパケットに戻せます。

—

2. 現場での実証:Pythonでフラグメンテーションをシミュレートする

Web API開発者がAPIの挙動を検証する際、パケットサイズを意識することは稀かもしれません。しかし、巨大なJSONやバイナリデータを送る際は、このメカニズムが背後で動いています。

以下のPythonコードは、Scapyを使ってフラグメンテーションの様子を確認するための概念的なスクリプトです。

from scapy.all import IP, ICMP, fragment, send

# 仮想的なMTUを小さく設定して分割を発生させる(概念実証用)
packet = IP(dst="192.168.1.100") / ICMP() / ("A" * 2000)

# 8バイト単位でフラグメント化する(IPの仕様上、8の倍数で計算される)
fragments = fragment(packet, fragsize=800)

for f in fragments:
    # ここで Identification が同じ値であることを確認できる
    print(f"ID: {f.id}, Offset: {f.frag}, MF: {f.flags.MF}")

—

3. セキュリティ上のリスク:断片化された悪意

フラグメンテーションは、攻撃者にとっても格好の隠れ蓑です。

  • IDS/IPSの回避: 悪意のあるシグネチャを複数のパケットに分割して送りつけることで、再構築処理を行わない簡易的なIDS(侵入検知システム)の網を潜り抜ける手法です。
  • Tiny Fragment Attack: オフセットを意図的に操作し、TCPヘッダーを2つ目のパケットに押し込めることで、ファイアウォールのポートフィルタリングを無効化しようとする攻撃です。

これに対抗するため、最近のエンタープライズ境界防御では「再構築後のパケット検査(Virtual Reassembly)」が必須要件となっています。ルーターやファイアウォールで一度パケットを「完成」させてから検査するため、CPU負荷は跳ね上がりますが、ゼロトラストを標榜する環境では避けて通れません。

—

4. トラブルシューティングの極意:PMTUDを制する

実務で最も遭遇するのは、「クライアント側ではMTUが1500なのに、サーバー側やVPN機器が1400で、パケットが途中でドロップされる」というPMTUD (Path MTU Discovery) 失敗のケースです。

パケットが「黒い穴」に落ちて消えるのを防ぐには、以下の設定を検討してください。

LinuxサーバーでのMSSクランプ設定例 (iptables)

MTUの不一致を検知して、TCPのハンドシェイク時に適切な最大セグメントサイズ(MSS)を強制的に教え込む設定です。

# TCPハンドシェイク時にMSSを1360バイトに強制修正する
# ネットワーク機器のヘッダー分を差し引いた安全なサイズを指定する
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360

—

最後に:ネットワークは「生き物」である

Web APIを設計する際、「パケットが確実に届く」と信じるのはエンジニアの性ですが、ネットワークの深層では、今回解説したような断片化と再構築というドラマが常に繰り広げられています。

もし、特定の環境で「なぜかレスポンスが返ってこない」という壁にぶつかったら、tcpdumpやWiresharkを開き、パケットのFragment Offsetを確認してみてください。そこに、トラブル解決の突破口が必ず隠れています。

技術は常に進化しますが、IPの基礎構造は変わりません。この泥臭いレイヤーを理解しているかどうかが、あなたのエンジニアとしての「深み」を決めるのです。

それでは、また次の現場でお会いしましょう。ネットワークに幸あれ。

コメント

タイトルとURLをコピーしました