你们好,我是肖邦,这是个人第 11 篇原创文章。php
今天要分享的是 tcpdump
,它是 Linux 系统中特别有用的网络工具,一般用于故障诊断、网络分析,功能很是的强大。面试
相对于其它 Linux 工具而言,tcpdump
是复杂的。固然我也不推荐你去学习它的所有,学以至用,可以解决工做中的问题才是关键。编程
本文会从应用场景和基础原理出发,提供丰富的实践案例,让你快速的掌握 tcpdump
的核心使用方法,足以应对平常工做的需求。api
在平常工做中遇到的不少网络问题均可以经过 tcpdump 优雅的解决:ruby
1. 相信大多数同窗都遇到过 SSH 链接服务器缓慢,经过 tcpdump 抓包,能够快速定位到具体缘由,通常都是由于 DNS 解析速度太慢。bash
2. 当咱们工程师与用户面对网络问题争执不下时,经过 tcpdump 抓包,能够快速定位故障缘由,轻松甩锅,毫无压力。服务器
3. 当咱们新开发的网络程序,没有按照预期工做时,经过 tcpdump 收集相关数据包,从包层面分析具体缘由,让问题迎刃而解。微信
4. 当咱们的网络程序性能比较低时,经过 tcpdump 分析数据流特征,结合相关协议来进行网络参数优化,提升系统网络性能。网络
5. 当咱们学习网络协议时,经过 tcpdump 抓包,分析协议格式,帮助咱们更直观、有效、快速的学习网络协议。app
上述只是简单罗列几种常见的应用场景,而 tcpdump 在网络诊断、网络优化、协议学习方面,确实是一款很是强大的网络工具,只要存在网络问题的地方,总能看到它的身影。
熟练的运用 tcpdump
,能够帮助咱们解决工做中各类网络问题,下边咱们先简单学习下它的工做原理。
tcpdump 是 Linux 系统中很是有用的网络工具,运行在用户态,本质上是经过调用 libpcap
库的各类 api
来实现数据包的抓取功能。
经过上图,咱们能够很直观的看到,数据包到达网卡后,通过数据包过滤器(BPF)筛选后,拷贝至用户态的 tcpdump 程序,以供 tcpdump 工具进行后续的处理工做,输出或保存到 pcap 文件。
数据包过滤器(BPF)主要做用,就是根据用户输入的过滤规则,只将用户关心的数据包拷贝至 tcpdump,这样可以减小没必要要的数据包拷贝,下降抓包带来的性能损耗。
思考:这里分享一个真实的面试题
面试官:若是某些数据包被 iptables 封禁,是否能够经过 tcpdump 抓到包?
经过上图,咱们能够很轻易的回答此问题。
由于 Linux 系统中 netfilter
是工做在协议栈阶段的,tcpdump 的过滤器(BPF)工做位置在协议栈以前,因此固然是能够抓到包了!
咱们理解了 tcpdump 基本原理以后,下边直接进入实战!
咱们先经过几个简单的示例来介绍 tcpdump 基本用法。
1. 不加任何参数,默认状况下将抓取第一个非 lo 网卡上全部的数据包
$ tcpdump
2. 抓取 eth0 网卡上的全部数据包
$ tcpdump -i eth0
3. 抓包时指定 -n
选项,不解析主机和端口名。这个参数很关键,会影响抓包的性能,通常抓包时都须要指定该选项。
$ tcpdump -n -i eth0
4. 抓取指定主机 192.168.1.100
的全部数据包
$ tcpdump -ni eth0 host 192.168.1.100
5. 抓取指定主机 10.1.1.2
发送的数据包
$ tcpdump -ni eth0 src host 10.1.1.2
6. 抓取发送给 10.1.1.2
的全部数据包
$ tcpdump -ni eth0 dst host 10.1.1.2
7. 抓取 eth0 网卡上发往指定主机的数据包,抓到 10 个包就中止,这个参数也比较经常使用
$ tcpdump -ni eth0 -c 10 dst host 192.168.1.200
8. 抓取 eth0 网卡上全部 SSH 请求数据包,SSH 默认端口是 22
$ tcpdump -ni eth0 dst port 22
9. 抓取 eth0 网卡上 5 个 ping 数据包
$ tcpdump -ni eth0 -c 5 icmp
10. 抓取 eth0 网卡上全部的 arp 数据包
$ tcpdump -ni eth0 arp
11. 使用十六进制输出,当你想检查数据包内容是否有问题时,十六进制输出会颇有帮助。
$ tcpdump -ni eth0 -c 1 arp -X
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:13:31.602995 ARP, Request who-has 172.17.92.133 tell 172.17.95.253, length 28
0x0000: 0001 0800 0604 0001 eeff ffff ffff ac11 ................
0x0010: 5ffd 0000 0000 0000 ac11 5c85 _.........\.
12. 只抓取 eth0 网卡上 IPv6 的流量
$ tcpdump -ni eth0 ip6
13. 抓取指定端口范围的流量
$ tcpdump -ni eth0 portrange 80-9000
14. 抓取指定网段的流量
$ tcpdump -ni eth0 net 192.168.1.0/24
tcpdump 强大的功能和灵活的策略,主要体如今过滤器(BPF)强大的表达式组合能力。
本节主要分享一些常见的所谓高级用法,但愿读者可以触类旁通,根据本身实际需求,来灵活使用它。
1. 抓取指定客户端访问 ssh 的数据包
$ tcpdump -ni eth0 src 192.168.1.100 and dst port 22
2. 抓取从某个网段来,到某个网段去的流量
$ tcpdump -ni eth0 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 eth0 src 10.0.2.4 and not dst port 22
4. 当构建复杂查询的时候,你可能须要使用引号,单引号告诉 tcpdump 忽略特定的特殊字符,这里的 ()
就是特殊符号,若是不用引号的话,就须要使用转义字符
$ tcpdump -ni eth0 'src 10.0.2.4 and (dst port 3389 or 22)'
5. 基于包大小进行筛选,若是你正在查看特定的包大小,可使用这个参数
小于等于 64 字节:
$ tcpdump -ni less 64
大于等于 64 字节:
$ tcpdump -ni eth0 greater 64
等于 64 字节:
$ tcpdump -ni eth0 length == 64
6. 过滤 TCP 特殊标记的数据包
抓取某主机发送的 RST
数据包:
$ tcpdump -ni eth0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-rst) != 0'
抓取某主机发送的 SYN
数据包:
$ tcpdump -ni eth0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-syn) != 0'
抓取某主机发送的 FIN
数据包:
$ tcpdump -ni eth0 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)) - ((tcp[12]&0xf0)>>2)) != 0)'
解释一下这个复杂的表达式,具体含义就是,整个 IP 数据包长度减去 IP 头长度,再减去 TCP 头的长度,结果不为 0,就表示数据包有 data
,若是还不是很理解,须要自行补一下 tcp/ip
协议
9. 抓取 HTTP 报文,0x4754
是 GET
前两字符的值,0x4854
是 HTTP
前两个字符的值
$ tcpdump -ni eth0 'tcp[20:2]=0x4745 or tcp[20:2]=0x4854'
经过上述的实战案例,相信你们已经掌握的 tcpdump
基本用法,在这里来详细总结一下经常使用的选项参数。
(一)基础选项
-i
:指定接口-D
:列出可用于抓包的接口-s
:指定数据包抓取的长度-c
:指定要抓取的数据包的数量-w
:将抓包数据保存在文件中-r
:从文件中读取数据-C
:指定文件大小,与 -w
配合使用-F
:从文件中读取抓包的表达式-n
:不解析主机和端口号,这个参数很重要,通常都须要加上-P
:指定要抓取的包是流入仍是流出的包,能够指定的值 in
、out
、inout
(二)输出选项
-e
:输出信息中包含数据链路层头部信息-t
:显示时间戳,tttt
显示更详细的时间-X
:显示十六进制格式-v
:显示详细的报文信息,尝试 -vvv
,v
越多显示越详细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
:表示非操做建议看到这里后,再回头去看实战篇章的示例,相信一定会有更深的理解。若是是这样,那就达到了我预期的效果了!
到这里就再也不加新知识点了,分享一些工做中总结的经验:
1. 咱们要知道 tcpdump
不是万能药,并不能解决全部的网络问题。
2. 在高流量场景下,抓包可能会影响系统性能,若是是在生产环境,请谨慎使用!
3. 在高流量场景下,tcpdump
并不适合作流量统计,若是须要,可使用交换机镜像的方式去分析统计。
4. 在 Linux 上使用 tcpdump
抓包,结合 wireshark
工具进行数据分析,能事半功倍。
5. 抓包时,尽量不要使用 any
接口来抓包。
6. 抓包时,尽量指定详细的数据包过滤表达式,减小无用数据包的拷贝。
7. 抓包时,尽可能指定 -n
选项,减小解析主机和端口带来的性能开销。
经过上述内容,咱们知道 tcpdump 是一款功能强大的故障诊断、网络分析工具。在咱们的平常工做中,遇到的网络问题老是可以经过 tcpdump 来解决。
不过 tcpdump 相对于其它 Linux 命令来讲,会复杂不少,但鉴于它强大功能的诱惑力,咱们多花一些时间是值得的。要想很好地掌握 tcpdump,须要对网络报文(TCP/IP
协议)有必定的了解。
固然,对于简单的使用来讲,只要有网络基础概念就行,掌握了 tcpdump 经常使用方法,就足以应付工做中大部分网络相关的疑难杂症了。
推荐阅读:
本次分享就到这里了,谢谢你们的阅读,我是肖邦。关注个人公众号「编程修养」,大量的干货文章等你来!
公众号后台回复「1024」有惊喜!
欢迎各位老铁,加肖邦的我的微信,技术交流!!