tcpdump的高级用法
Fri ,May 1 ,2020tcpdump是linux平台的,基于bpf的抓包工具。
比较常见的用法是: tcpdump -i eth1 tcp port 80
前几天在工作中遇到一个问题:线上的redis库,因为HGET命令中包含特殊字符报错。
不能确定是哪个模块引入的问题。
问题描述: tcp 7700 端口接收外部的查询命令, 同时包含多个redis命令字。
当前:只有 HGET 命令字有问题,且出错的字符串多是 a 域名。
抓全部的包去找有问题的场景简直大海捞针,因此让我们见识下tcpdump的新魔法:
tcpdump -i any 'tcp port 7700 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)
and (tcp[25] == 0x34)
and (tcp[28] == 0x48) and (tcp[29] == 0x47) and (tcp[30] == 0x45) and (tcp[31] == 0x54)'
-nnn -vvv -w 49.7700.pcap
====基础知识:
ip[2:2] 以2起,2个字节表示包长度
(ip[0]&0xf)<<2 第一个字节 前4bit是协议 后4bit 乘以4 是ip包头大小。
tcp[12]&0xf0>>2 高位4bit是长度
tcp[0-19]表示包头,自tcp 20个字节起是 payload.
redis的tcp命令是:
*3
$4
HGET
$99
PLAN_...
$10
abcdef.com....
(ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0
保证tcp的包大小大于0, 把握手包这种就过滤了。
tcp[25] == 0x34 检查$4的4 , 只要4个字符的命令字。
28,29,30,31 对应的就是 H G E T
为什么是25:
因为redis命令字后跟着2个字节额 0d 0a。
本身思路出来就可以,再具体的可以:
- 包长度的校验具体成大于多少。
- redis命令中有变长的字符,可以针对$99,$100做单独的处理,这样就可以明确定位到abcdef.com的域名。