Understanding ngrep
抓包
一般都有 tcpdump/ngrep,tcpdump 可读性比较差,一般只有在怀疑 tcp 连接出现问题,会用 tcpdump 去查看 tcp 的连接状态。ngrep 对比之下,使用比较方便,基本能满足一般需求。
ngrep | tcpdump | |
---|---|---|
过滤规则 | 支持 host\port\net\proc | 支持 host\port\net\proc |
易读性 | 较高(http 协议等很清晰) | 较低 |
过滤字符串 | 支持 | 不支持 |
ngrep
ngrep 方便的数据包匹配和显示工具,可以过滤网络数据包并搜索字符串,是grep(在文本中搜索字符串的工具)的网络版。
输出内容
1 | interface: any |
- 第一行是网卡
- 第二行是过滤的规则
- 第三行#,未匹配的数据包都以“#”显示
- 第四行监听到的 http 请求协议,请求 url,请求头和请求的参数内容。
- 第9行未匹配的数据包都以“#”显示。
- 第19行是 http 返回值
参数说明
- 过滤指定网卡的数据包
-d 要查看所有网卡,可以-d any
- 查看内容
-W: 一般为了可读性使用 byline。有4种格式 normal, byline, single, none。
-n 仅捕获指定数目的数据包进行查看
-A 匹配到数据包后dump随后的指定数目的数据包
-T 显示上一个匹配的数据包之间的时间间隔 - 二进制查看
-xX 左边会显示16进制格式,右边显示可读字符 - 输出或读取文件
-O 将匹配的数据保存到.dump
文件
-I 从.dump
文件中读取数据进行匹配 - 其它
-q 静默模式,如果没有此开关,未匹配的数据包都以“#”显示
-t 显示匹配到数据包的时间
语法
1 | ngrep <-LhNXViwqpevxlDtTRM><-IO pcap_dump><-n num><-d dev><-A num> |
简化ngrep -W byline -d any '过滤字符串,支持表达式' '过滤规则'
在实际使用中,没有过滤字符串最好也加上''
,因为过滤规则可能被这个影响。所以如果发现输出都是 #####
且不符合预期,最好先检查一下自己的命令,过滤字符串和过滤规则格式是否正确。
过滤规则
基于地址过滤:host
1
sudo ngrep -W byline -d any '' 'host 127.0.0.1'
数据包的 ip 可以再细分为源ip和目标ip两种
1
2
3
4
5# 根据源ip进行过滤
sudo ngrep -W byline -d any '' 'src host 127.0.0.1'
# 根据目标ip进行过滤
sudo ngrep -W byline -d any '' 'dst host 127.0.0.1'支持域名
基于端口过滤:port
使用 port 就可以指定特定端口进行过滤1
sudo ngrep -W byline -d any '' 'port 8083'
端口同样可以再细分为源端口,目标端口
1
2
3
4
5# 根据源端口进行过滤
sudo ngrep -W byline -d any '' 'src port 8083'
# 根据目标端口进行过滤
sudo ngrep -W byline -d any '' 'dst port 8083'也可以指定一个端口段
1
sudo ngrep -W byline -d any '' 'portrange 80-8082'
其它
能识别TCP、UDP和ICMP包,使用tcp
、tdp
、icmp
tcp 里面 ip 和 ip6 区分,使用ip
和ip6
支持网段过滤,使用示例net 172.17.0.0/24
,支持源和目标网段。过滤规则组合
支持 and、or、not。1
2
3and:所有的条件都需要满足,也可以表示为 &&
or:只要有一个条件满足就可以,也可以表示为 ||
not:取反,也可以使用 !也有可能需要用到括号
()
场景
基础
- 指定 port
查看请求,监听相应端口即可,以 station 举例,端口是 8083,示例如下:sudo ngrep -W byline -d any '' 'port 8083'
sudo ngrep -W byline -d any port 8083
这样写有没有问题?sudo ngrep -W byline -d any src port 8083
这样写会不会有问题?
PostgreSQL 默认端口是 5432sudo ngrep -W byline -d any '' 'port 5432'
Redis 默认端口是 6379sudo ngrep -W byline -d any '' port 6379'
指定 host
需要过滤对应的 host 和 port,比如过滤出某个数据库的请求。可以使用域名sudo ngrep -W byline -d any '' 'host 172.17.20.138'
sudo ngrep -W byline -d any '' 'host bytepower-station-db.cluster-cv0oenksk2p5.rds.cn-northwest-1.amazonaws.com.cn'
正则过滤
过滤请求的 urlsudo ngrep -W byline -d any '/withdra(.+)?/wechat' 'port 8083'
查看二进制
sudo ngrep -xX -W byline -d any '/withdra(.+)?/wechat' 'port 8083'
udp
sudo ngrep -d any '' 'udp'
进阶
分析
排查问题的时候,很多时候我们需要对一份数据反复分析查看。
这种情况下:- 先收集导出到文件,这个时候过滤条件可以比较少甚至不设置。
sudo ngrep -W byline -O /tmp/check_1.dump -d any -t
- 退出后,针对这个文件进行搜索分析。
sudo ngrep -W byline -I /tmp/check_1.dump '^GET' 'port 8083'
sudo ngrep -W byline -I /tmp/check_1.dump 'app_id=APPIFP5WATVLJAZ3' 'port 8083'
如何看到这个请求后面的一系列操作,可以使用 -A 来过滤出匹配到数据包后面的数据包sudo ngrep -W byline -I /tmp/check_1.dump -A 10 'app_id=APPIFP5WATVLJAZ3' 'port 8083'
通过做这种途径可以看到后续的 sql 和 redis 相关操作。还是难以分析?可以循环上面的操作,过滤导出文件在分析sudo ngrep -W byline -I /tmp/check_1.dump -O /tmp/check_2.dump -A 10 'user_id=UUCGNNN7KAXGQ'
这是一种分析的思路。当然你要是正则够厉害,可以一个复杂的正则搞定。
- 先收集导出到文件,这个时候过滤条件可以比较少甚至不设置。
实际使用
在测试部署到机器上后,通过 ngrep 来查看请求发起了多少次数据库查询、redis 操作。这在和产品组联调的时候很有用。sudo ngrep -W byline '' 'not port 22'
sudo ngrep -d any '' 'portrange 5000-8082'
线上的时候,因为每秒数百上千个请求,这个时候就结合
组合使用
可以对结果使用 awk 或者 grep 过滤sudo ngrep -W byline -d any '' 'port 8083' |grep 10 '/withdraw'
tcpdump
tcpdump是一个对网络上的数据包进行截获的包分析工具。它允许用户截获和显示发送或收到通过网络连接到该计算机的TCP/IP和其他数据包。
输出内容
1 | 08:31:54.674766 IP ip-172-30-1-113.cn-northwest-1.compute.internal.http > ip-172-31-48-163.cn-northwest-1.compute.internal.64372: Flags [P.], seq 619:14807, ack 1313, win 285, options [nop,nop,TS val 3247021864 ecr 577459112], length 14188: HTTP: HTTP/1.1 200 OK |
- 第一列:时分秒毫秒 21:26:49.013621
- 第二列:网络协议 IP
- 第三列:发送方的地址+端口号,其中172.20.20.1是 ip,而15605 是端口号
- 第四列:箭头 >, 表示数据流向
- 第五列:接收方的ip地址+端口号,其中 172.20.20.2 是 ip,而5920 是端口号
- 第六列:冒号
- 第七列:数据包内容,包括Flags 标识符,seq 号,ack 号,win 窗口,数据长度 length,其中 [P.] 表示 PUSH 标志位为 1,更多标识符见下面
参数说明
- 控制详细内容的输出
一般 -v 就足够使用了
-v 产生详细的输出. 比如包的TTL,id标识,数据包长度,以及IP包的一些选项
-vv 产生比-v更详细的输出。比如NFS回应包中的附加域
-vvv 产生比-vv更详细的输出。比如 telent 时所使用的SB - 过滤指定网卡的数据包
-i 要查看所有网卡,可以-i any
- 过滤特定流向的数据包
-Q: 选择是入方向还是出方向的数据,可选项有:in, out, inout - 输出或读取文件
-w 后接一个以.pcap
后缀命令的文件名
-r 从.pcap
文件读取 - 其它
-n 不把ip转化成域名,直接显示 ip
-nn 不把协议和端口号转化成名字
-s number,number 是 0 的话,表示截取报文全部内容
-l 基于行的输出,便于你保存查看,或者交给其它工具分析
场景
查看请求
我们一般使用 nginx 中转,因为 nginx 转到 127.0.0.1,需要指定 interfacesudo tcpdump port 8083 -i lo
查看完整的请求
默认的话 tcpdump 只显示部分数据包,默认68字节。sudo tcpdump -s 0 -v -n -l
图形化查看
通过ssh传到本地 Wireshark ,查看内容ssh bytepower-appserver-tasklet 'sudo tcpdump -s 0 -c 1000 -nn -w - not port 22' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -
附录
1 | ngrep: invalid option -- '-' |