我正在尝试使用 Pcap.Net 打开一个 tcp 连接。
我正在发送以下包裹:
服务器响应:
之后,Windows 会自行发送重置数据包:
为什么会发生这种情况,如何阻止这种行为?
我在 Windows 7 上这样做
正如哈里斯先生所说,你可以使用WinDivert来做你想做的事。例如,只是进行 TCP 握手,您可以编写如下内容:
// TCP handshake using WinDivert:
HANDLE handle = DivertOpen("inbound && tcp.SrcPort == 80 && tcp.Syn && tcp.Ack", 0, 0, 0);
DivertSend(handle, synPacket, sizeof(synPacket), dstAddr, NULL);
...
DivertRecv(handle, synAckPacket, sizeof(synAckPacket), &srcAddr, &length);
...
DivertSend(handle, ackPacket, sizeof(ackPacket), dstAddr, NULL);
...
DivertRecv() 函数将服务器响应重定向到用户空间,然后由 Windows TCP/IP 堆栈处理。所以不会产生讨厌的 TCP RST。DivertSend() 注入数据包。
这是 WinDivert 和 WinPCAP 之间的主要区别。后者只是一个数据包嗅探器,而前者可以拦截/过滤/阻止流量。
WinDivert 是用 C 语言编写的,因此您需要编写自己的 .NET 包装器。
(通常披露:WinDivert 是我的项目)。
本质上,问题是scapy
在用户空间运行,windows内核会先收到SYN-ACK。您的 Windows 内核将发送 TCP RST,因为在您有机会对 scapy 执行任何操作之前,它不会在相关端口号上打开套接字。
典型的解决方案(在 linux 中)是在运行脚本时阻止内核在该 TCP 端口(12456)上接收 RST 数据包...问题是我认为 Windows 防火墙不允许您如此精细(即查看 TCP 标志)是否有丢包。
也许最简单的解决方案是在 linux VM 下执行此操作并用于iptables
实现 RST drop。
通过使用 Boring Old Winsock 与服务器建立 TCP 连接,而不是构建您自己的 TCP-over-IP-over-Ethernet 数据包并将它们发送到服务器,或者以某种方式说服 Windows Internet 协议栈忽略 SYN +ACK(以及所有后续数据包)从服务器获得,因此它看不到来自服务器的 SYN+ACK,请注意没有进程尝试建立从 192.168.1.3:12456 到 192.168 的 TCP 连接。 1.1:80 使用标准的内核内网络堆栈(即,没有人尝试使用 Boring Old Winsock 设置它),并返回一个 RST 告诉服务器在机器上的端口 12456 上没有人在监听。
您也许可以使用WinDivert来完成后者。它本身似乎没有 .NET 包装器,因此如果您要使用 .NET 而不是 Boring Old Unmanaged C 或 Boring Old Unmanaged C++,您可能需要寻找一个。