TCPのオプション 〜SACK、Timestamp(PAWS)、Window Scale、MSS〜

TCPのオプションは、以下の形式で表現されます。

TCPのオプションの種類は、主に以下の7つがあります。

0.End Of Option List
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。1Byteが全て0で指定され、オプションの最後であることを示します。ただし、このオプションは実装されないことが多いようです。

No Operation

オプション番号1。オプション間のデリミタ(区切り文字)として使われ、かつ、4Byte単位に揃うように配置されます。例えばオプション番号5 SACKが使われるとき、SACKのバイト数が10Byteだった場合、No-Operationを2つ(2Byte)穴埋めで使い、その後にSACK(10Byte)が入り、合計12Byte(4Byteの倍数)で送信されます。

MSS

オプション番号2。TCP 3wayハンドシェイクのsyn, syn/ackのタイミングで、お互いに受信できるセグメントのサイズを ネゴシエーションします。
通常のホストはMTU値が1500Byteで、IPヘッダが20Byte、TCPヘッダも20Byteなので、1460Byte同士でネゴシエーションします。

ただし、フレッツ等の回線では、MTU値が1454Byteに制限されているため、インターネットとの通信は1414Byteにする必要が出てきます(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サイズが64KByteまでの頃はまだ良かったのですが、Window Scaleによりサイズが大きくなった場合、RTT値の精度が 悪くなってしまいます。

これに対応するために、Time Stampオプションを利用します。3wayハンドシェイクのタイミングで このオプションをつけることで、そのコネクション中でいつでもRTT値を計算することができるようになります。

ホストAからTS値(32bitの整数値)の入ったセグメントを受け取ったホストBは、TSエコー応答値Fieldには受け取ったセグメントのTS値を入れ、 TS値にはホストAに送り返す時刻(32bitの整数値)を入れます。

また、最近では1Gbpsのネットワークが当たり前になってきましたが、1Gbpsの速度においては、シーケンス番号がわずか40秒程度で一巡してしまう 事態も想定されます。パケットが遅延してしまうと、シーケンス番号が一巡して重複する可能性が出てきます

そこでPAWS (Protection Against Wrapped Sequence) という解決策が出てきました。これは、シーケンス番号をTime Stampオプションとセットにすることで、重複を避ける、というものです。 これにより、シーケンス番号が重複しても古いパケットと新しいパケットを識別することができます。

ただし、このPAWSはDoS攻撃を受ける脆弱性があることが分かっており、有効化する場合はパケットが推測されない、FWを経由している、等の適切な環境にすることが重要です。

TCP/UDP の勉強については、以下の書籍がお薦めです。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする