前言:
linux下tcpdump的地位可类比为windows下的wireshark,二者在语法和过滤条件上都是相通的
基础语法:
- 过滤主机
抓取所有经过eth1,目的或源地址是192.168.1.1的网络数据
tcpdump -i eth1 host 192.168.1.1
指定源地址
tcpdump -i eth1 src host 192.168.1.1
指定目的地址
tcpdump -i eth1 dst host 192.168.1.1
- 过滤端口
抓取所有经过eth1,目的或源端口是25的网络数据
tcpdump -i eth1 port 25
指定源端口
tcpdump -i eth1 src port 25
指定目的端口
tcpdump -i eth1 dst port 25
- 过滤网段
tcpdump -i eth1 net 192.168
tcpdump -i eth1 src net 192.168
tcpdump -i eth1 dst net 192.168
- 协议过滤
tcpdump -i eth1 arp
tcpdump -i eth1 ip
tcpdump -i eth1 tcp
tcpdump -i eth1 udp
tcpdump -i eth1 icmp
- 常用表达式
非 : ! or "not" (去掉双引号)
且 : && or "and"
或 : || or "or"
抓取所有经过eth1,目的地址是192.168.1.254或192.168.1.200端口是80的TCP数据
tcpdump -i eth1 '((tcp) and (port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))'
抓取所有经过eth1,目标MAC地址是00:01:02:03:04:05的ICMP数据
tcpdump -i eth1 '((icmp) and ((ether dst host 00:01:02:03:04:05)))'
抓取所有经过eth1,目的网络是192.168,但目的主机不是192.168.1.200的TCP数据
tcpdump -i eth1 '((tcp) and ((dst net 192.168) and (not dst host 192.168.1.200)))'
进阶用法:
首先了解如何从包头过滤信息:
(这里的proto指某种协议,比如tcp,ip,tipc等等,可以直接把proto换成相应的协议名)
(这里x,y都是字节数,不是“比特位”)
proto[x:y] : 过滤从x字节开始的y“字节数”。比如ip[2:2]过滤出3、4字节(第一字节从0开始排)
proto[x:y] & z = 0 : proto[x:y]和z的与操作为0 (可以用来过滤报文中某一段字节是否为某个值)
proto[x:y] & z !=0 : proto[x:y]和z的与操作不为0 (可以用来过滤报文中某一段字节是否为某个值)
proto[x:y] & z = z : proto[x:y]和z的与操作为z (可以用来过滤报文中某一段字节是否为某个值)
proto[x:y] = z : proto[x:y]等于z (可以用来过滤报文中某一段字节是否为某个值)
操作符 :
>, <, >=, <=, =, !=
例如:(判断ip协议的第一个字节“按位与”15(0x0f)之后的值)
tcpdump -i eth1 'ip[0] & 15 > 5'
或者
tcpdump -i eth1 'ip[0] & 0x0f > 5'
tcpdump考虑了一些数字恐惧症者的需求,提供了部分常用的字段偏移名字:
icmptype (ICMP类型字段)
icmpcode (ICMP符号字段)
tcpflags (TCP标记字段)
ICMP类型值有:
icmp-echoreply, icmp-unreach, icmp-sourcequench, icmp-redirect, icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob, icmp-tstamp, icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq, icmp-maskreplyTCP标记值:
tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-push, tcp-ack, tcp-urg
这样上面按照TCP标记位抓包的就可以写直观的表达式了:
只抓SYN包:
tcpdump -i eth1 'tcp[tcpflags] = tcp-syn'
抓SYN, ACK:
tcpdump -i eth1 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0'
例子:
抓SMTP数据:
tcpdump -i eth1 '((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))'
抓取数据区开始为"MAIL"的包,"MAIL"的十六进制为0x4d41494c。
抓HTTP GET数据
tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x47455420'
"GET "的十六进制是47455420
抓SSH返回
tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x5353482D'
"SSH-"的十六进制是0x5353482D
tcpdump -i eth1 '(tcp[(tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>>2)+4):2] = 0x312E)'
抓老版本的SSH返回信息,如"SSH-1.99.."
*****注:从上面这些看出,HTTP,SMTP和SSH都是TCP包的一种类型,时寄生在TCP报文中的自定义应用数据结构*****
一些技巧:
保存抓包数据到文件:
如果是为了查看数据内容,建议用“tcpdump -s 0 -w filename”把数据包都保存下来,然后用wireshark的Follow TCP Stream/Follow UDP Stream来查看整个会话内容。
-s 0是抓取完整数据包,否则默认只抓68字节。
数据量过大会导致宕机:
-c参数对于运维人员来说也比较常用,因为流量比较大的服务器,靠人工CTRL+C还是抓的太多,甚至导致服务器宕机,于是可以用-c参数指定抓多少个包。
计算抓包时间:
time tcpdump -nn -i eth0 'tcp[tcpflags] = tcp-syn' -c 10000 > /dev/null
上面的命令计算抓10000个SYN包花费多少时间,可以判断访问量大概是多少。