TCP通信では、シーケンス番号と確認応答(ACK)番号を使用して、データバイトのやり取りします。 シーケンス番号は、TCPデータセグメントを正しい順番で並び替えることができるよう、追跡する数字で、ACK番号は、接続先にどこからのデータを要求したいのかを表す数字です。
ここでは、以下の擬似環境下を例にシーケンス番号とACK番号がどのように計算されるか確認します。
- クライアントからサーバへTCP接続を開始する。
- クライアントからサーバへ111バイトのTCPデータ(セグメント)を送信する。
- サーバからクライアントへ222バイトのTCPデータ(セグメント)を送信する。
- サーバからTCP接続を終了させる。
シーケンスの考え方
シーケンスは、初期値からTCPデータ(セグメント)を送信したバイト数分を加算していきます。
例えば、1000バイトのTCPデータを100,200,300,400の4つのセグメントに分割して、送信する場合するとします。
シーケンス番号は各セグメントの先頭のバイトが何番目のバイトなのかを表します。 初めのセグメントは1番目の1バイトから100番目の1バイトの計100バイトが送信されます。この場合、シーケンス番号は1です。
次の200バイトは101番目の1バイトから300番目の1バイトが送信されます。この場合、シーケンス番号は101です。
実際のシーケンス番号は1から始まるわけでなく、初期シーケンス番号(ISN)から順番に始まります。
ただし、WireSharkの場合は、Relative sequence numbersを有効にすることで、シーケンス番号を自動的に0から始まるものとして、解析してくれます。
シーケンス番号は、どこから始まるのかが大事ではなく、どのように値が変化していくのかが大事になるため、この機能は非常に便利です。
擬似環境でのシーケンス
クライアントからサーバへ3-way ハンドシェイクを結びます。 まず、クライアントからサーバへのSYNはシーケンス番号(SEQ)は初期値である0で送信します。 TCPデータサイズは1バイトとします。これは実体のないの値です。
サーバはSYN/ACKを返信します。サーバはSEQ=0まで受け取りました。SEQ=1からのデータがほしいので、それをACK番号として送信します。サーバからのシーケンス番号(SEQ)は、初期値である0で送信します。このTCPデータサイズも実体のない1バイトとします。
クライアントは、サーバにACKを返信します。サーバからACK番号=1を受け取っているので、次はシーケンス番号=1が欲しいのだと解釈します。
次にクライアントからサーバへ111バイトのTCPデータ(セグメント)を送信する。シーケンス番号、ACK番号はそのままで、TCPデータを111バイトを送信します。
サーバは次に112バイト目のデータが欲しいので、ACK=112を送信します。また、このTCPデータのサイズは222バイトとします。
クライアントは、サーバからACK=112を受信したので、次はシーケンス番号112で送信します。 また、クライアントはサーバからシーケンス番号1から222バイト目まで受信し、次は223バイト目から欲しいので、ACK=223で送信します。
サーバからセッションを終了します。このTCPデータサイズも実体のない1バイトとします。
次にクライアントからサーバへセッションを閉じ、TCPセッションが終了します。
TCPの解析は、Wiresharkなどのパケットキャプチャソフトをよく使用します。Wiresharkを用いて解析する際によく使用するキャプチャフィルタは、下記記事を参考にしてください。
>> 参考記事 : 【Wireshark】よく使用する表示フィルタ>> 参考記事 : 【Wireshark】TCP解析(Retransmission/Dup ACK など)
コメント