tcpdump
是个Linux抓包工具,由于它是命令行的,打印出来的东西也是纯文本的,可以输出为pcap类型后用wireshark解析,其本身不支持GUI。
tcpdump基本功能
使用$tcpdump --help
打印出这么堆东西:
tcpdump [ -AbdDefhHIJKlLnNOpqStuUvxX# ] [ -B buffer_size ]
[ -c count ] [ -C file_size ]
[ -E spi@ipaddr algo:secret,... ]
[ -F file ] [ -G rotate_seconds ] [ -i interface ]
[ --immediate-mode ] [ -j tstamp_type ] [ -m module ]
[ -M secret ] [ --number ] [ --print ] [ -Q in|out|inout ]
[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]
[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]
[ -z postrotate-command ] [ -Z user ]
[ --time-stamp-precision=tstamp_precision ]
[ expression ]
简单看一下,除了最后的[expression]
之外都只是一些参数,参数在最下面,表达式比较重要,如果一个数据包根据expression得出true
结果,那就是应该打印的,否则就不打印。先来看看基本的使用:
-i
:指定接口,比如eth0、lan0等。$ifconfig
可以查看,注意127.0.0.1是属于lo接口。比如这样指定:
$tcpdump -i eth0
port
:指定端口。如果只关心某个端口那就好了,打印的内容必定少了许多。比如这样指定:
$tcpdump -i eth0 port 80
dst
、src
、host
这三个关键字分别用于增加限制"目的端"、"源端"、"地址"。用起来像这样:
$tcpdump -i eth0 src host 192.168.1.103
src同样可以用在port上面,就是表示源端口的意思。注意,那些前面带有-
的才是参数,比如-i
,而那些没有的,就是个关键字,它们是不能一块写的,比如这样就不对:
$tcpdump -i eth0 src host 192.168.1.103 port 80
这port
和host
是起限制作用的关键字,不能直接这样拼接的,正确用法是用and
关键字,可以换成下面这样就合法了:
$tcpdump -i wlan0 src host 192.168.1.103 and port 80
如果关心的是某个网段而不是具体到某个ip,可以指定一个范围就像这样:
$tcpdump -i wlan0 net 192.168
相当于
$tcpdump -i wlan0 net 192.168.0.1/16
现在范围已经比较小了,但是我们往往只关心某个协议,毕竟多个协议放一块,太不直观了。可以这样指定协议:
$tcpdump -i wlan0 ip src host 192.168.1.103 and port 80
其实and
是个逻辑操作符,同样类型的还有or
和not
两个操作符,如果嫌不直观就用符号吧,分别对应&&
、||
、!
。它还允许复杂式子用括号改变优先级,比如这样:
$tcpdump -i wlan0 ip src host 192.168.1.103 && ! \(port 80 or 23\)
注意转义两个括号符号,它们是在bash shell里面的。也别写冲突了,比如src host xxx && src host yyy
就不可能有符合的情况,tcpdump就会提示你 expression rejects all packets。表达式写得不好就会显示syntax error或者illegal xxx什么的。
综上,expression就是由一个至多个子表达式[proto] [dir] [type]
搭配逻辑符号构成,其中
-
proto
表示协议,可以是ether
、fddi
、tr
、wlan
、ip
、ip6
、arp
、rarp
、decnet
、tcp
、udp
,默认协议是所有。 -
dir
表示方向,可以是dst
、src
、dst && src
、dst || src
(默认)、ra
、ta
、addr1
、addr2
、addr3
、addr4
,后六个仅可用于802.11 Wireless LAN link layers。 -
type
表示类型,可以是net
、port
、portrange
、host
(默认)。
示例:
$tcpdump -n "dst host 192.168.1.1 && (dst port 80 or dst port 443)"
更多细节请参考expression手册
现在开始挖一挖tcpdump提供的选项效果,首先是不带参数的选项:
-A 以ASCII编码输出。
-b BGP协议相关的选项,不解释了。
-d
-D 列出能监听的网卡interface,比如eth0,wlan0等等,-i选项所带的参数。
-e 显示数据链路层的报头。
-f
-h
-H
-I
-J
-K
-l
-L
-n 显示地址而不是hostname。
-nn 显示端口号和地址,而不是hostname和服务,比如默认会将端口号80显示成"http"等,加上这个选项后就不会这样了。这个命令很重要:有一次在远程机器上抓包没有加此选项,tcpdump需要30秒以上才输出结果,而且ctrl+c还杀不掉tcpdump,然后加上这个选项就正常了。
-N
-O
-p
-q 精简输出。
-S 显示绝对TCP序号,默认是相对的,即从1开始。
-u
-U
-t 不输出时间戳。下面四个是指定时间戳格式的。
-tt
-ttt
-tttt
-ttttt
-v 让输出详细些。
-vv 让输出更详细些。
-vvv 让输出最详细。
-x 这两个都是十六进制输出,格式比较易看。
-X 比上面多打印出ASCII码。
-xx 这两个也是十六进制输出,但是比上面两个多一个数据链路层报头。
-XX
接下来是带参数值的选项:
[ -B buffer_size ]
指定缓冲区大小,单位是千字节。
[ -c count ]
指定捕获包的数量
[ -C file_size ]
[ -E spi@ipaddr algo:secret,... ]
[ -F file ]
[ -G rotate_seconds ]
[ -i interface ]
指定网卡,默认是其中一个,用-D看哪些可用,any指代所有,lo指代本机通讯包。
[ --immediate-mode ]
[ -j tstamp_type ]
[ -m module ]
[ -M secret ]
[ --number ]
[ --print ]
[ -Q in|out|inout ]
[ -r file ]
从文件中解析出包的信息并输出,file就是-w所保存的那种文件。可以用-
从标准输入读取。
[ -s snaplen ]
指定所捕获包的长度,默认是68B,若为0则是整个包。
[ -T type ]
[ --version ]
[ -V file ]
从file中读取多个文件名,应该同-r的性质差不多。
[ -w file ]
将输出到终端改成以pcap格式输出到文件。
[ -W filecount ]
[ -y datalinktype ]
[ -z postrotate-command ]
[ -Z user ]
[ --time-stamp-precision=tstamp_precision ]
比较常用的格式是先列出要监听的网卡:
$tcpdump -D
从中挑选一个(比如eth0)后开始监听ICMP包:
$sudo tcpdump -i eth0 -x -vvv -n -s 0 icmp
监听所有包一般要保存到文件中:
$sudo tcpdump -i eth0 -x -nnv -s0 -w test.pcap
保存的pcap文件解析后打印出来:
$sudo tcpdump -x -vvv -r test.pcap
高级筛选
expression还可以详细到指定报文中的某个field的值,不过还是建议都抓下来后用wireshark分析,待续~
编辑pcap文件
pcap文件中的包可以进行裁剪,删除,过滤。如果能通过wireshark的过滤器进行筛选出必要的包,那么久可以点击【选择特定分组】进行导出这部分包。
如果想要筛选的包是没有规则可言的,或者不好过滤,那就通过editcap
工具来编辑它,下面是几个常用命令。
删除指定编号2的报文:
editcap in.pcap out.pcap 2
留下指定编号范围1~5的报文:
editcap -r in.pcap out.pcap 1-5
如果是要合并几个pcap文件,可以适用mergecap
工具,下面是几个常用命令。
将3个in文件合成out.pcap输出:
mergecap -w out.pcap in1.pcap in2.pcap in3.pcap
作者:xcw0754
水平有限,若有疏漏,欢迎指出。