tcpdump 是 Linux 系统中非常有用的网络工具,运行在用户态,本质上是通过调用 libpcap 库的各种
api 来实现数据包的抓取功能,利用内核中的 AF_PACKET 套接字,抓取网络接口中传输的网络包。查 看 tcpdump 的 手册 ,以及 pcap-filter 的手册,tcpdump 提供了大量的选项以及各式各样的过滤表达 式。tcpdump 的输出格式
时间戳 协议 源地址.源端口 > 目的地址.目的端口 网络包详细信息
通过上图,我们可以很直观的看到,数据包到达网卡后,经过数据包过滤器(BPF)筛选后,拷贝至用 户态的 tcpdump 程序,以供 tcpdump 工具进行后续的处理工作,输出或保存到 pcap 文件。 数据包过滤器(BPF)主要作用,就是根据用户输入的过滤规则,只将用户关心的数据包拷贝至 tcpdump,这样能够减少不必要的数据包拷贝,降低抓包带来的性能损耗。
思考:
如果某些数据包被 iptables 封禁,是否可以通过 tcpdump 抓到包?
因为 Linux 系统中 netfilter 是工作在协议栈阶段的,tcpdump 的过滤器(BPF)工作位置在协议栈 之前,所以是可以抓到包的!
实战:基础用法
我们先通过几个简单的示例来介绍 tcpdump 基本用法。
1. 不加任何参数,默认情况下将抓取第一个非 lo 网卡上所有的数据包
$ tcpdump
2. 抓取 wlp3s0 网卡上的所有数据包
$ tcpdump -i wlp3s0
3. 抓包时指定 -n 选项,不解析主机和端口名。这个参数很关键,会影响抓包的性能,一般抓包时都需 要指定该选项。
$ tcpdump -n -i wlp3s0
4. 抓取指定主机 192.168.1.100 的所有数据包
$ tcpdump -ni wlp3s0 host 192.168.1.100
5. 抓取指定主机 10.1.1.2 发送的数据包
$ tcpdump -ni wlp3s0 src host 10.1.1.2
6. 抓取发送给 10.1.1.2 的所有数据包
$ tcpdump -ni wlp3s0 dst host 10.1.1.2
7. 抓取 wlp3s0 网卡上发往指定主机的数据包,抓到 10 个包就停止,这个参数也比较常用
$ tcpdump -ni wlp3s0 -c 10 dst host 192.168.1.200
8. 抓取 wlp3s0 网卡上所有 SSH 请求数据包,SSH 默认端口是 22
$ tcpdump -ni wlp3s0 dst port 22
9. 抓取 wlp3s0 网卡上 5 个 ping 数据包
$ tcpdump -ni wlp3s0 -c 5 icmp
10. 抓取 wlp3s0 网卡上所有的 arp 数据包
$ tcpdump -ni wlp3s0 arp
11. 使用十六进制输出,当想检查数据包内容是否有问题时,十六进制输出会很有帮助。
$ tcpdump -ni wlp3s0 -c 1 arp -X tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on wlp3s0, link-type EN10MB (Ethernet), capture size 262144 bytes 14:38:52.549659 ARP, Request who-has 192.168.0.106 tell 192.168.0.1, length 28 0x0000: 0001 0800 0604 0001 0840 f3d3 ad70 c0a8 [email protected].. 0x0010: 0001 0000 0000 0000 c0a8 006a ...........j
12. 只抓取 wlp3s0 网卡上 IPv6 的流量
$ tcpdump -ni wlp3s0 ip6
13. 抓取指定端口范围的流量
$ tcpdump -ni wlp3s0 portrange 80-9000
14. 抓取指定网段的流量
$ tcpdump -ni wlp3s0 net 192.168.1.0/24
实战:高级进阶
tcpdump 强大的功能和灵活的策略,主要体现在过滤器(BPF)强大的表达式组合能力。
1. 抓取指定客户端访问 ssh 的数据包
$ tcpdump -ni wlp3s0 src 192.168.1.100 and dst port 22
2. 抓取从某个网段来,到某个网段去的流量
$ tcpdump -ni wlp3s0 src net 192.168.1.0/16 and dst net 10.0.0.0/8 or 172.16.0.0/16
3. 抓取来自某个主机,发往非 ssh 端口的流量
$ tcpdump -ni wlp3s0 src 10.0.2.4 and not dst port 22
4. 当构建复杂查询的时候,可能需要使用引号,单引号告诉 tcpdump 忽略特定的特殊字符,这里的
$ tcpdump -ni wlp3s0 'src 10.0.2.4 and (dst port 3389 or 22)'
() 就是特殊符号,如果不用引号的话,就需要使用转义字符
5. 基于包大小进行筛选,如果正在查看特定的包大小,可以使用这个参数 小于等于 64 字节:
$ tcpdump -ni less 64
大于等于 64 字节:
$ tcpdump -ni wlp3s0 greater 64
等于 64 字节:
$ tcpdump -ni wlp3s0 length == 64
6. 过滤 TCP 特殊标记的数据包 抓取某主机发送的 RST 数据包:
$ tcpdump -ni wlp3s0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-rst) != 0'
抓取某主机发送的 SYN 数据包:
$ tcpdump -ni wlp3s0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-syn) != 0'
抓取某主机发送的 FIN 数据包:
$ tcpdump -ni wlp3s0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-fin) != 0'
抓取 TCP 连接中的 SYN 或 FIN 包
$ tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0'
7. 抓取所有非 ping 类型的 ICMP 包
$ tcpdump 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply'
8. 抓取端口是 80,网络层协议为 IPv4, 并且含有数据,而不是 SYN、FIN 以及 ACK 等不含数据的数据 包
$ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)>2)) != 0)'
解释一下这个复杂的表达式,具体含义就是,整个 IP 数据包长度减去 IP 头长度,再减去 TCP 头的长 度,结果不为 0,就表示数据包有 data ,如果还不是很理解,需要自行补一下 tcp/ip 协议
9. 抓取 HTTP 报文, 0x4754 是 GET 前两字符的值, 0x4854 是 HTTP 前两个字符的值
$ tcpdump -ni wlp3s0 'tcp[20:2]=0x4745 or tcp[20:2]=0x4854'
常用选项
常用的选项参数。
(一)基础选项
-i :指定接口
-D :列出可用于抓包的接口
-s :指定数据包抓取的长度
-c :指定要抓取的数据包的数量
-w :将抓包数据保存在文件中
-r :从文件中读取数据
-C :指定文件大小,与 -w 配合使用
-F :从文件中读取抓包的表达式
-n :不解析主机和端口号,这个参数很重要,一般都需要加上
-P :指定要抓取的包是流入还是流出的包,可以指定的值 in 、 out 、 inout
(二)输出选项
-e :输出信息中包含数据链路层头部信息
-t :显示时间戳, tttt 显示更详细的时间
过滤表达式
tcpdump 强大的功能和灵活的策略,主要体现在过滤器(BPF)强大的表达式组合能力。
(一)操作对象
表达式中可以操作的对象有如下几种:
type ,表示对象的类型,比如: host 、 net 、 port 、 portrange ,如果不指定 type 的话,默 认是 host
dir :表示传输的方向,可取的方式为: src 、 dst 。
proto :表示协议,可选的协议有: ether 、 ip 、 ip6 、 arp 、 icmp 、 tcp 、 udp 。
(二)条件组合
表达对象之间还可以通过关键字 and 、 or 、 not 进行连接,组成功能更强大的表达式。
or :表示或操作
and :表示与操作
not :表示非操作
tips
1. 在高流量场景下,抓包可能会影响系统性能,如果是在生产环境,请谨慎使用!
2. 在高流量场景下, tcpdump 并不适合做流量统计,如果需要,可以使用交换机镜像的方式去分析 统计。
3. 在 Linux 上使用 tcpdump 抓包,结合 wireshark 工具进行数据分析,能事半功倍。
4. 抓包时,尽可能不要使用 any 接口来抓包。
5. 抓包时,尽可能指定详细的数据包过滤表达式,减少无用数据包的拷贝。
6. 抓包时,尽量指定 -n 选项,减少解析主机和端口带来的性能开销。
查找可用的网络设备
在 wireshark 能够分析数据包之前,它需要捕获这些数据包。网络数据包通过服务器、工作站或台式机 上的网络接口卡(NIC)或笔记本电脑上的 WiFi 卡进行处理。首先识别用于连接互联网的网卡或 WiFi 卡。
sudo wireshark -D
1. wlp3s0
2. vmnet1
3. vmnet8
4. lo (Loopback)
5. any
6. enp2s0f0
7. enp5s0
8. bluetooth-monitor
9. nflog
10. nfqueue
11. ciscodump (Cisco remote capture)
12. dpauxmon (DisplayPort AUX channel monitor capture)
13. randpkt (Random packet generator)
14. sdjournal (systemd Journal Export)
15. sshdump (SSH remote capture)
16. udpdump (UDP Listener remote capture)
捕获选项
图形化或者命令皆可
1. 命令
sudo wireshark -i wlp3s0
可以使用 -c (count)选项限制捕获和显示在屏幕上的数据包数量。下面的示例显示捕获的10个数据 包
sudo wireshark -i wlp3s0 -c 10
查询出来的线路包括箭头两侧的两个 IP 地址--这两个地址是交换数据包的主机。箭头的方向指示数 据包的前进方向。因此,192.168.0.6→14.215.158.102意味着数据包来源于主机192.168.0.6, 我的笔记本电脑前往目的地14.215.158.102。在目标 IP 地址之后,还有DNS、NTP、tcp等协议,
DNS 协议将主机名转换为 IP 地址,将 IP 地址转换为主机名。有专用的 DNS 服务器,可以使用主 机名或 IP 地址查询 可以通过/etc/resolv.conf查找域名服务器相关信息,然后通过nslookup或者dig解析 先用另一个终端执行
sudo wireshark -i wlp3s0 host 1.1.1.1
然后
dig opensource.com ; > DiG 9.16.1-Ubuntu > opensource.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER33748
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 4
;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1280
; COOKIE: 3fec9b884e3a642d944ac20261b792c57e39c04d210c6ba3 (good) ;; QUESTION SECTION:
;opensource.com. IN A ;; ANSWER SECTION: opensource.com. 600 IN A 54.204.39.132 ;; AUTHORITY SECTION: opensource.com. 150455 IN NS ns1.redhat.com. opensource.com. 150455 IN NS ns3.redhat.com. opensource.com. 150455 IN NS ns2.redhat.com. ;; ADDITIONAL SECTION: ns2.redhat.com. 2680 IN A 209.132.183.2 ns3.redhat.com. 2680 IN A 66.187.233.212 ns1.redhat.com. 2680 IN A 209.132.186.218
只查找某种类型协议
sudo wireshark -i wlp3s0 udp
通过-x将二进转化成十六进制(网络数据包是以二进制格式发送)
sudo wireshark -i wlp3s0 -x -c 2 host x.x.x.x
保存输出
sudo wireshark -w /tmp/nlog.pcap -i wlp3s0 host x.x.x.x file命令查看文件类型
sudo file /tmp/nlog.pcap
读取(pcapng文件不能用vim等查看)
sudo wireshark -r /tmp/nlog.pcap
2. 图形化
点击选择后 有波动线的对应网卡是存在流量交互的,选择一个网卡点击开始,即开始抓包了,更加方便的是双击选 择一个网卡进行抓包,同时还可以选择使用捕获过滤器,抓自己想要的一些包。
混杂模式与非混杂模式的区别
非混杂模式:主机仅嗅探那些跟它直接有关的通信,如发向它的,从它发出的,或经它路由的等都会被 嗅探器捕捉。简单理解就是只接受我们该接受的数据包。
混杂模式:嗅探网卡传输线路上所有的通信,并且在非交换式网络,嗅探的是整个网络中的通信,会因 为的嗅网络原因任何对有用或者没用的包都会抓取,混杂模式同时是可以被探测到,如果在一个高负荷 网络中,主机系统资源消耗会非常严重。
过滤器设置
捕获过滤器
捕获过滤器的菜单栏路径为捕获 --> 捕获过滤器。用于在抓取数据包前设置。或者可以在主界面选择网卡 的时候就选择应用过滤器规则。
显示过滤器
显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对 宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。
我们这里应用的是只显示TCP传输控制协议的数据包,我们在最底下可以看见显示了195个相关的流量 包。
数据包详细信息面板(数据包的结构)主要用来查看协议中的每一个字段。各行信息分别为: (1)Frame: 物理层的数据帧概况 (2)Ethernet II: 数据链路层以太网帧头部信息,端点会话的MAC地址(3)Internet Protocol Version 4: 互联网层IP包头部信息,端点会话IP地址 (4)Transmission Control Protocol: 传输层的数据段头部信息,此处是TCP,端点会话的端口 (5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议
通常一个完整的数据流一般都是由很多个包组成的,如果查看某条数据包数据流的话。可以选中数据, 然后右键选择追踪流。里面就会有TCP流、UDP流、SSL流、HTTP流等。数据包属于哪种流就选择对应 的流,例如上图属于TCP我们就选择追逐TCP流。
包 括 我 们 可 以 选 择 流 之 间 的IP 对 话 , 找 指 定 的 会 话 。
Conversions窗口可以看到两个主机之间发送/接收数据包的数量、字节大小以及数据的流向情况,可以 通过排序来判断占用最大带宽的主机,也可以解析名称,选择作为会话过滤器。
tcpdump 仅支持命令行格式使用,常用在服务器中抓取和分析网络包。Wireshark 除了可以抓包外,还 提供了强大的图形界面和汇总分析工具,因而,可以先用 tcpdump 抓包,后用 Wireshark 分析,可以执 行下面的命令,把抓取的网络包保存到 ping.pcap 文件中:
tcpdump -nn udp port 53 or host 35.190.27.188 -w ping.pcap
接着,把它拷贝到安装有 Wireshark 的机器中进行分析。
tcpdump -nn host 93.184.216.34 -w web.pcap 或者直接使用域名,即 tcpdump -nn host example.com -w web.pcap
执行下面的 curl 命令,访问 http://example.com:
curl http://example.com
最后,再回到终端一,按下 Ctrl+C 停止 tcpdump,并把得到的 web.pcap 拷贝出来。 使用 Wireshark 打开 web.pcap 后,就可以在 Wireshark 中,看到如下的界面:
由于 HTTP 基于 TCP ,所以最先看到的三个包,分别是 TCP 三次握手的包。接下来,中间的才是 HTTP
请求和响应包,而最后的三个包,则是 TCP 连接断开时的三次挥手包。 从菜单栏中,点击 Statistics -> Flow Graph,然后,在弹出的界面中的 Flow type 选择 TCP Flows,可以 更清晰的看到,整个过程中 TCP 流的执行过程:
跟各种教程上讲到的,TCP 三次握手和四次挥手很类似,作为对比, 通常看到的 TCP 三次握手和四次挥 手的流程,基本是这样的: