tcpdump入门

By | 09/18/2015
这篇文章写的

为什么要了解tcpdump?

tcpdump 是一款Linux下强大的基于命令行的网络流量包分析工具。

尽管很多人宁愿选择Wireshark等工具,但大部分服务器并没有图形界面环境。
若要快速的分析网络异常或者获取流量包数据,还是非 tcpdump 莫属。

对于开发网络应用而言, tcpdump 实在是上上之品啊。

用法

tcpdump options expressions

选项options

对于许多linux命令而言,其命令行参数复杂地让人怀疑自己,比如 findgrep .
tcpdump 同样包含了从 -a ~ -z 的选项。

面对如此繁多的选项,站在门口的我们该从何开始呢?

我们可以从最为常用的、也是最基本的一些选项开始。

-n 表示不将域名转换成名字。 -nn 表示不将域名/端口等转换为名字,如http表示80等。

TCP协议中包含sequence numbers,tcpdump默认将输出相对的(相对于发出此包的进程的包数)。

加上 -S 后,则会输出绝对的sequence numbers.
tcpdump 默认只会打印出每个包的部分信息:源地址、源端口、目标地址、目标端口、seq、length等。

若想进一步探究,查看整个数据包,可以加上 -X-XX .

这样 tcpdump 会输出包含 ASCIIhex 的详细包内容。

当然,默认情况下 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 acenot 到底是跟 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表达式语法。

这篇文章对我来说它是知识的一次总结:)

当然,如果有任何探讨/疑义,欢迎留言或联系我。

参考文献

  1. man tcpdump
  2. man 7 pcap-filter

One thought on “tcpdump入门

发表评论

电子邮件地址不会被公开。 必填项已用*标注