1. 实操
tcpdump -i 接口 -w 保存的路径 host 主机IP and port 端口号 -s0 -C 包大小
tcpdump -i any -w /test/test.pcap host 127.0.0.1 and port 8001 -s0 -C 100
nohup tcpdump -i ens3 host baidu.com or csdn.com -s0 -C 100 -w ~/test.pcap &
查
ps -ef|grep tcpdump |grep -v 'grep'
直接kill掉进程号就可以关闭掉后台运行的tcpdump了
tcpdump -i any -s0 -G 600 -w %Y_%m%d_%H%M_%S.pcap
tcpdump -D
tcpdump -i eth0
tcpdump -i eth1 host 192.168.0.11 and ! port 80 and ! port 25
tcpdump -i eth1 host 192.168.0.11 -c 10000
协议可以是:ether, fddi, tr, wlan, ip, ip6, arp, rarp, decnet, tcp and udp
sudo tcpdump -i ens33 tcp and ....(其他自定义内容)
2. 抓取
21:26:49.013621 IP 172.20.20.1.15605 > 172.20.20.2.5920: Flags [P.], seq 49:97, ack 106048, win 4723, length 48
第一列:时分秒毫秒 21:26:49.013621
第二列:网络协议 IP
第三列:发送方的ip地址+端口号,其中172.20.20.1是 ip,而15605 是端口号
第四列:箭头 >, 表示数据流向
第五列:接收方的ip地址+端口号,其中 172.20.20.2 是 ip,而5920 是端口号
第六列:冒号
第七列:数据包内容,包括Flags 标识符,seq 号,ack 号,win 窗口,数据长度 length,其中 [P.] 表示 PUSH 标志位为 1
监听第一块网卡上经过的数据包。主机上可能有不止一块网卡,所以经常需要指定网卡。
tcpdump -i en0
例子:监听本机跟主机182.254.38.55之间往来的通信包。
备注:出、入的包都会被监听。
tcpdump host 182.254.38.55
特定来源
tcpdump src host hostname/ip
tcpdump dst host hostname/ip
tcpdump host hostname/ip
若你的ip范围是一个网段,可以直接这样指定
$ tcpdump net 192.168.10.0/24
$ tcpdump src net 192.168
$ tcpdump dst net 192.168
tcpdump port 3000
端口同样可以再细分为源端口,目标端口
$ tcpdump src port 8088
$ tcpdump dst port 8088
如果你想要同时指定两个端口你可以这样写
$ tcpdump port 80 or port 8088
$ tcpdump port 80 or 8088
如果你的想抓取的不再是一两个端口,而是一个范围,一个一个指定就非常麻烦了,此时你可以这样指定一个端口段。
$ tcpdump portrange 8000-8080
$ tcpdump src portrange 8000-8080
$ tcpdump dst portrange 8000-8080
对于一些常见协议的默认端口,我们还可以直接使用协议名,而不用具体的端口号
比如 http == 80,https == 443 等
$ tcpdump tcp port http
常见的网络协议有:tcp, udp, icmp, http, ip,ipv6 等
若你只想查看 icmp 的包,可以直接这样写
$ tcpdump icmp
protocol 可选值:ip, ip6, arp, rarp, atalk, aarp, decnet, sca, lat, mopdl, moprc, iso, stp, ipx, or netbeui
监听来自主机123.207.116.169在端口22上的TCP数据包
tcpdump tcp port 22 and src host 123.207.116.169
tcpdump ip host 210.27.48.1 and 210.27.48.2
210.27.48.1除了和210.27.48.2之外的主机之间的通信
tcpdump ip host 210.27.48.1 and ! 210.27.48.2
tcpdump tcp -i eth1 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap
(1)tcp: ip icmp arp rarp 和 tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型
(2)-i eth1 : 只抓经过接口eth1的包
(3)-t : 不显示时间戳
(4)-s 0 : 抓取数据包时默认抓取长度为68字节。加上-S 0 后可以抓到完整的数据包
(5)-c 100 : 只抓取100个数据包
(6)dst port ! 22 : 不抓取目标端口是22的数据包
(7)src net 192.168.1.0/24 : 数据包的源网络地址为192.168.1.0/24
(8)-w ./target.cap : 保存成cap文件,方便用ethereal(即wireshark)分析
如下,抓到1000个包后,自动退出
tcpdump -c 1000
备注:tcpdump默认会将输出写到缓冲区,只有缓冲区内容达到一定的大小,或者tcpdump退出时,才会将输出写到本地磁盘,使用 -w 参数后接一个以 .pcap 后缀命令的文件名,就可以将 tcpdump 抓到的数据保存到文件中。
$ tcpdump icmp -w icmp.pcap
tcpdump -n -vvv -c 1000 -w /tmp/tcpdump_save.pcap
先看下面一个比较常见的部署方式,在服务器上部署了nodejs server,监听3000端口。nginx反向代理监听80端口,并将请求转发给nodejs server(127.0.0.1:3000)。
浏览器 -> nginx反向代理 -> nodejs server
问题:假设用户(183.14.132.117)访问浏览器,发现请求没有返回,该怎么排查呢?
步骤一:查看请求是否到达nodejs server -> 可通过日志查看。
步骤二:查看nginx是否将请求转发给nodejs server。
tcpdump port 8383
这时你会发现没有任何输出,即使nodejs server已经收到了请求。因为nginx转发到的地址是127.0.0.1,用的不是默认的interface,此时需要显示指定interface
tcpdump port 8383 -i lo
备注:配置nginx,让nginx带上请求侧的host,不然nodejs server无法获取 src host,也就是说,下面的监听是无效的,因为此时对于nodejs server来说,src host 都是 127.0.0.1
tcpdump port 8383 -i lo and src host 183.14.132.117
步骤三:查看请求是否达到服务器
tcpdump -n tcp port 8383 -i lo and src host 183.14.132.117
3. 读取抓包文件内容
使用 -w 是写入数据到文件,而使用 -r 是从文件中读取数据。
$ tcpdump icmp -r all.pcap
-i:指定要过滤的网卡接口,如果要查看所有网卡,可以 -i any
-Q: 选择是入方向还是出方向的数据包,可选项有:in, out, inout,也可以使用 --direction=[direction] 这种写法
-A:以ASCII码方式显示每一个数据包(不显示链路层头部信息). 在抓取包含网页数据的数据包时, 可方便查看数据
-l : 基于行的输出,便于你保存查看,或者交给其它工具分析
-q : 简洁地打印输出。即打印很少的协议相关信息, 从而输出行都比较简短.
-c : 捕获 count 个包 tcpdump 就退出
-s : tcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s number, number 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。
-S : 使用绝对序列号,而不是相对序列号
-C:file-size,tcpdump 在把原始数据包直接保存到文件中之前, 检查此文件大小是否超过file-size. 如果超过了, 将关闭此文件,另创一个文件继续用于原始数据包的记录. 新创建的文件名与-w 选项指定的文件名一致, 但文件名后多了一个数字.该数字会从1开始随着新创建文件的增多而增加. file-size的单位是百万字节(nt: 这里指1,000,000个字节,并非1,048,576个字节, 后者是以1024字节为1k, 1024k字节为1M计算所得, 即1M=1024 * 1024 = 1,048,576)
-F:使用file 文件作为过滤条件表达式的输入, 此时命令行上的输入将被忽略.
-D : 显示所有可用网络接口的列表
-e : 每行的打印输出中将包括数据包的数据链路层头部信息
-E : 揭秘IPSEC数据
-L :列出指定网络接口所支持的数据链路层的类型后退出
-Z:后接用户名,在抓包时会受到权限的限制。如果以root用户启动tcpdump,tcpdump将会有超级用户权限。
-d:打印出易读的包匹配码
-dd:以C语言的形式打印出包匹配码.
-ddd:以十进制数的形式打印出包匹配码
and:所有的条件都需要满足,也可以表示为 &&
or:只要有一个条件满足就可以,也可以表示为 ||
not:取反,也可以使用
举个例子,我想需要抓一个来自10.5.2.3,发往任意主机的3389端口的包
$ tcpdump src 10.5.2.3 and dst port 3389
当你在使用多个过滤器进行组合时,有可能需要用到括号,而括号在 shell 中是特殊符号,因为你需要使用引号将其包含。例子如下:
$ tcpdump 'src 10.0.2.4 and (dst port 3389 or 22)'
而在单个过滤器里,常常会判断一条件是否成立,这时候,就要使用下面两个符号
=:判断二者相等
==:判断二者相等
!=:判断二者不相等
当你使用这两个符号时,tcpdump 还提供了一些关键字的接口来方便我们进行判断,比如
if:表示网卡接口名、
proc:表示进程名
pid:表示进程 id
svc:表示 service class
dir:表示方向,in 和 out
eproc:表示 effective process name
epid:表示 effective process ID
比如我现在要过滤来自进程名为 nc 发出的流经 en0 网卡的数据包,或者不流经 en0 的入方向数据包,可以这样子写
$ tcpdump "( if=en0 and proc =nc ) || (if != en0 and dir=in)"