Lua编写Wireshark dissector:UDP隧道内Ethernet帧解析失败求助
问题描述
我是一名新手,借助ChatGPT编写了一个用于自定义UDP隧道协议的Lua Wireshark dissector。该协议包含两个固定长度字段:24字节的ID、8字节的时间戳,后续为隧道化的Ethernet帧。运行脚本后,预期隧道内的Ethernet帧能被正确解析,但实际它被显示为二进制blob。
原脚本代码
-- Define the protocol my_proto = Proto("my_proto", "Custom UDP Tunneling Protocol") -- Define the fields for the protocol local f_id = ProtoField.string("my_proto.id", "ID", base.ASCII) local f_timestamp = ProtoField.uint64("my_proto.timestamp", "Timestamp", base.DEC) local f_tunneled_eth = ProtoField.bytes("my_proto.tunneled_eth", "Tunneled Ethernet Frame") -- Assign fields to the protocol my_proto.fields = { f_id, f_timestamp, f_tunneled_eth } -- Dissector function function my_proto.dissector(buffer, pinfo, tree) -- Set the protocol column to "Custom Proto" pinfo.cols.protocol = "MY_PROTO" -- Check if the packet is large enough for minimum fields if buffer:len() < 32 then return -- Not enough data for ID + Timestamp end -- Add protocol to the dissection tree local subtree = tree:add(my_proto, buffer(), "Custom UDP Tunneling Protocol") -- Extract the ID field (24 bytes) subtree:add(f_id, buffer(0, 24)) -- Extract the Timestamp field (8 bytes) subtree:add(f_timestamp, buffer(24, 8)) -- Extract the Tunneled Ethernet frame (starting from byte 32) local eth_buffer = buffer(32):tvb() local eth_dissector = Dissector.get("eth") -- Get the Ethernet dissector if eth_dissector then -- Call the Ethernet dissector to parse the tunneled frame properly, adding it directly to the tree eth_dissector:call(eth_buffer, pinfo, tree) else -- Fallback if Ethernet dissector is unavailable subtree:add(f_tunneled_eth, buffer(32), "Ethernet Frame (unrecognized)") end end
解决方案
问题出在两个核心点:
- 子 dissector 挂载位置错误:原代码将Ethernet dissector直接调用到根协议树(
tree),导致Wireshark无法正确关联隧道帧与自定义协议,解析上下文混乱。 - 缺少帧长度校验:未验证剩余数据是否满足Ethernet帧的最小长度要求,可能触发解析失败。
修改后的脚本如下:
-- Define the protocol my_proto = Proto("my_proto", "Custom UDP Tunneling Protocol") -- Define the fields for the protocol local f_id = ProtoField.string("my_proto.id", "ID", base.ASCII) local f_timestamp = ProtoField.uint64("my_proto.timestamp", "Timestamp", base.DEC) local f_tunneled_eth = ProtoField.bytes("my_proto.tunneled_eth", "Tunneled Ethernet Frame") -- Assign fields to the protocol my_proto.fields = { f_id, f_timestamp, f_tunneled_eth } -- Dissector function function my_proto.dissector(buffer, pinfo, tree) -- Set the protocol column to "Custom Proto" pinfo.cols.protocol = "MY_PROTO" -- 最小长度校验:24字节ID +8字节时间戳 +64字节最小以太网帧 =96字节 local min_total_len = 32 + 64 if buffer:len() < min_total_len then local subtree = tree:add(my_proto, buffer(), "Custom UDP Tunneling Protocol") subtree:add_expert_info(PI_MALFORMED, PI_WARN, "数据长度不足,无法解析隧道内以太网帧") return end -- 添加自定义协议到解析树 local subtree = tree:add(my_proto, buffer(), "Custom UDP Tunneling Protocol") -- 提取ID字段(24字节) subtree:add(f_id, buffer(0, 24)) -- 提取时间戳字段(8字节) subtree:add(f_timestamp, buffer(24, 8)) -- 提取隧道内以太网帧(从第32字节开始) local eth_buffer = buffer(32):tvb() local eth_dissector = Dissector.get("eth") if eth_dissector then -- 创建以太网帧子项,将dissector挂载到该子项的解析树中 local eth_subtree = subtree:add(f_tunneled_eth, eth_buffer, "Tunneled Ethernet Frame") eth_dissector:call(eth_buffer, pinfo, eth_subtree) else -- 以太网dissector不可用时的降级处理 subtree:add(f_tunneled_eth, buffer(32), "Ethernet Frame (unrecognized)") end end -- 注册到UDP端口(替换为你的隧道实际使用的UDP端口) local udp_table = DissectorTable.get("udp.port") udp_table:add(12345, my_proto)
关键修改说明
- 调整dissector挂载层级:将Ethernet dissector的调用目标改为自定义协议子树的子项,确保解析结果嵌套在自定义协议下,符合Wireshark的解析树结构逻辑。
- 完善长度校验:增加了包含以太网帧最小长度的总长度校验,并添加专家警告提示数据异常情况。
- 补充端口注册:添加了UDP端口绑定代码(需替换为实际使用的隧道端口),确保Wireshark能将对应流量交给自定义dissector处理。
内容的提问来源于stack exchange,提问作者Rod D
相关产品推荐
相关产品推荐

