Network

IPトレースの見方についていろいろ調査

2009年9月9日

IP/TCPヘッダーのフォーマットについて

IPヘッダのフォーマットは以下のページの絵が綺麗

【第3回 IPヘッダの解読法とパケット分割/キーマンズネット】 http://www.keyman.or.jp/3w/prd/42/30002442/

TCPヘッダーのフォーマットは、以下のページの絵が見やすい

【Transmission Control Protocol - Wikipedia】 http://ja.wikipedia.org/wiki/Transmission_Control_Protocol

iptrace トレースだと、IPヘッダーのダンプの後、TCPヘッダーのダンプが表示される。両方とも”オプション”の部分は、通常はデータが入らず(ネット上の解説もそうだし、実際のトレースもそう)、それぞれサイズとしては、20byte の大きさである。

なので、ACKの様な付随するデータの無いパケットだと、20Byte + 20 Byte で 40Byteのパケット・サイズが一般的。

IPヘッダーの中に、”IPヘッダーレングス(IHL)”というのがあるが、これは、TCPのヘッダーは含まない。

一方で、同じIPヘッダー中の”Total Length” はTCPヘッダーもデータも含む全体なので、少しこんがらがる。

細かい通信のやりとりについて

全体を通して、Seqやack\の番号がどの様に振られるかが、一番理解が大変だが、以下のサイトの説明が良かった。

【@IT:TCP/IPアレルギー撲滅ドリル【下位レイヤ編】6-2】 http://www.atmarkit.co.jp/fnetwork/rensai/tcp13/02.html

ここからは、詳しく解説しているサイトが無かったため、いろいろ考えた結果、多分こうだろう。と言う理解。

実際のトレースでは Webサイトに載っているような教科書通りの動きとはちょっと違った。教科書に載っている例と違い、ACK を返す必用が無い場合でも、ACKのビットが立っている事が多かった。

また通信終了の FIN → FIN/ACK → ACK という教科書通りの綺麗な流れは目撃できなかった。Dataが送り終わったら、Dataが届いた ACK を待たずに、いきなり FIN を送るトレースしか見つけられなかった。(といっても2つしかサンプルを見ていないので、なんとも言えないが)

以下は実際のトレースを元に、seq と ackの 番号を見やすくふり直したもの。クライアントからサーバーに 120Byte のデータを送るだけの通信。

クライアント

サーバー

No

flg

seq

ack

Len

flg

seq

ack

Len

1

SYN

1000

0

2

SYN | ACK

2000

1001

3

ACK

1001

2001

4

PSH | ACK

1001

2001

120

5

FIN | ACK

1121

2001

6

ACK

2001

1122

7

FIN | ACK

2001

1122

8

ACK

1122

2001

各ステップの勝手な解説は以下の通り。

No コメント
1 Client側のseqの開始番号は、環境と状況による。
通信開始時の ack も、綺麗に0で始まることは無い。ここでは見やすさのため0にする。
2 Server側のseqの開始番号は、以前の通信と状況に依存。
ack の番号は、ACK対象のseqの番号に対して+1するのが作法。
3 seq番号は、直前にもらった ack の値になる。ackの値は、ACKを返すべき seq に +1した値を入れる。
ここまでが、3ハンドシェイクと言う。
4 DataのPSH(PUSH)。
教科書だとPSHフラグだけだったりするが、実際には、ACKのフラグも立っていた。
ただし、この ACKフラグには、意味はなさそう。
5 教科書だと、ここでサーバーからACKを返したりするが現実には、クライアントは、データの受信確認を待たずに、もう送るデータが無い事を示すFINを送る事が多い。seqは、自分が送ったバイト数だけ加算されている。
ここでも、ACKが立っているが、値は、SYN/ACKのハンドシェイク終了後と変わっていない。サーバー側から特に何も受け取っていないのでack の値は変わらない。
6 ここで漸く、ACKが返るが、No.4に対するACKならack=1121になるはずだが、実際は、1122になる。恐らくNo.4に対するACKを返す前にNo.5が来たため、No.4/No.5へのACKをまとめて返している。と理解。

つまり、ack の値の算出は、

1001 + 120(No.4のDataへの応答) + 1(No.5のFINほの応答) = 1122

DataのACKをまとめて返す例は Webにあったが、DataとFINのACKをまとめて返す例は、Webでは、みつからなかった。ただ実際のトレースを見ると、その様に解釈を割り当てる以外に今の所思いつかない。

7 No.6と seqも、ack も同じ。
FINが送りたいだけだと思われる。No.6でACKを返しているので、ACKフラグも立てる必用が無いと思うが、実際には立っていた。
8 通信終了

seq/ack の番号を理解するための法則

  • SYN/FIN に対してACKを返す場合は、ackの値として、ACKを返す対象の seq番号に 1足した値 を ack にセットして返す。
  • データを受け取った時にACKを返す場合は、データの長さ + seq 番号を入れた値を ack にセットして返す。
  • 最期に受け取った ACKの ack の値が、次のseq の値になる。反対に言うと、ACKの ack に値1001を入れて返すという事は、相手に次の通信の seq は、1001から始めて下さい。(1000まで受け取りました)という事を表す。
  • seqは、自分が、SYNや、PSH を送ると1加算される。Dataを送るとDataのバイト数分だけ加算される。ACKを返した時のみ、何も加算されない。

データのサイズの計算方法

送ったデータサイズは、ダンプされているデータの量を数えるか、IPヘッダー(TCPヘッダーでは無い)の IHL (IP Header Lengt) と、IP Length と、TCPヘッダーの長さから計算する。

データをやりとりする時に、ack の値に加算されるのは、IP/TCPヘッダーを含まない部分のデータサイズ(つまり本当のデータ部分である)

IP Length = IP ヘッダーの長さ(IHL) (1) + TCP ヘッダー の長さ(2) + Dataサイズ (3)

(2)のTCPヘッダーの長さだけが、トレースからは読みにくい。TCPヘッダー内のData Offset という項目が、TCPヘッダー長を表すが、32bit ワード単位(4バイト単位)であるため、もし DataOffset =5 であれば、 4 Byte x 5 = 20 byte になる。

大抵は (1) も (2) も 20byte のサイズである事が多い。オプションが付く時だけ、(1)、(2)のサイズは 20byte 以外の値になる。


コネクション切断処理

No.6とNo.7 のステップはひとまとめにできる気がする。が、トレースからは、これらがまとまる例は、まだ見ていない。

下記のサイトの資料のPage 7にも、典型的な FIN/ACKの例として同様な動きが解説されているので、これは「こういうもの」として理解しておく。

http://www.scs.stanford.edu/nyu/01sp/notes/l11.pdf

-Network

Copyright© エンジニアの何でもメモ帳 , 2024 All Rights Reserved.