Ubuntu で NIC や IP アドレスを確認し、tcpdump などを使って 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'' meansunbuffered’’, 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キャプチャ

Step 1. ターミナル 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

Step 2. ターミナル 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

Step 3. ターミナル 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 フィルタの例

例 1

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.34 や ip host 93.184.216.34 を付与すると正しく動作しませんでした。 Ubuntu は正常に動作しました。

※ 93.184.216.34 は example.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)は受信側に直ちにデータ処理を依頼するフラグです。

例 2

sudo tcpdump -tnl -i eth0 src host 203.0.113.50 and dst port 80
  • NIC が eth0 かつ送信元 IP が 203.0.113.50 かつ送信先ポート番号が 80
curl -v example.com

* Rebuilt URL to: example.com/
*   Trying 203.0.113.50...
* TCP_NODELAY set
* Connected to example.com (203.0.113.50) port 80 (#0)
> GET / HTTP/1.1
> Host: example.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://example.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://example.com/">here</a>.</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at example.com Port 80</address>
</body></html>
* Connection #0 to host example.com left intact
sudo tcpdump -tnl -i eth0 src host 203.0.113.50 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 203.0.113.50.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 203.0.113.50.36452 > 10.0.0.78.80: Flags [.], ack 2551827646, win 981, options [nop,nop,TS val 2135968872 ecr 2135968871], length 0
IP 203.0.113.50.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 203.0.113.50.36452 > 10.0.0.78.80: Flags [.], ack 525, win 973, options [nop,nop,TS val 2135968872 ecr 2135968872], length 0
IP 203.0.113.50.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 203.0.113.50.36452 > 10.0.0.78.80: Flags [.], ack 526, win 973, options [nop,nop,TS val 2135968873 ecr 2135968873], length 0

例 3

sudo tcpdump -tnl -i eth0 src host 203.0.113.50 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
  • NIC eth0 かつ(送信元 IP が 203.0.113.50 かつ送信先 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 203.0.113.50 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 のみを許可します。

※ 実際のセキュリティグループ設定のスクリーンショットは省略

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

備考

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

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

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

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