参考文献

tcpdump

  • tcpdump抓包使用的是libpacp这种机制.它的大致原理是:在收发包时,如果该包符合tcpdump设置的规则(BPF filter),那么该网络包就会被拷贝一份到tcpdump的内核缓冲区,然后以PACKET_MMAP的方式将这部分内存映射到tcpdump用户空间,解析后就会把这些内容给输出了
1
2
3
4
5
6
7
8
9
10
11
12
root@root:/home/root# tcpdump -h
tcpdump version 4.9.3
libpcap version 1.9.1 (with TPACKET_V3)
OpenSSL 1.1.1f 31 Mar 2020
Usage: tcpdump [-aAbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ]
[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
[ -i interface ] [ -j tstamptype ] [ -M secret ] [ --number ]
[ -Q in|out|inout ]
[ -r file ] [ -s snaplen ] [ --time-stamp-precision precision ]
[ --immediate-mode ] [ -T type ] [ --version ] [ -V file ]
[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z postrotate-command ]
[ -Z user ] [ expression ]
  • -i: 表示监听抓服务器上哪个网卡
  • -t : 表示不显示时间戳
  • -s: 可以抓到完整的数据包,如果不加的话,可能就只抓部分字节
  • -c: 表示一共抓取多少次数据包

img

img

  • 上述图片来自极客时间-Linux性能优化 倪朋飞

tcpdump原理

img

  • 上图来自 极客时间-Linux内核技术实战课 第16讲
  • 在收包的时候,如果网络包已经被网卡丢弃了,那么tcpdump是抓不到它的;在发包的时候,如果网络包在协议栈里被丢弃了,比如因为发送缓冲区满而被丢弃,tcpdump同样抓不到它.可以将tcpdump的能力范围简单地总结为:网卡以内的问题可以交给tcpdump来处理;对于网卡以外(包括网卡上)的问题,tcpdump可能就捉襟见肘了.这个时候,你需要在对端也使用tcpdump来抓包.
  • tcpdump的开销比较大,这主要在于BPF过滤器.如果系统中存在非常多的TCP连接,那么这个过滤的过程是非常耗时的,所以在生产环境中要慎用.但是,在出现网络问题时,如果你真的没有什么排查思路,那就想办法使用tcpdump来抓一下包吧,也许它的输出会给你带来一些意外的惊喜.

监视指定网络接口的数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@root:/home/root# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1480
inet 172.16.210.90 netmask 255.255.255.255 broadcast 0.0.0.0
ether d2:d3:7c:9b:ea:de txqueuelen 0 (Ethernet)
RX packets 1159105 bytes 250437200 (250.4 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1606165 bytes 173357716 (173.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 1449 bytes 89110 (89.1 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1449 bytes 89110 (89.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

root@dntech:/home/dntech# tcpdump -i eth0

监听指定网络接口以及端口的数据包并写入文件中

1
root@dntech:/home/dntech# tcpdump -n -i eth0 tcp and  port 8002 -c 20 -vvv -w packets.pcap
  • -n : 显示IP地址
  • -nn : 显示端口号,表示不解析抓包中的域名(即不反向解析)、协议以及端口号
  • port 8002: 指定特定端口

查看可以被tcpdump使用的网络接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# tcpdump -D
1.docker0 [Up, Running]
2.veth300f1cb [Up, Running]
3.br-22cf8f34a4ab [Up, Running]
4.veth913a0cb [Up, Running]
5.eno1 [Up, Running]
6.veth4ec61e8 [Up, Running]
7.vethb60fcf9 [Up, Running]
8.veth61edd48 [Up, Running]
9.veth1833c70 [Up, Running]
10.vethf2fc86f [Up, Running]
11.br-c0f1f534c419 [Up, Running]
12.veth8ab1310 [Up, Running]
13.vethe01821b [Up, Running]
14.any (Pseudo-device that captures on all interfaces) [Up, Running]
15.lo [Up, Running, Loopback]
16.eno2 [Up]
17.eno3 [Up]
18.eno4 [Up]
19.br-9ad2d87fbcb6 [Up]
20.br-5f963d83c7c8 [Up]
21.br-efada4fe7cc9 [Up]
22.nflog (Linux netfilter log (NFLOG) interface)
23.nfqueue (Linux netfilter queue (NFQUEUE) interface)
24.usbmon1 (USB bus number 1)
25.usbmon2 (USB bus number 2)

对任意接口进行抓包

1
2
# tcpdump -i any
# tcpdump -i any -n -s 0 -A dst port 443 -c 100 -vvv -w packets.pcap

使用!符号排除特定条件

1
2
3
4
# 不抓取目标端口是22的数据包
dst port ! 22
# 不抓取目标端口是80的数据包
src port ! 80

抓取来自特定IP的包

1
tcpdump port 8002 and host 172.168.11.12
  • host 172.168.11.12: 指定特定IP

Docker容器抓包

在docker容器内安装tcpdunmp工具

在宿主机上使用tcpdump对容器内抓包

  • 获取容器进程ID,即PID

    1
    2
    3
    4
    5
    # 获取容器Id/Name
    docker ps|grep xxx

    # 获取容器进程PID
    docker inspect --format "{{.State.Pid}}" container_id/name
  • 使用nsenter切换网络命名空间

    1
    nsenter -n -t PID
  • 切换后使用ifconfig查看网络接口信息

  • 切换成功后,使用tcpdump工具来进行网络抓包

使用tcpdump实时监控网络速度

1
2
3
# tcpdump -i eno1 -w - |pv -bert > /dev/null
tcpdump: listening on eno1, link-type EN10MB (Ethernet), capture size 262144 bytes
140KiB 0:00:10 [15.6KiB/s]

tcpdump输出内容说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# tcpdump -n -i en5 tcp and port 22 and host 192.168.11.216 -c 100 -S
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on en5, link-type EN10MB (Ethernet), snapshot length 524288 bytes
14:46:07.020782 IP 192.168.11.58.60569 > 192.168.11.216.22: Flags [S], seq 3367572248, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 279150261 ecr 0,sackOK,eol], length 0
14:46:07.021116 IP 192.168.11.216.22 > 192.168.11.58.60569: Flags [S.], seq 2332834302, ack 3367572249, win 65160, options [mss 1460,sackOK,TS val 2954351820 ecr 279150261,nop,wscale 7], length 0
14:46:07.021205 IP 192.168.11.58.60569 > 192.168.11.216.22: Flags [.], ack 2332834303, win 2058, options [nop,nop,TS val 279150261 ecr 2954351820], length 0
14:46:07.021772 IP 192.168.11.58.60569 > 192.168.11.216.22: Flags [P.], seq 3367572249:3367572270, ack 2332834303, win 2058, options [nop,nop,TS val 279150262 ecr 2954351820], length 21: SSH: SSH-2.0-OpenSSH_9.4
14:46:07.022124 IP 192.168.11.216.22 > 192.168.11.58.60569: Flags [.], ack 3367572270, win 509, options [nop,nop,TS val 2954351821 ecr 279150262], length 0
// ... 中间信息略
14:46:13.601422 IP 192.168.11.58.60569 > 192.168.11.216.22: Flags [P.], seq 3367575486:3367575522, ack 2332838196, win 2048, options [nop,nop,TS val 279156842 ecr 2954358400], length 36
14:46:13.601449 IP 192.168.11.58.60569 > 192.168.11.216.22: Flags [P.], seq 3367575522:3367575582, ack 2332838196, win 2048, options [nop,nop,TS val 279156842 ecr 2954358400], length 60
14:46:13.601494 IP 192.168.11.58.60569 > 192.168.11.216.22: Flags [F.], seq 3367575582, ack 2332838196, win 2048, options [nop,nop,TS val 279156842 ecr 2954358400], length 0
14:46:13.601815 IP 192.168.11.216.22 > 192.168.11.58.60569: Flags [.], ack 3367575583, win 501, options [nop,nop,TS val 2954358401 ecr 279156842], length 0
14:46:13.605522 IP 192.168.11.216.22 > 192.168.11.58.60569: Flags [F.], seq 2332838196, ack 3367575583, win 501, options [nop,nop,TS val 2954358405 ecr 279156842], length 0
14:46:13.605632 IP 192.168.11.58.60569 > 192.168.11.216.22: Flags [.], ack 2332838197, win 2048, options [nop,nop,TS val 279156846 ecr 2954358405], length 0
标志 3字符缩写 描述
S SYN 表示开始连接
F FIN 表示结束连接
R RST 复位连接
P PSH 表示数据推送
. 没有标记,一般是确认
  • 14:46:07.020782 IP 192.168.11.58.60569 > 192.168.11.216.22: Flags [S], seq 3367572248, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 279150261 ecr 0,sackOK,eol], length 0
    • 格式为 时间戳 源 > 目标 : 标志