こんにちは!技術メディアへようこそ。プロのネットワークセキュリティスペシャリストの視点から、今日もパケットが飛び交うネットワークの深淵を一緒にのぞいていきましょう。
ネットワークの世界に一歩踏み入れると、必ず耳にするのが「パケット」という言葉ですよね。私たちがブラウザでWebサイトを見たり、メッセージアプリでスタンプを送ったりするとき、そのデータは細かく分割され、インターネットという広大な網の目を通って相手に届けられます。
このとき、パケットの先頭にくっついている「宛先や送り主、扱い方」が書かれたラベル。それこそが「IPv4ヘッダー」です。
一見すると、英語の略称やビット数(IHL や TTL、16ビット など)が並んでいて、頭が痛くなりそうですよね。でも、安心してください!
今回は、このIPv4ヘッダーの構造を、私たちが毎日お世話になっている「郵便配達の流れ」に例えて、一歩ずつ丁寧に紐解いていきます。この記事を読み終える頃には、無機質なビットの羅列が、血の通った温かい「配達伝票」に見えてくるはずです。
それでは、パケット探検の旅へ出発しましょう!
—
1. IPv4ヘッダーは「魔法の配達伝票」
私たちが荷物を郵送するとき、段ボール箱の天面に「送り状(伝票)」を貼りますよね。そこには宛先、差出人、壊れ物注意の有無、荷物の重さなどが書かれています。
ネットワークの世界における「IPv4ヘッダー」も、まったく同じ役割を持っています。
データを運ぶ「箱」であるIPパケットの先頭には、必ず以下のような構造のヘッダー(伝票)がくっついています。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
「うわっ、難しそう…」と思わなくても大丈夫です!
この図は、横幅が「32ビット(4バイト)」で区切られたグリッドになっています。パケットがルーターに届くと、ルーターは上から順番にこの情報を読み取って、「なるほど、この荷物はこう扱えばいいんだな」と判断していくのです。
では、各フィールドが郵便でいうと何に当たるのか、1つずつ優しく解説していきますね。
—
2. 各フィールドの役割を郵便に例えて大解剖!
① Version(バージョン): 郵便ハガキか、ゆうパックか
- ビット幅: 4ビット
- 郵便での例え: 「この発送伝票のフォーマットは、バージョン何ですか?」という規格の宣言。
IPv4(インターネット・プロトコル・バージョン4)のパケットなので、ここには必ず2進数の 0100(10進数で 4)が入ります。ルーターはこの最初の4ビットを見て、「よし、これはIPv4のルールで書かれた伝票だな」と即座に理解します。ちなみに、これがIPv6になると、ここが 6(0110)になります。
② IHL (Internet Header Length) : 伝票の「縦の長さ」
- ビット幅: 4ビット
- 郵便での例え: 伝票自体の大きさ(どこまでが伝票で、どこからが中身の荷物か)。
IPヘッダーは、実はオプションが付くことで長さが変わることがあります。そのため、「この伝票はここまでですよ!」という目印が必要です。
通常、オプションがない場合のヘッダーの長さは20バイト。このフィールドには 5 という値が入ります。「なぜ 5 なの?」と思いますよね。実はこの値に4を掛け算した値($5 \times 4 = 20$ バイト)が実際の長さになるルールなのです。
③ Type of Service (ToS) : 「お急ぎ便」や「書留」の指定
- ビット幅: 8ビット
- 郵便での例え: 「速達」「壊れ物注意」といった、配達の優先順位オプション。
このパケットをどれくらい優先して運ぶべきかを指定します。例えば、遅延が許されない「IP電話の音声データ」などを優先的に通し、普通のWebページのデータは少し待たせる、といった制御(QoS:Quality of Service)に使われます。
④ Total Length(全長): 荷物全体の重さ
- ビット幅: 16ビット
- 郵便での例え: 伝票と中身を合わせた、荷物全体の「総重量(グラム)」。
ヘッダーと中身のデータ(ペイロード)を合わせた、パケット全体の長さをバイト単位で表します。ルーターはこの値を見て、「これからどれくらいの大きさのデータが届くのか」を把握します。
—
大きな荷物を小分けにする「分身の術」トリオ
次の3つのフィールドは、ネットワークの途中で「荷物が大きすぎて通れない!」となったときに、荷物をバラバラに分割(フラグメンテーション)して送るための超重要機能です。
+-------------------+ +-------------------+ +-------------------+
| パケット A (1/3) | + | パケット A (2/3) | + | パケット A (3/3) |
+-------------------+ +-------------------+ +-------------------+
ID: 12345 ID: 12345 ID: 12345
Flags: MF=1 (次あり) Flags: MF=1 (次あり) Flags: MF=0 (最後)
Offset: 0 Offset: 180 Offset: 360
⑤ Identification(識別子)
- ビット幅: 16ビット
- 郵便での例え: 分割された荷物すべてに貼られる「同一グループのID」。
- 荷物を3つに分けて送る際、すべてに「ID: 12345」と書いておくことで、受け取った人が「あ、この3つは元々1つの荷物だったんだな」と分かります。
⑥ Flags(フラグ)
- ビット幅: 3ビット
- 郵便での例え: 「これ以上分割してはダメ(DFフラグ)」や「この後ろにもまだ分割された荷物が続きます(MFフラグ)」というメッセージ。
- 「これ以上分けちゃダメ!」という指示があるのに通れない道に突き当たると、ルーターはパケットを泣く泣く破棄して「通れなかったよ」とエラーを返します。
⑦ Fragment Offset(フラグメント・オフセット)
- ビット幅: 13ビット
- 郵便での例え: 「この箱は、元の大きな荷物の何番目のパーツか」を示す組み立て説明書。
- バラバラに届いた荷物を、元の順番通りにピタッとパズルみたいに組み立てるために必要な、開始位置の情報です。
—
⑧ Time to Live (TTL) : パケットの寿命(砂時計)
- ビット幅: 8ビット
- 郵便での例え: 宛先不明の荷物が、無限に郵便局間をたらい回しにされるのを防ぐ「有効期限」。
ネットワークの世界で最もドラマチックなフィールドが、この TTL です。
パケットがルーターを1つ通過する(ホップする)たびに、この TTL の値は「1」ずつ減らされます。
もしネットワークの経路設定がループしていて、パケットがぐるぐると同じ場所を回り続けてしまったら、いずれ TTL は 0 になります。その瞬間、ルーターはパケットを破棄し、パケットはその一生を終えます。これによって、インターネットが迷子パケットでパンクするのを防いでいるのです。健気ですよね。
⑨ Protocol(プロトコル): 中身の便箋に書かれた言語
- ビット幅: 8ビット
- 郵便での例え: 中身の手紙が「日本語(TCP)」で書かれているか、「英語(UDP)」で書かれているか。
IPパケットという封筒の中に、さらにどんなデータが入っているかを伝えます。
6が入っていれば「中身は丁寧なやり取りをするTCPです」17が入っていれば「中身はスピード重視のUDPです」1が入っていれば「通信テスト用のICMP(pingなど)です」
というように、次にバトンを渡す相手を教えてくれます。
⑩ Header Checksum(ヘッダー・チェックサム): 伝票の汚れチェック
- ビット幅: 16ビット
- 郵便での例え: 伝票が雨で濡れて、文字がにじんで読めなくなっていないかの確認サイン。
送信元がヘッダーの数字を複雑に計算した結果をここに書いておきます。受信したルーターも同じ計算をして、ここの値と一致するかを確かめます。もしノイズなどで1ビットでもデータが変わっていれば、計算が合わなくなり、「この伝票は破損している!」と判断してそのパケットを静かにゴミ箱へ捨てます。
—
3. 実践!PythonでIPv4ヘッダーを「解剖」してみよう
言葉の解説だけでは、まだイメージが湧きにくいかもしれません。
そこで、ネットワークエンジニアやセキュリティアナリストがよく使うパケット生成・解析ライブラリ 「Scapy (スキャピ)」 を使ったPythonコードを見てみましょう。
実際にパケットを作成し、その中にこれまで学んだフィールドがどのように格納されているかを表示してみます。
# 必要なライブラリをインポートします
# ※事前に「pip install scapy」でインストール可能です
from scapy.all import IP, TCP, show_interfaces
def create_and_dissect_packet():
print("--- 1. オリジナルのIPパケットを作成します ---")
# Pythonのコードで、まるで手紙を書くようにIPパケットを組み立てます
# ここで指定した値が、先ほど解説した各フィールドに格納されます!
packet = IP(
src="192.168.10.10", # 送信元IPアドレス (Source IP)
dst="8.8.8.8", # 宛先IPアドレス (Destination IP)
ttl=64, # 寿命 (Time to Live)
tos=0x10, # 優先度 (Type of Service: 低遅延を要求)
id=54321 # 識別子 (Identification)
) / TCP(dport=443) # 中身のプロトコルとしてTCP(ポート443: HTTPS)をカプセル化
print("\n--- 2. パケットのヘッダー情報を解剖してみましょう ---")
# packet.show() メソッドを使うと、ヘッダーの各フィールドが綺麗に表示されます
packet.show()
print("\n--- 3. 生のバイナリ(パケットが電線を流れるときの姿)を覗いてみましょう ---")
# パケットを16進数のバイト列に変換して表示します
raw_bytes = bytes(packet)
# 最初の20バイトが「IPヘッダー」に相当します
ip_header_bytes = raw_bytes[:20]
# 16進数で2桁ずつ見やすく表示
hex_string = " ".join(f"{b:02x}" for b in ip_header_bytes)
print(f"IPヘッダー(16進数): {hex_string}")
# 先頭の1バイト(Version と IHL が合体したもの)を解析してみます
# 0x45 の場合、上の4ビットが「4」(IPv4)、下の4ビットが「5」(IHL: 5*4=20バイト)
first_byte = ip_header_bytes[0]
version = first_byte >> 4
ihl = (first_byte & 0x0F) * 4
print(f"解析結果 -> バージョン: IPv{version}, ヘッダー長: {ihl}バイト")
if __name__ == "__main__":
create_and_dissect_packet()
このコードを実行すると、どうなる?
このスクリプトを実行すると、コンソールには以下のような解析結果が出力されます。
--- 1. オリジナルのIPパケットを作成します ---
--- 2. パケットのヘッダー情報を解剖してみましょう ---
###[ IP ]###
version = 4 <-- ① Version: IPv4
ihl = 5 <-- ② IHL: 5(20バイト)
tos = 0x10 <-- ③ ToS: 低遅延(最小遅延)
len = 40 <-- ④ Total Length: TCPヘッダーと合わせて40バイト
id = 54321 <-- ⑤ Identification: このパケットのID
flags = <-- ⑥ Flags: 分割なし
frag = 0 <-- ⑦ Fragment Offset: 0番目の位置
ttl = 64 <-- ⑧ TTL: 寿命は残り64ホップ
proto = tcp <-- ⑨ Protocol: 中身はTCP (値としては 6)
chksum = None <-- ⑩ Checksum: 送信時に自動計算されます
src = 192.168.10.10 <-- 送信元IP
dst = 8.8.8.8 <-- 宛先IP
--- 3. 生のバイナリを覗いてみましょう ---
IPヘッダー(16進数): 45 10 00 28 d4 31 00 00 40 06 00 00 c0 a8 0a 0a 08 08 08 08
解析結果 -> バージョン: IPv4, ヘッダー長: 20バイト
機械が処理しているパケットの中身が、私たちが学んだ通りの構造で綺麗に格納されているのが一目瞭然ですね!
—
4. 現場のトラブルシューティングから:ヘッダーが語るドラマ
最後に、私たちネットワークエンジニアが現場で遭遇する「IPv4ヘッダーにまつわる泥臭いトラブル」を2つご紹介します。
ドラマ1:巨大な荷物が引き起こす「パケット迷子」
「特定のWebサイトだけ、なぜか画像の読み込みが途中で止まってしまうんです…」
こんな相談を受けたとき、真っ先に疑うのが Flags と Total Length です。
通信経路のどこかに「うちは一度に1400バイトまでの荷物しか通せません!」という細いトンネル(MTUの制限)があったとします。
そこに、送信元が Flags に「DF(Don’t Fragment:絶対に分割するな!)」と書いた 1500バイト のパケットを送りつけると、ルーターは「分割して送りたいけど、分割禁止って書いてあるから無理!」と判断し、パケットを捨ててしまいます。
これが、いわゆる「Path MTU Discoveryブラックホール」と呼ばれるトラブルです。ヘッダーのフラグ1つが、通信の成否を握っているのですね。
ドラマ2:TTL が語る「無限ループの恐怖」
ルーターの設定ミスによって、ネットワーク内でパケットの「たらい回し」が起きることがあります。
Router A は Router B へ送り、Router B は「いや、それは Router A に送るべきだよ」と送り返す……。
もし TTL という寿命フィールドがなかったら、このパケットは永遠に光ファイバーの中を回り続け、最終的に回線をパンクさせてしまいます。
トラブルの際、パケットキャプチャ(Wiresharkなど)を見て、TTL の値が異様に小さくなっている(例: TTL=1 や 2)パケットを発見したとき、エンジニアは「あっ、どこかでループが起きているな!」と察知するのです。
—
まとめ:基礎は最大の武器になる
お疲れ様でした!一見すると難解なIPv4ヘッダーですが、こうして1つひとつのフィールドを郵便に例えて見ていくと、「どれも必要だから存在しているんだな」ということが実感できたのではないでしょうか。
ゼロトラストやクラウドの時代になり、物理的なネットワークを意識する機会は減っているかもしれません。しかし、パケットがネットワークを駆け巡るリアルな挙動や、ヘッダーに刻まれた情報は、今も昔もシステムの本質です。
何か通信トラブルが起きたとき、あるいは新しいセキュリティ対策を考えるとき、この「パケットの宛名ラベル」の知識は、あなたを助ける強力な武器になります。
一歩ずつ、焦らずに理解を深めていきましょう。あなたのインフラエンジニアとしてのこれからの歩みを、心から応援しています!
コメント