Lua脚本无法在Wireshark控制台输出443端口TCP分析结果排查
Wireshark Lua脚本无法处理443端口TCP包的问题分析与修复
问题描述
我为工作编写了以下Lua脚本,但针对443端口的TCP数据包,它无法在Wireshark控制台显示任何输出。已尝试修复多日却毫无成效,请问问题出在哪里?
用户提供的脚本:
local plugin = {} function plugin.init() --I have initialized the plugins in the function plugin.rtt = {} plugin.window_sizes = {} plugin.congestion_window_size = 0 plugin.slow_start_threshold = 0 plugin.retransmit_threshold = 0 plugin.packet_drops = 0 plugin.throughput = 0 end function plugin.process_packet(packet) --This is processing every TCP packet local rtt = packet:get_tcp_option("tcp_rtt") if rtt ~= nil then plugin.rtt[#plugin.rtt + 1] = rtt end local window_size = packet:get_tcp_option("tcp_window_size") if window_size ~= nil then plugin.window_sizes[#plugin.window_sizes + 1] = window_size end if packet.tcp.flags.syn then plugin.congestion_window_size = 2 else plugin.congestion_window_size = math.min(plugin.congestion_window_size * 2, math.max(plugin.window_sizes[#plugin.window_sizes - 1], 1)) end if packet.tcp.flags.ack then plugin.slow_start_threshold = plugin.congestion_window_size + 1 plugin.retransmit_threshold = plugin.congestion_window_size / 2 end if packet.tcp.flags.rst then plugin.congestion_window_size = 0 plugin.packet_drops = 0 end if packet.tcp.flags.fin then plugin.throughput = plugin.congestion_window_size / plugin.rtt[#plugin.rtt] end print("Results for packet:") print("RTT:", rtt) print("Congestion Window Size:", plugin.congestion_window_size) print("Slow Start Threshold:", plugin.slow_start_threshold) print("Retransmit Threshold:", plugin.retransmit_threshold) print("Packet Drops:", plugin.packet_drops) print("Throughput:", plugin.throughput) end function plugin.get_results() return { rtt = plugin.rtt, window_sizes = plugin.window_sizes, congestion_window_size = plugin.congestion_window_size, slow_start_threshold = plugin.slow_start_threshold, retransmit_threshold = plugin.retransmit_threshold, packet_drops = plugin.packet_drops, throughput = plugin.throughput } end return plugin
核心问题与修复方案
1. 未针对443端口过滤数据包
脚本当前会处理所有TCP数据包,但你只关注443端口流量,若没有添加端口过滤逻辑,要么脚本处理了非443包导致你没看到对应输出,要么全局过滤后脚本没被触发。
修复:在process_packet开头添加端口判断,只处理源或目的为443的TCP包:
-- 仅处理443端口的TCP数据包 if not (packet.tcp.srcport == 443 or packet.tcp.dstport == 443) then return end
2. TCP选项与字段获取方式错误
Wireshark Lua API中没有get_tcp_option方法,且RTT不是TCP头部选项,是Wireshark分析出的tcp.analysis.rtt字段;TCP窗口大小直接通过packet.tcp.window_size获取即可。
修复:
-- 获取Wireshark分析的RTT值 local rtt = packet.tcp.analysis and packet.tcp.analysis.rtt if rtt ~= nil then plugin.rtt[#plugin.rtt + 1] = rtt end -- 获取TCP窗口大小 local window_size = packet.tcp.window_size if window_size ~= nil then plugin.window_sizes[#plugin.window_sizes + 1] = window_size end
3. 数组索引越界导致脚本中断
当脚本刚启动或还未收集到窗口大小数据时,plugin.window_sizes[#plugin.window_sizes - 1]会访问无效索引,触发报错导致脚本停止执行,控制台无输出。
修复:添加数组非空判断:
if packet.tcp.flags.syn then plugin.congestion_window_size = 2 else -- 确保window_sizes数组有数据才访问 local last_window_size = #plugin.window_sizes > 0 and plugin.window_sizes[#plugin.window_sizes] or 1 plugin.congestion_window_size = math.min(plugin.congestion_window_size * 2, math.max(last_window_size, 1)) end
4. 吞吐量计算时的空数组访问
当RTT数组为空时,plugin.rtt[#plugin.rtt]为nil,执行除法会报错中断脚本。
修复:添加非空判断:
if packet.tcp.flags.fin then if #plugin.rtt > 0 then plugin.throughput = plugin.congestion_window_size / plugin.rtt[#plugin.rtt] else plugin.throughput = 0 end end
5. 未正确注册Wireshark Tap
你的脚本定义了插件结构,但没有注册到Wireshark的TCP Tap上,导致process_packet函数根本不会被调用。
修复:在脚本末尾添加Tap注册逻辑:
-- 注册TCP Tap local tap = Listener.new(nil, "tcp") function tap.packet(pinfo, tvb, tcp) -- 将pinfo和tcp数据包装为兼容现有代码的packet对象 local packet = { tcp = { srcport = pinfo.src_port, dstport = pinfo.dst_port, flags = { syn = tcp.syn, ack = tcp.ack, rst = tcp.rst, fin = tcp.fin }, window_size = tcp.window_size, analysis = { rtt = pinfo.rtt } } } plugin.process_packet(packet) end function tap.reset() plugin.init() end -- 初始化插件 plugin.init()
完整修复后的脚本
local plugin = {} function plugin.init() plugin.rtt = {} plugin.window_sizes = {} plugin.congestion_window_size = 0 plugin.slow_start_threshold = 0 plugin.retransmit_threshold = 0 plugin.packet_drops = 0 plugin.throughput = 0 end function plugin.process_packet(packet) -- 仅处理443端口的TCP数据包 if not (packet.tcp.srcport == 443 or packet.tcp.dstport == 443) then return end -- 获取Wireshark分析的RTT值 local rtt = packet.tcp.analysis and packet.tcp.analysis.rtt if rtt ~= nil then plugin.rtt[#plugin.rtt + 1] = rtt end -- 获取TCP窗口大小 local window_size = packet.tcp.window_size if window_size ~= nil then plugin.window_sizes[#plugin.window_sizes + 1] = window_size end if packet.tcp.flags.syn then plugin.congestion_window_size = 2 else -- 确保window_sizes数组有数据才访问 local last_window_size = #plugin.window_sizes > 0 and plugin.window_sizes[#plugin.window_sizes] or 1 plugin.congestion_window_size = math.min(plugin.congestion_window_size * 2, math.max(last_window_size, 1)) end if packet.tcp.flags.ack then plugin.slow_start_threshold = plugin.congestion_window_size + 1 plugin.retransmit_threshold = plugin.congestion_window_size / 2 end if packet.tcp.flags.rst then plugin.congestion_window_size = 0 plugin.packet_drops = 0 end if packet.tcp.flags.fin then if #plugin.rtt > 0 then plugin.throughput = plugin.congestion_window_size / plugin.rtt[#plugin.rtt] else plugin.throughput = 0 end end -- 输出结果到控制台 print("Results for 443 port packet:") print("RTT:", rtt or "N/A") print("Congestion Window Size:", plugin.congestion_window_size) print("Slow Start Threshold:", plugin.slow_start_threshold) print("Retransmit Threshold:", plugin.retransmit_threshold) print("Packet Drops:", plugin.packet_drops) print("Throughput:", plugin.throughput) end function plugin.get_results() return { rtt = plugin.rtt, window_sizes = plugin.window_sizes, congestion_window_size = plugin.congestion_window_size, slow_start_threshold = plugin.slow_start_threshold, retransmit_threshold = plugin.retransmit_threshold, packet_drops = plugin.packet_drops, throughput = plugin.throughput } end -- 注册TCP Tap local tap = Listener.new(nil, "tcp") function tap.packet(pinfo, tvb, tcp) -- 将pinfo和tcp数据包装为兼容现有代码的packet对象 local packet = { tcp = { srcport = pinfo.src_port, dstport = pinfo.dst_port, flags = { syn = tcp.syn, ack = tcp.ack, rst = tcp.rst, fin = tcp.fin }, window_size = tcp.window_size, analysis = { rtt = pinfo.rtt } } } plugin.process_packet(packet) end function tap.reset() plugin.init() end -- 初始化插件 plugin.init() return plugin
内容的提问来源于stack exchange,提问作者Dark Vedar
相关产品推荐
相关产品推荐

