#
ドキュメント

Document

自分のための備忘録です。

TCP/UDP パケットキャプチャ

前提

Ubuntu 20.0.4

準備

// ipコマンド
$ sudo apt install iproute2
// ifconfigはnet-toolsに含まれている
$ sudo apt install net-tools

NICやIPアドレスを確認

ip address showまたはifcofigで確認する。

  • loはループバックアドレス127.0.0.1仮想NIC
  • eth0はプライベートIP10.0.0.78/24のNIC
ip address show
// or
// ifconfig
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
    link/ether 06:d5:5e:00:b9:10 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.78/24 brd 10.0.0.255 scope global dynamic eth0
       valid_lft 3590sec preferred_lft 3590sec
    inet6 fe80::4d5:5eff:fe00:b910/64 scope link
       valid_lft forever preferred_lft forever

コントロールフラグ

  • コントロールフラグはTCPヘッダの6ビット長フィールド
  • コントロールビットとも呼ぶ
  • 左からURG、ACK、PSH、RST、SYN、FIN
  • 現在はCWR、ECE、NSを加えた9ビットになっている

URG
パケットに緊急データが含まれている
ACK
受信データを確認
PSH
アプリケーションレイヤーにデータをプッシュ
RST
接続をリセット(破棄)
SYN
接続を同期
FIN
正常に接続を終了
CWR
輻輳ウィンドウ削減
ECE
明示的な輻輳通知エコー
NS
輻輳を管理

ref. https://piedpin.com/top/2020/04/29/tcp-flag/

PSH(Push Flag)
受信したデータをすぐに上位のアプリケーションに渡さなければなりません。"0"の場合には、受信したデータをすぐにアプリケーションに渡さずに、バッファリングすることが許されます。

ref. マスタリングTCP/IP p212

tcpdump

tcpdumpでTCP/UDPのパケットをキャプチャする。
例としてeth0(10.0.0.78)のPing(ICMPエコー/リプライ)をキャプチャする。

tcpdumpオプション

  • tオプション:時刻を表示しない
  • nオプション:ドメイン名に変換しない
  • iオプション:NICを指定
  • eオプション:イーサネットヘッダを表示

l,v,vv,vvvオプションは以下のとおり。

lオプション

-l Make stdout line buffered. Useful if you want to see the data while capturing it. E.g., tcpdump -l | tee dat or tcpdump -l > dat & tail -f dat Note that on Windows,line buffered'' means unbuffered'', so that WinDump will write each character individually if -l is specified. -U is similar to -l in its behavior, but it will cause output to be ``packet-buffered'', so that the output is written to stdout at the end of each packet rather than at the end of each line; this is buffered on all platforms, including Windows.

-- man tcpdump

v, vv, vvvオプション

-v When parsing and printing, produce (slightly more) verbose output. For example, the time to live, identification, total length and options in an IP packet areprinted. Also enables additional packet integrity checks such as verifying the IP and ICMP header checksum. When writing to a file with the -w option and at the same time not reading from a file with the -r option, report to stderr, once per second, the number of packets captured. In Solaris, FreeBSD and possibly other operating systems this periodic update currently can cause loss of captured packets on their way from the kernel to tcpdump.

-vv Even more verbose output. For example, additional fields are printed from NFS reply packets, and SMB packets are fully decoded.

-vvv Even more verbose output. For example, telnet SB ... SE options are printed in full. With -X Telnet options are printed in hex as well.

tcpdump フィルタ

HTTPの通信のみキャプチャする。
ref. https://qiita.com/tossh/items/4cd33693965ef231bd2a

$ sudo tcpdump -tnl -i eth0 port 80

TCPキャプチャ

Step1. ターミナル1でtcpdumpコマンドを実行

ICMPプロトコル(Layer3)をキャプチャする。

$ sudo tcpdump -tnl -i eth0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

Step2. ターミナル2でpingコマンドを実行

$ ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=105 time=2.48 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=105 time=2.46 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=105 time=2.50 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 2.464/2.485/2.504/0.059 ms

Step3. ターミナル1にキャプチャが表示

