为什么要了解tcpdump?¶
tcpdump 是一款Linux下强大的基于命令行的网络流量包分析工具。
尽管很多人宁愿选择Wireshark等工具,但大部分服务器并没有图形界面环境。
若要快速的分析网络异常或者获取流量包数据,还是非 tcpdump 莫属。
对于开发网络应用而言, tcpdump 实在是上上之品啊。
用法¶
tcpdump options expressions
选项options¶
对于许多linux命令而言,其命令行参数复杂地让人怀疑自己,比如 find 、 grep .
tcpdump 同样包含了从 -a ~ -z 的选项。
面对如此繁多的选项,站在门口的我们该从何开始呢?
我们可以从最为常用的、也是最基本的一些选项开始。
-n 表示不将域名转换成名字。 -nn 表示不将域名/端口等转换为名字,如http表示80等。
TCP协议中包含sequence numbers,tcpdump默认将输出相对的(相对于发出此包的进程的包数)。
加上 -S 后,则会输出绝对的sequence numbers.
tcpdump 默认只会打印出每个包的部分信息:源地址、源端口、目标地址、目标端口、seq、length等。
若想进一步探究,查看整个数据包,可以加上 -X 或 -XX .
这样 tcpdump 会输出包含 ASCII 和 hex 的详细包内容。
当然,默认情况下 tcpdump 只会打印出65535字节的包内容。
若想得到更多包信息,加上 -s snaplen bytes 参数可以选择打印指定字节数的内容。
当使用 -s 0 时,会打出整个包的内容。
还有一个常用的参数是 -c count :在捕捉到 count 个包后结束 tcpdump 程序。
那我们就以捕捉ping包作为例子学习 tcpdump 的使用方法。
我们都知道ping包是基于ICMP协议的。
实验环境:多张网卡,p5p1连接到外网。 捕捉任意网卡上的icmp协议包:
tcpdump -i any icmp
-i:指定捕捉的网卡,any表示任意网卡
Hint
如何获取系统所有的网卡?
tcpdump -D
ifconfig -s
netstat -i
捕捉一个完整的ping交互(ping/pong):
tcpdump -i p5p1 icmp -c 2 -S
查看真实的地址IP:
tcpdump -i p5p1 icmp -c 2 -S -nn
捕捉完整的ICMP包:
tcpdump -i p5p1 icmp -S -nn -s 0 -XX
捕捉所有80端口(包括源端口和目标端口)的请求:
tcpdump -i p5p1 port 80
进阶:表达式expression¶
恭喜你现在已经能用tcpdump来观察网络流量了。但服务器大流量的情况下,如何捕捉到自己想要跟踪的流量包呢?
这个时候就需要用到expression了。
为什么要单独提expression?
因为它在tcpdump里面属于一块独立的篇章,
linux中man手册有一章专门介绍了expression,也就是pcap-filter。
可以说掌握tcpdump的一个标准就是是否能够灵活使用pcap-filter表达式。
tcpdump 命令行中的expression主要用来选择捕获哪些流量包。
如果不加expression,所有的网络流量包都会被捕获。
否则,只捕获那些使expression为真的流量包。
表达式包含三种可能的限定符(qualifier):
- type
- host
- net
- port
- portrange
- dir
- src
- dst
- src or dst
- src and dst
- proto
- ip/ip6
- arp/rarp
- tcp
- udp
- ether
- fddi
- tr
- decnet
此外,还有一些关键字不符合这些表达式的,比如gateway、broadcast等。还包括greater、less等用来根据包大小过滤。
而这些primitives可以使用一些combinator来连接。
- and
- or
- not
或者使用符号
- &&
- ||
- >/>=
- </<=
- =/!=
- !
对于复杂的表达式分组,pcap还提供了一系列默认的优先级组合。
比如 not/! 具有最高的优先级, and/&& 、 or/|| 具有同等优先级且是从左到右进行组合。
比如如果标识符没有任何关键字,那么使用最近的关键字。E.g:
not host vs and ace
表示
not host vs and host ace
而不是
not (host vs or ace)。
看到这里是不是有点头大而想起了大学挂掉的C语言操作符优先级?
上例中 not host vs and host ace 中 not 到底是跟 host vs 还是跟 host ace 组合的,还是同时组合的呢?
不用担心,我也没有弄明白:)。但凡遇到可能使逻辑变得复杂的跟优先级相关的操作符,就使用括号(())来分组。
使用 (not host vs) and(not host ace) 或者 not (host vs and host ace) 来表达出你想要的效果来吧。
比进阶更进阶:字节位和比特位¶
tcpdump -i any '(icmp[0] & 0xff == 8) or icmp[0] & 0xff == 0' -XXnS -s 0
当然,tcpdump内置了一些标志和值,支持特定包的过滤。
ICMP协议中有icmptype/icmpcode和对应的值:icmp-echoreply/icmp-echo/icmp-tsstamp/icmp-tsstampreply等。
TCP协议中有tcpflags和对应的值:
- tcp-fin
- tcp-syn
- tcp-rst
- tcp-push
- tcp-ack
- tcp-urg
tcpdump -i any '(icmp[icmptype] == icmp-echo) or (icmp[icmptype] == icmp-echoreply)' -XXnS -s 0
捕捉所有tcpflag:
.. code-block:: bash
tcpdump -i any ‘tcp[tcpflag] == tcp-fin’ -XXnS -s 0
tcpdump -i any 'tcp[tcpflag] == tcp-syn' -XXnS -s 0
tcpdump -i any 'tcp[tcpflag] == tcp-rst' -XXnS -s 0
tcpdump -i any 'tcp[tcpflag] == tcp-push' -XXnS -s 0
tcpdump -i any 'tcp[tcpflag] == tcp-ack' -XXnS -s 0
tcpdump -i any 'tcp[tcpflag] == tcp-urg' -XXnS -s 0
总结¶
本篇文章提供了 tcpdump 的入门参考:包括 tcpdump 的命令格式、常用选项以及更为高级的pcap-filter表达式语法。
这篇文章对我来说它是知识的一次总结:)
当然,如果有任何探讨/疑义,欢迎留言或联系我。
参考文献¶
- man tcpdump
- man 7 pcap-filter