IPパケットフォーマット
IPとは、インターネットプロトコルの略で、現在主流のレイヤー3の通信プロトコルです。
IPの通信データ単位は"パケット"と呼ぶことが多く、ここでもそれに倣うことにします。
現在のIPのバージョンは4(IPv4)が多いですが、IPv4のIPアドレスが枯渇しており、 2011年2月1日にIANAからの新規割り当てができない状態になったことが発表されました。
それを受けてIPバージョン6(IPv6)が注目を浴びており、2011年6月8日にはWorld IPv6 dayという名前で、 世界の各業者が24時間、IPv6に切り替えて影響を量ってみよう、という試みがなされました。
今後はIPv4とIPv6の混在環境が続き、最終的にはIPv6に切り替わるのではないかと推測していますが、コストがかかる(PCやサーバへのIPv6設定変更等含む)割には、必須の作業ではないため、導入が思ったよりも進んでいません。IPv4はおそらくまだまだ活躍することになりそうです。
さて、IPはレイヤー3の通信プロトコルと言いましたが、そのプロトコル(決まり事)の大きな要素として、 IPパケットのフォーマットがあります。
下記にIPv4のパケットフォーマットを示します。IPは現在、よくEthernetフレームにカプセル化されて 使われます。カプセル化される際はEthernetのタイプFieldにOx0800を指定します。
各フィールドについて
バージョン (Version)
4bit。IPのバージョンが入ります。IPv4 は当然4ですので、"0100"が入ります。
ヘッダ長 (IHL: Internet Headr Length)
4bit。IPパケットのヘッダの長さ(4Byte単位)が入ります。オプションFieldとパディングFieldは無い場合がほとんどですので、 その場合はヘッダ長は20Byte(=5×4Byte)となり、"0101"が入ります。
サービスタイプ (ToS: Type of Service)
8bit。主にQoSを司るFieldです。このFieldには歴史があります。
もともと RFC791 により、上位3bitは IP-Precedence として、優先度を表現するbit、続く3bit はそれぞれ求められる遅延(D bit: 0=通常の遅延で処理、1=低遅延で処理)、 求められるスループット(T bit: 0=通常のスループットのパスを選択、1=高スループットのパスを選択)、求められる信頼性(R bit: 0=通常の信頼性のパスを選択、 1=高信頼性のパスを選択)を表現するbit、下位の2bitは予備として常に0が割り当てられる bit でした。
RFC1349 では予備の7bit目が金銭的コストの最小化を表現するM bit: 0=通常のコストのパスを選択、1=金銭的に安い(課金の少ない)パスを選択)が定義されました。
しかし、あまり実装されることもなく、この8bitは Differentiated Services Code Points (DSCP) として定義し直されました。
ただし、このDSCP は上位3bitは IP-Precedenceと互換性があるため、IP-Precedenceを利用してもある程度意図に沿うようになっています。
IP Precedence、および、DSCPの上位3bitは8段階の優先度を表し、値が高いほうが優先度も高くなります。
また、最後の 2bit は ECN(Explicit Congestion Notification) という輻輳制御の仕組みに使われます。 この ECN は、ECT(ECN Capable Transport) と CE(Congestion Experienced) の 2bit から構成され、NWが輻輳を起こした際、 実際にNW機器がパケット破棄を始める前に、データ通信をしているホストに輻輳を知らせる役目を持ちます。
ECT は上位層がECNの仕組みに対応しているかどうかを示します。TCP 自体は対応しているのですが、データ通信を扱うアプリケーション (ブラウザ等)も対応している必要があり、アプリケーションがこのビットの扱いを決めます。
CE はNW機器が輻輳しそうになった際にこのフィールドを1に変えて受信側に送ります。受信側はこれを検知すると、TCPのECEフィールドに 1をセットし、送信側に輻輳を知らせます。
これは一見回りくどいですが、次のように考えれば分かりやすいと思います。
輻輳はホスト同士の通信によって発生するため、TCP で制御するのが筋ですが(IPではデータ量の調整はできない)、NW機器は TCP に介入してはならず (IP は TCP 等を運ぶのが仕事だから)、そのため、NW機器は IPヘッダを変更し、受信側に輻輳を通知します。そして受信側が TCP レベルで、 送信側にデータ量を抑えるように伝えるのです。
パケット長 (Length)
16bit。IPパケット全体の長さ(Byte単位)が入ります。フィールドの長さは 16bit なので、IPパケットの最大長は 64KByte となります。 ただし、Ethernetの長さは最大 1518Byte、最近はジャンボフレームという名前で 9KByte や 16KByte までサポートされるようになりましたが、 IP は現在ほとんどが Ethernet に格納されて運ばれるため、64KByte の大きさでIPパケットが運ばれることはまずありません。
識別子 (Identification)
16bit。このFieldとフラグField、フラグメントオフセットFieldはフラグメンテーションが起きた際に必要になります。
フラグメンテーションが発生した際、先頭のパケットにはIPヘッダがついていますが、後続のパケットにはIPデータの途中からであるため、IPヘッダがなく、そのままではルーティングできません。
そのため、後続パケットにはIPヘッダを付けていきます(ただし、オプションFieldは コピーされないため、必ず20ByteのIPヘッダが付きます)。その際、識別子Fieldは 変更しないでおきます。
フラグメントされたパケットは宛先IPホスト(下記例ではホストB)で再構成されますが、MFフラグやオフセットを見て、到達順序が変わってしまっても正確に再構成できるようになっています。なお、送信元ホスト(下記例ではホストA)はパケットを出すたびに識別子を1ずつ増やして重複を避けています。
フラグ (Flag)
3bit。それぞれの意味を下記に示します。
1bit目: 未定義。常に0。
2bit目: DF bit(Don't Fragment)。0=フラグメントを許可、1=フラグメントを禁止。
3bit目: MF bit(More Fragment)。0=後続にフラグメントデータ無し、1=後続にフラグメントデータ有り。
2bit目のDF bitは、Path MTU Discovery という概念で頻繁に利用されているもので、ソケットと呼ばれるAPI(Windowsの場合は特に winsock と呼ぶ)はこのbitを立てて送信するようになっています。 このbitを立てて送信すると、自動的に返りのパケットもbitが立ちます。
IPv6では、この Path MTU Discovery の考え方を全面的に取り入れ、フラグメントをしない仕様になりました。
詳細についてはPath MTU Discoveryの項目を参照下さい。
オフセット (Offset)
13bit。分割していないパケットや分割した先頭のパケットにおいては常に0。分割した後続パケットにおいては、 元のデータに戻すときの位置を示します。8Byte単位のため、175という値であれば、再構成する際に 1400Byte目からこのデータが入る、ということを表しています。
生存時間 (TTL: Time to Live)
8bit。TTLと略されます。ルーティングされるたびに1ずつ減らすようにし、TTL=1の状態でルーティングをしようとすると、TTL=0 になり、ルーティングをする前にパケットは破棄され、送信元に Time Exceed と 呼ばれるICMPメッセージが通知されます。
この TTL により、ルーティングループが発生してもずっとネットワーク上にパケットが生き残らないようにしています。
プロトコル (Protocol)
8bit。この領域には、プロトコル番号が入ります。プロトコル番号は IANA により管理されており、番号ごとに対応する プロトコルが決められています。代表例として、TCP の場合は"6"が入ります。
下記に、このフィールドの値とそれに対応するプロトコルの一部を示します。
プロトコル番号 | プロトコル | ||
1 | ICMP | ||
2 | IGMP | ||
4 | IPv4 | ||
6 | TCP | ||
8 | EGP | ||
9 | IGP | ||
17 | UDP | ||
41 | IPv6 | ||
46 | RSVP | ||
47 | GRE | ||
88 | EIGRP | ||
89 | OSPF | ||
103 | PIM | ||
112 | VRRP | ||
115 | L2TP |
IPv4 や IPv6 がありますが、これは "IP in IP" や "IPv6 in IPv4" と呼ばれるもので、IPパケットの中にさらに IPパケットをカプセル化するトンネリング技術です。
ヘッダチェックサム (Header Checksum)
16bit。IPヘッダに破損がないかを確認する項目です。
計算方法は下記の通り。
- IPヘッダのチェックサムFieldを全て0として考える
- IPヘッダを 16bit 単位で加算
- 総計の下位 16bit の1の補数を取る
ルーティングするたびに TTL の値が減るため、 ルータでは受け取ったデータからこのFieldをチェックし、破損がなければ TTL を減らし、再びチェックサムを計算してこの領域に格納します。
オプション (Options)
現在、オプションFieldが使われることはまずありませんが、 1つだけ例をあげると、"ソースルーティング"というものがあります。
宛先に行く途中に通るべきIPアドレスをこのFieldで指定します。
例えばアドレスAからアドレスBに行く途中で、アドレスC、D、E、Fという 順番に経路を通りなさい、という指定ができます。
パディング (Padding)
ヘッダ長Fieldから分かるとおり、IPヘッダは 4Byte(32bit)単位である必要があります。しかし、オプションFieldは長さが 不特定のため、うまく 32bit の長さになるか分かりません。そのため、32bit 単位になるようにパディングFieldで埋めます。
コメント