$ sudo tcpdump -tnl -i eth0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 10.0.0.78 > 8.8.8.8: ICMP echo request, id 3283, seq 1, length 64
IP 8.8.8.8 > 10.0.0.78: ICMP echo reply, id 3283, seq 1, length 64
IP 10.0.0.78 > 8.8.8.8: ICMP echo request, id 3283, seq 2, length 64
IP 8.8.8.8 > 10.0.0.78: ICMP echo reply, id 3283, seq 2, length 64
IP 10.0.0.78 > 8.8.8.8: ICMP echo request, id 3283, seq 3, length 64
IP 8.8.8.8 > 10.0.0.78: ICMP echo reply, id 3283, seq 3, length 64

tcpdumpフィルタの例

例0)

https://example.com との通信をキャプチャする。

$ sudo tcpdump -tnl -i eth0 tcp port 443 and dst host 93.184.216.34
// sudo tcpdump -tnl -i eth0 tcp port 443 and ip host 93.184.216.34

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

Macのtcpdumpではdst host 93.184.216.34ip host 93.184.216.34を付与すると正しく動作しない。
Ubuntuでは正常に動作。

93.184.216.34example.comのIPアドレス。

$ curl -v -k https://example.com

*   Trying 93.184.216.34:443...
* TCP_NODELAY set
* Connected to example.com (93.184.216.34) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=Los Angeles; O=InternetCorporationforAssignedNamesandNumbers; CN=www.example.org
*  start date: Mar 14 00:00:00 2022 GMT
*  expire date: Mar 14 23:59:59 2023 GMT
*  issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1
*  SSL certificate verify ok.
...
...
...
$ sudo tcpdump -tnl -i eth0 tcp and port 443

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

IP 10.3.0.183.57298 > 93.184.216.34.443: Flags [S], seq 88688733, win 62727, options [mss 8961,sackOK,TS val 1300754457 ecr 0,nop,wscale 6], length 0 <--- (1)
IP 93.184.216.34.443 > 10.3.0.183.57298: Flags [S.], seq 1222124562, ack 88688734, win 65535, options [mss 1460,sackOK,TS val 950349798 ecr 1300754457,nop,wscale 9], length 0 ---(2)
IP 10.3.0.183.57298 > 93.184.216.34.443: Flags [.], ack 1, win 981, options [nop,nop,TS val 1300754565 ecr 950349798], length 0 ---(3)
IP 10.3.0.183.57298 > 93.184.216.34.443: Flags [P.], seq 1:518, ack 1, win 981, options [nop,nop,TS val 1300754573 ecr 950349798], length 517
IP 93.184.216.34.443 > 10.3.0.183.57298: Flags [.], ack 518, win 131, options [nop,nop,TS val 950349914 ecr 1300754573], length 0

(1)、(2)、(3)でスリーハンドシェイクが確立。

  1. Flags [S] SYN
  2. Flags [S.] SYN/ACK
  3. Flags [.] ACK

※ FLags [P] PSH(PUSH)は受信側に直ちにデータ処理を依頼するフラグ。

例1)

$ sudo tcpdump -tnl -i eth0 src host 52.68.24.79 and dst port 80
  • NICがeth0かつ送信元IPが52.68.24.79かつ送信先Port番頭が80
$ curl -v hiroshi-sawai.com

* Rebuilt URL to: hiroshi-sawai.com/
*   Trying 52.68.24.79...
* TCP_NODELAY set
* Connected to hiroshi-sawai.com (52.68.24.79) port 80 (#0)
> GET / HTTP/1.1
> Host: hiroshi-sawai.com
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Sun, 03 Apr 2022 06:46:07 GMT
< Server: Apache/2.4.29 (Ubuntu)
< Location: https://hiroshi-sawai.com/
< Content-Length: 317
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://hiroshi-sawai.com/">here</a>.</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at hiroshi-sawai.com Port 80</address>
</body></html>
* Connection #0 to host hiroshi-sawai.com left intact
$ sudo tcpdump -tnl -i eth0 src host 52.68.24.79 and dst port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

IP 52.68.24.79.36452 > 10.0.0.78.80: Flags [S], seq 642591391, win 62727, options [mss 1460,sackOK,TS val 2135968871 ecr 0,nop,wscale 6], length 0
IP 52.68.24.79.36452 > 10.0.0.78.80: Flags [.], ack 2551827646, win 981, options [nop,nop,TS val 2135968872 ecr 2135968871], length 0
IP 52.68.24.79.36452 > 10.0.0.78.80: Flags [P.], seq 0:81, ack 1, win 981, options [nop,nop,TS val 2135968872 ecr 2135968871], length 81: HTTP: GET / HTTP/1.1
IP 52.68.24.79.36452 > 10.0.0.78.80: Flags [.], ack 525, win 973, options [nop,nop,TS val 2135968872 ecr 2135968872], length 0
IP 52.68.24.79.36452 > 10.0.0.78.80: Flags [F.], seq 81, ack 525, win 973, options [nop,nop,TS val 2135968873 ecr 2135968872], length 0
IP 52.68.24.79.36452 > 10.0.0.78.80: Flags [.], ack 526, win 973, options [nop,nop,TS val 2135968873 ecr 2135968873], length 0

例2)

