Wireshark 很强大,比你想象中的还要厉害。
强烈推荐《Wireshark网络分析就这么简单》和《Wireshark网络分析的艺术》,作者林沛满。
以下内容并非读书笔记。书是两年前读的了。
抓包过滤字节
tcpdump 和 Wireshark 过滤字节的语法存在差异:
1 | capture filter / 含 8 字节头部 |
多思考一步,这个差异从哪来的?
- 命令行使用 tcpdump 是在抓取报文时过滤的;
- 图形界面使用 Wireshark 存在“捕获过滤器”和“显示过滤器”,
- 使用 Wireshark 查看已捕获的报文时只用到后者;
两者捕获报文时的过滤语法其实一致: man pcap-filter
Wireshark “显示过滤器”的语法: man wireshark-filter
capture filter 语法
通过 man pcap-filter 查阅 expr relop expr 章节,解释 tcpdump len = 100
True if the relation holds, where
relopis one of >, <, >=, <=, =, !=,and
expris an arithmetic expression composed of
- integer constants (expressed in standard C syntax),
- the normal binary operators [+, -, *, /, %, &, |, ^, <<, >>],
- a length operator,
- and special packet data accessors.
proto [ expr : size ]Note that all comparisons are unsigned, so that, for example, 0x80000000 and 0xffffffff are > 0.
提取报文内部数据时, size 可取值只有 1、2、4 。
The length operator, indicated by the keyword
len, gives the length of the packet.
是整个包的长度,并非如 Wireshark display filter 中数据部分的长度。
以 UDP 为例,一般是 42字节 + 数据长度:
1 | 以太网头部(14字节) → IPv4头部(20字节) → UDP头部(8字节) → 应用数据(58字节) |
display filter 语法
通过 man wireshark-filter 查阅 “The slice operator” 章节
You can take a slice of a field if the field base type is a text string or a byte array.
不同于 pcap-filter 抽取一字节、两字节、四字节转换成无符号数(进行比较),
在 wireshark-filter 中可以抽取任意长度的字节(切片),相应的也就无法转换成无符号数。
You can take a slice of a field if the field base type is a text string or a byte array.
在 wireshark-filter 中切片都是单个字节依次比较 frame[60:2] == 50:51,
Ethernet addresses and byte arrays are represented by hex digits.
The hex digits may be separated by colons, periods, or hyphens. 冒号 / 句号 / 连字符
字节序列可以隐式地转换成字符串,比较时更灵活:
Fields which are sequences of bytes are implicitly converted to strings for comparisons against (double quoted) literal strings and raw strings.
1 | frame[60:2] == "PQ" # literal strings |
封装了多种类型,避免了只能在字节序列上筛选:
Each protocol field is typed. 数值、网络地址、时间、协议等多种类型
udp 是协议,udp.payload 是字节序列,所以前者不能使用切片语法,后者才可以。
Classless Inter-Domain Routing (CIDR) notation can be used to test if an IPv4 address is in a certain subnet.
For example, this display filter will find all packets in the 129.111 network:
1 | ip.addr == 129.111.0.0/16 |
后记
各有各的不足:
- tcpdump 没有参数直接映射 udp 协议(含头部和数据)的长度,
需要手动提取协议中长度字段对应的序列切片 udp[4:2]
Wireshark 没有字段直接获取 udp 报文(含头部和数据),
需要通过 ip 的数据来间接地访问
自定义协议
使用 C 语言编写动态库或者 Lua 脚本语言,放到对应的插件目录,重启软件。
学习官方手册的过程笔记呢?
简单的协议交给大语言模型完全能搞定,比如基于 UDP 的由传感器上传的无状态的测量数据报文。