tcpdump可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。
一、Ref
- Man-Page:http://www.tcpdump.org/tcpdump_man.html
- tcpdump:https://github.com/the-tcpdump-group/tcpdump.git
- libpcap:https://github.com/the-tcpdump-group/libpcap.git
- Linux tcpdump命令详解:http://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html
二、命令
tcpdump [ -AbdDefhHIJKlLnNOpqStuUvxX# ] [ -B buffer_size ]
[ -c count ]
[ -C file_size ] [ -G rotate_seconds ] [ -F file ]
[ -i interface ] [ -j tstamp_type ] [ -m module ] [ -M secret ]
[ --number ] [ -Q in|out|inout ]
[ -r file ] [ -V file ] [ -s snaplen ] [ -T type ] [ -w file ]
[ -W filecount ]
[ -E spi@ipaddr algo:secret,... ]
[ -y datalinktype ] [ -z postrotate-command ] [ -Z user ]
[ --time-stamp-precision=tstamp_precision ]
[ --immediate-mode ] [ --version ]
[ expression ]
三、举例
1、使用tcpdump抓取HTTP包
// 0x4745 为"GET"前两个字母"GE",0x4854 为"HTTP"前两个字母"HT"
sudo tcpdump -XvvennSs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854
2、Http GET
sudo tcpdump -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
3、Http POST
sudo tcpdump -s 0 -A 'tcp dst port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354)'
4、过滤如下请求:POST /collect/v2/app_log/
// 可以用https://www.wireshark.org/tools/string-cf.html这个工具来快速获得过滤的表达式
sudo tcpdump -XvvennSs 0 -i eth0 -A 'tcp dst port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354 && tcp[((tcp[12:1] & 0xf0) >> 2) + 4:4] = 0x202f636f && tcp[((tcp[12:1] & 0xf0) >> 2) + 8:4] = 0x6c6c6563 && tcp[((tcp[12:1] & 0xf0) >> 2) + 12:4] = 0x742f7632 && tcp[((tcp[12:1] & 0xf0) >> 2) + 16:4] = 0x2f617070 && tcp[((tcp[12:1] & 0xf0) >> 2) + 20:4] = 0x5f6c6f67 && tcp[((tcp[12:1] & 0xf0) >> 2) + 24:1] = 0x2f)' -w 1.cap
5、打印所有源或目的端口是80, 网络层协议为IPv4, 并且含有数据,而不是SYN,FIN以及ACK-only等不含数据的数据包
sudo tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
(nt: 可理解为, ip[2:2]表示整个ip数据包的长度, (ip[0]&0xf)<<2)表示ip数据包包头的长度(ip[0]&0xf代表包中的IHL域, 而此域的单位为32bit, 要换算
成字节数需要乘以4, 即左移2. (tcp[12]&0xf0)>>4 表示tcp头的长度, 此域的单位也是32bit, 换算成比特数为 ((tcp[12]&0xf0) >> 4) << 2,
即 ((tcp[12]&0xf0)>>2). ((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0 表示: 整个ip数据包的长度减去ip头的长度,再减去
tcp头的长度不为0, 这就意味着, ip数据包中确实是有数据.对于ipv6版本只需考虑ipv6头中的’Payload Length’ 与 ‘tcp头的长度’的差值, 并且其中表达方式’ip[]’需换成’ip6[]’.)