TCP のオプションは、以下の形式で表現されます。
TCP のオプションの種類は、主に以下の 7 つがあります。
1.No Operation
2.MSS (Maximum Segment Size: 最大セグメントサイズ)
3.Window Scale
4.SACK (Selective ACKnowledge) Permitted
5.SACK
8.Time Stamp
各オプションの説明
End of Option List
オプション番号 0。1 Byte が全て 0 で指定され、オプションの最後であることを示します。ただし、このオプションは実装されないことが多いようです。
No Operation
オプション番号 1。オプション間のデリミタ(区切り文字)として使われ、かつ、4 Byte 単位に揃うように配置されます。例えばオプション番号 5 SACK が使われるとき、SACK のバイト数が 10 Byte だった場合、No-Operation を 2 つ (2 Byte)穴埋めで使い、その後にSACK (10 Byte)が入り、合計 12 Byte (4 Byteの倍数)で送信されます。
MSS
オプション番号2。TCP 3way ハンドシェイクの syn, syn/ack のタイミングで、お互いに受信できるセグメントのサイズを ネゴシエーションします。
通常のホストは MTU 値が 1500 Byte で、IP ヘッダが 20 Byte、TCP ヘッダも 20 Byte なので、1460 Byte 同士でネゴシエーションします。
ただし、フレッツ等の回線では、MTU 値が 1454 Byte に制限されているため、インターネットとの通信は 1414 Byte にする必要が出てきます (Path MTU Discovery によりフラグメントが禁止されているため)。そのため、一般的なルータでは、このスリーウェイハンドシェイクの時にこのオプションの MSS 値を 変更する機能が実装されています。
例えば Cisco では、以下のコマンドにより、これを実現します。
(config-if)# ip tcp adjust-mss 1414
Window Scale
オプション番号 3。TCP のウィンドウ Field では、2 の 16 乗 = 64K Byte まで表現できますが、最近のホストの性能の観点からすると、これでは不十分であるため、このオプションで拡張を行なえるようにしました。
この Window Scale で指定した値の数だけ、ウィンドウ Field のスケールを bit シフトすることができます。
すなわち、Window Scale を 1 に指定した場合、ウィンドウ Field は 2 の 17乗 = 128K Byte まで表現でき、 Window Scale を 4 に指定した場合、ウィンドウ Field は 2 の 20乗 = 1M Byte まで表現できます。 Window Scale は 0 から 15 までの値を入れることができます。
なお、このオプションも TCP 3way ハンドシェイクの syn, syn/ack のタイミングで利用されますが、ネゴシエーションという訳ではなく、 お互いが別々の値を設定することができます。
SACK Permitted
オプション番号 4。SACK (Selective ACK) が利用できることを通知します。これも 3way ハンドシェイクのタイミングで利用されます。
この SACK という機能ができる前は、TCP データの受信側は、TCP の Seq# を見て、欠けているデータがあったとき、送信側に欠けているデータの直前までの Ack# を返し、送信側ではそれを受けて、欠けているデータ以降を全て再送することになっていました。そのため受信側では、欠けているデータ以降で既に受信できていたデータも 再度受信することになっていました。
しかし、SACK の登場によって、これが解決されました。具体的には次の SACK を参照下さい。
SACK
オプション番号 5。3way ハンドシェイク時に SACK Permitted が示されたホスト同士の通信においては、 以下のようにすることで、送信側に欠けているデータだけを再送することができるようになりました。
受信側は TCP の Seq# を見て、欠けているデータがあったとき、欠けているデータの直前までの応答確認を Ack# で示しつつ、このオプション領域で、受信できている一連のシーケンスの先頭 Seq# と末尾 Seq# を示します。飛び飛びで受信できている場合は複数の先頭 Seq#、末尾 Seq# を付けることができます。
SACK の使われ方を下図に示します。
Time Stamp
オプション番号 8。TCP の再送時間は RTT (Round Trip Time) 値、すなわち、パケットを出してから戻ってくるまでの平均時間をもとに計算されますが、 この RTT 値は Window サイズ毎に 1 パケットだけサンプリングされ、計算されます。
Window サイズが 64K Byte までの頃はまだ良かったのですが、Window Scale によりサイズが大きくなった場合、RTT 値の精度が 悪くなってしまいます。
これに対応するために、Time Stamp オプションを利用します。3way ハンドシェイクのタイミングで このオプションをつけることで、そのコネクション中でいつでも RTT 値を計算することができるようになります。
ホスト A から TS 値 (32 bit の整数値) の入ったセグメントを受け取ったホスト B は、TS エコー応答値 Field には受け取ったセグメントの TS 値を入れ、 TS 値にはホスト A に送り返す時刻 (32 bit の整数値) を入れます。
また、最近では 1G bps のネットワークが当たり前になってきましたが、1G bps の速度においては、シーケンス番号がわずか 40 秒程度で一巡してしまう 事態も想定されます。パケットが遅延してしまうと、シーケンス番号が一巡して重複する可能性が出てきます。
そこで PAWS (Protection Against Wrapped Sequence) という解決策が出てきました。これは、シーケンス番号を Time Stamp オプションとセットにすることで、重複を避ける、というものです。 これにより、シーケンス番号が重複しても古いパケットと新しいパケットを識別することができます。
ただし、この PAWS は DoS 攻撃を受ける脆弱性があることが分かっており、有効化する場合はパケットが推測されない、FW を経由している、等の適切な環境にすることが重要です。
nesukeの推薦図書
以下に該当する人なら熟読することを強く推奨します。
- 周りのネットワークエンジニアよりも一歩抜き出た存在となり、価値を高めたい!
- サーバエンジニアだけどネットワークも含めた総合的なセキュリティへの理解も深めていきたい!
コメント