SharpPcap捕获首个TCP包问题:解决端口扫描时重复输出端口状态的问题
嘿,我刚好碰到过类似的SharpPcap捕获重复包的问题,你的情况完全能理解——明明服务器的SYN-ACK只需要处理一次,结果后续的TCP包(比如你提到的“TCP Port numbers reused”报文)也满足了你的判断条件,导致重复输出端口状态。给你两个实用的解决思路:
方法一:用标记变量跳过已处理的端口
这是最直接的修改方式,核心就是用一个变量记录我们是否已经处理过目标端口的状态,一旦处理完成,后续符合条件的包直接跳过即可。
单端口扫描场景
如果你的工具是单次扫描单个端口,只需要在类级别声明一个布尔标记:
private bool _hasProcessedPort = false; private int _targetPort; // 假设你的目标端口存在这个类变量中
然后修改你的OnPacketArrival逻辑,先检查标记再处理:
if (tcp != null && ip != null && tcp.SourcePort == _targetPort && eth.SourceHardwareAddress == gatewayMac) { // 核心:如果已经处理过这个端口,直接跳过后续逻辑 if (_hasProcessedPort) { return; } if (tcp.Synchronize && tcp.Acknowledgment) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($"Port {_targetPort} is open."); device.SendPacket(ethernetPacket2); _hasProcessedPort = true; // 处理完成后标记为已处理 } else if (tcp.Reset || (tcp.Reset && tcp.Acknowledgment)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Port {_targetPort} is closed."); _hasProcessedPort = true; } else if (!tcp.Reset && !tcp.Acknowledgment) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Port {_targetPort} is filtered."); _hasProcessedPort = true; } }
多端口扫描场景
如果是批量扫描多个端口,就用一个字典来记录每个端口的处理状态:
private Dictionary<int, bool> _processedPorts = new Dictionary<int, bool>();
然后在处理逻辑中加入端口检查:
if (tcp != null && ip != null && eth.SourceHardwareAddress == gatewayMac) { int currentPort = tcp.SourcePort; // 检查当前端口是否已经处理过 if (_processedPorts.ContainsKey(currentPort) && _processedPorts[currentPort]) { return; } if (tcp.Synchronize && tcp.Acknowledgment) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($"Port {currentPort} is open."); device.SendPacket(ethernetPacket2); _processedPorts[currentPort] = true; } // 其余判断逻辑同理,处理完成后标记端口为已处理 else if (tcp.Reset || (tcp.Reset && tcp.Acknowledgment)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Port {currentPort} is closed."); _processedPorts[currentPort] = true; } else if (!tcp.Reset && !tcp.Acknowledgment) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Port {currentPort} is filtered."); _processedPorts[currentPort] = true; } }
方法二:提前过滤不需要的包
从根源上减少进入处理逻辑的包,利用SharpPcap的包过滤功能,只捕获我们真正需要的SYN-ACK或RST响应包,那些“端口复用”之类的无关包直接在捕获阶段就被过滤掉。
你可以在启动捕获前设置过滤规则:
// 只捕获目标端口发来的SYN-ACK或RST包 device.Filter = $"tcp src port {_targetPort} and (tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn|tcp-ack or tcp[tcpflags] & tcp-rst != 0)";
这个过滤规则基于pcap的过滤语法,精准筛选出我们需要的握手响应包,后续就不会有无关包触发重复判断了。
两种方法各有优劣:标记变量的方式改动小,适合你现有逻辑的快速调整;包过滤的方式更高效,能减少不必要的包处理开销,你可以根据自己的扫描场景选择。
内容来源于stack exchange
相关产品推荐
相关产品推荐

