■ping(ICMPv4)で出力されたパケットキャプチャデータを読んでみる。 以下の続き。 ラウンドトリップ時間をpingのワンライナーで計測してみる。 http://labunix.hateblo.jp/entry/20150804/1438641097 $ ping -c 1 -s $((1500-28)) 172.31.31.252 PING 172.31.31.252 (172.31.31.252) 1472(1500) bytes of data. 1480 bytes from 172.31.31.252: icmp_seq=1 ttl=254 time=1.41 ms --- 172.31.31.252 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 1.417/1.417/1.417/0.000 ms ■RTT(ラウンドトリップ時間)なので、往復のパケット。 $ sudo tcpdump -i eth0 -n icmp -vvv > icmp.log $ cat icmp.log 05:15:33.901362 IP (tos 0x0, ttl 64, id 32943, offset 0, flags [DF], proto ICMP (1), length 1500) 172.16.16.90 > 172.31.31.252: ICMP echo request, id 3717, seq 1, length 1480 05:15:33.902697 IP (tos 0x0, ttl 254, id 60839, offset 0, flags [none], proto ICMP (1), length 1500) 172.31.31.252 > 172.16.16.90: ICMP echo reply, id 3717, seq 1, length 1480 ■DFフラグはフラグメント化禁止フラグ $ man tcpdump 2>&1 | grep DF フラグメント化禁止フラグ の設定されたパケットの場合、行末に (DF)と表示する。 ■tsharkを導入、icmpをキャプチャ $ sudo apt-get install -y tshark $ sudo tshark -D 2>&1 | grep eth0 1. eth0 $ sudo tshark -V -i 1 -f "icmp" | grep -v ^0 > icmp.log Capturing on 'eth0' ■pingのデータを「1」で埋めて $ man ping | grep -A 3 "\-p pattern\$" -p pattern 送出するパケットを埋めるための 16 個までの ``pad'' バイトを指定で きる。 これはネットワークでの、データに依存した問題の診断に有用で ある。 たとえば “-p ff” は全て 1 で埋められたパケットを送る。 $ ping -c 1 -s $((1500-28)) -p ff 172.31.31.252 PATTERN: 0xff PING 172.31.31.252 (172.31.31.252) 1472(1500) bytes of data. 1480 bytes from 172.31.31.252: icmp_seq=1 ttl=254 time=1.41 ms --- 172.31.31.252 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 1.413/1.413/1.413/0.000 ms ■tsharkのtcpdumpと関連する箇所のみ確認 $ sed 's/[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]/XX:XX/g' icmp.log | grep -A 35 "^Internet Protocol" Internet Protocol Version 4, Src: 172.16.16.90 (172.16.16.90), Dst: 172.31.31.252 (172.31.31.252) Version: 4 Header Length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport)) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00) Total Length: 1500 Identification: 0xc223 (49699) Flags: 0x02 (Don't Fragment) 0... .... = Reserved bit: Not set .1.. .... = Don't fragment: Set ..0. .... = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: ICMP (1) Header checksum: 0xea77 [validation disabled] [Good: False] [Bad: False] Source: 172.16.16.90 (172.16.16.90) Destination: 172.31.31.252 (172.31.31.252) [Source GeoIP: Unknown] [Destination GeoIP: Unknown] Internet Control Message Protocol Type: 8 (Echo (ping) request) Code: 0 Checksum: 0xfc72 [correct] Identifier (BE): 5837 (0x16cd) Identifier (LE): 52502 (0xcd16) Sequence number (BE): 1 (0x0001) Sequence number (LE): 256 (0x0100) Timestamp from icmp data: Aug 5, 2015 XX:XX:48.000000000 JST [Timestamp from icmp data (relative): 0.798956000 seconds] Data (1464 bytes) Data: af300c0000000000ffffffffffffffffffffffffffffffff... [Length: 1464]
■tcpdumpも再度出力してみる。 $ sudo tcpdump -i eth0 -n icmp -vvv -x > icmp.log $ grep ^0 -A 4 icmp.log 07:30:49.975264 IP (tos 0x0, ttl 64, id 58904, offset 0, flags [DF], proto ICMP (1), length 1500) 172.16.16.90 > 172.31.31.252: ICMP echo request, id 5914, seq 1, length 1480 0x0000: 4500 05dc e618 4000 4001 c682 ac10 105a 0x0010: ac1f 1ffc 0800 8c70 171a 0001 193d c155 0x0020: 0000 0000 6be1 0e00 0000 0000 ffff ffff -- 07:30:49.976687 IP (tos 0x0, ttl 254, id 43062, offset 0, flags [none], proto ICMP (1), length 1500) 172.31.31.252 > 172.16.16.90: ICMP echo reply, id 5914, seq 1, length 1480 0x0000: 4500 05dc a836 0000 fe01 8664 ac1f 1ffc 0x0010: ac10 105a 0000 9470 171a 0001 193d c155 0x0020: 0000 0000 6be1 0e00 0000 0000 ffff ffff ■「4500」について、「5」はヘッダ長、ToSはフラグ無し。 $ echo "$((0x5*4)) bytes" 20 bytes 4bit Version 4bit Header Length / 4(オクテット) 8bit Differentiated Services Field(Tos) ■「05dc」はパケット長。 $ echo "$((0x05dc))" 1500 16 Total Length ■識別子はフラグメント時の復元用。 $ echo "$((0xa836))" 43062 16 Identification ■フラグの先頭ビット(3桁目)は(Reserved)で予約済みの未使用なので実質2ビット。 2桁目はDF(Do not Fragment)ビット 1桁目はMF(More Fragments)ビット。 それぞれ別のフラグだし、「パケットのフラグメントを許可しない,分割されたパケットの途中のフラグメント」は、 矛盾しているので起こらないとは思うが、DF,MFの両フラグが立ったパケットの扱いについては分からない。 $ seq 0 3 | awk '{print "ibase=10;obase=2 ;"$1}' | bc | \ awk '{printf "%03d\n",$1}' | awk '{printf $0" "}; \ {if($1>="010"){printf "パケットのフラグメントを許可しない,"} \ else{printf "パケットのフラグメントを 許可する,"}} \ {if($1%2=="1"){print "分割されたパケットの途中のフラグメント"} \ else{if($1%2=="0"){print "分割されたパケットの最後のフラグメント"}}}' 000 パケットのフラグメントを許可する,分割されたパケットの最後のフラグメント 001 パケットのフラグメントを許可する,分割されたパケットの途中のフラグメント 010 パケットのフラグメントを許可しない,分割されたパケットの最後のフラグメント 011 パケットのフラグメントを許可しない,分割されたパケットの途中のフラグメント 3 Flags ■最大8191のフラグメント(断片化)した場合の位置を8オクテット単位で示す。 $ echo $((0x1fff)) 8191 13 Fragment offset ■TTL $ echo $((0xfe)) 254 8 Time to live ■0から255までのプロトコル番号のうち、ICMPv4は1。 $ w3m -cols 1000 -dump http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml | \ grep "^ *[0-9]" | cut -c -20 | grep ICMP 1 ICMP 58 IPv6-ICMP 8 Protocol ■「1の補数和の1の補数」で計算されたチェックサム 16 Header checksum ■送信元IP $ echo "ac 1f 1f fc" | tr ' ' '\n' | awk '{print "echo $((0x"$1"))"}' | bash | xargs echo -n | sed -e 's/ /./g';echo 172.31.31.252 32 Source ■宛先IP $ echo "ac 10 10 5a" | tr ' ' '\n' | awk '{print "echo $((0x"$1"))"}' | bash | xargs echo -n | sed -e 's/ /./g';echo 172.16.16.90 32 Destination ■オプション 32bit単位で無い場合、桁揃えのためにパディングで32bitまで0埋めされる。 オプション(32-n bit)、パディング(n bit)の構成。 pingのデータ部分は「0xff」で埋めたので、宛先IPとの間に 32bit区切りでタイムスタンプ等の付加情報や拡張情報が入る。 IP Packet Structure http://www.freesoft.org/CIE/Course/Section3/7.htm