$ sudo tcpdump -tnl -i eth0 src host 52.68.24.79 and dst port 80 or icmp

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
  • NICeth0かつ(送信元IPが52.68.24.79かつ送信先Portが80)またはProtocol ICMP
$ ping -c 3 8.8.8.8

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=105 time=2.45 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=105 time=2.49 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=105 time=2.50 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 2.456/2.484/2.500/0.045 ms
$ sudo tcpdump -tnp -i eth0 src host 52.68.24.79 and dst port 80 or icmp

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

IP 8.8.8.8 > 10.0.0.78: ICMP echo reply, id 4935, seq 1, length 64
IP 10.0.0.78 > 8.8.8.8: ICMP echo request, id 4935, seq 2, length 64
IP 8.8.8.8 > 10.0.0.78: ICMP echo reply, id 4935, seq 2, length 64
IP 10.0.0.78 > 8.8.8.8: ICMP echo request, id 4935, seq 3, length 64
IP 8.8.8.8 > 10.0.0.78: ICMP echo reply, id 4935, seq 3, length 64

tcpdumpでHTTPヘッダを表示

$ sudo tcpdump -i eth0 -tnlvvv 1600 host 10.2.2.6 and port 80

AWS セキュリティグループ

アウトバウンドを443のみ許可。

インスタンス___EC2_Management_Console

HTTP(ポート番号:80)でリクエストしてみる。

$ curl --head http://example.com
$ sudo tcpdump -tnl -i eth0 port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

IP 10.3.0.183.52704 > 93.184.216.34.80: Flags [S], seq 458002455, win 62727, options [mss 8961,sackOK,TS val 3541591389 ecr 0,nop,wscale 6], length 0
IP 10.3.0.183.52704 > 93.184.216.34.80: Flags [S], seq 458002455, win 62727, options [mss 8961,sackOK,TS val 3541592393 ecr 0,nop,wscale 6], length 0
IP 10.3.0.183.52704 > 93.184.216.34.80: Flags [S], seq 458002455, win 62727, options [mss 8961,sackOK,TS val 3541594409 ecr 0,nop,wscale 6], length 0
IP 10.3.0.183.52704 > 93.184.216.34.80: Flags [S], seq 458002455, win 62727, options [mss 8961,sackOK,TS val 3541598665 ecr 0,nop,wscale 6], length 0
IP 10.3.0.183.52704 > 93.184.216.34.80: Flags [S], seq 458002455, win 62727, options [mss 8961,sackOK,TS val 3541606857 ecr 0,nop,wscale 6], length 0

想定どおり送信先から確認応答(Flags [S.])を受信できない。

Pingも想定どおり応答がない(185.125.188.54はexample.org)。

ping -c 3 185.125.188.54
PING 185.125.188.54 (185.125.188.54) 56(84) bytes of data.

--- 185.125.188.54 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2026ms

tcpdumpからpcapngに保存

$ pwd 
/home/ubuntu
# 10.0.0.78でApacheがポート番号443で稼働
$ sudo tcpdump -ntl -i eth0 tcp port 443 and host 10.0.0.78 -w ./data.pcapng
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C52 packets captured
52 packets received by filter
0 packets dropped by kernel
$ tcp ubuntu@ホスト:/home/ubuntu ./data.pcapng

備考

EC2インスタンスからグローバルIPを確認

EC2インスタンス内部からグローバルIPを確認する。

$ curl http://169.254.169.254/latest/meta-data/public-ipv4

ref. https://blog.serverworks.co.jp/ec2/ipaddress