0

我的网络编程经验相对有限,希望有人可以帮助我解决一个可能是 n00bish 的问题,在此先感谢您的帮助!:)

我有两个分别运行的 C++ 程序。一种是使用 libpcap 库编写的简单数据包嗅探器,它进行过滤,使其仅侦听在特定端口上接收到的数据包,然后解析数据包,以便将有效负载长度和有效负载内容写入二进制文件。

另一个程序是一个简单的 bsd 套接字服务器程序,它被设置为使用 recv() 函数在特定端口上接收消息,然后类似地将接收到的消息长度和消息内容写入二进制文件。

一切似乎都运行良好,所以当我检查二进制输出文件时,我希望内容是相同的......但不幸的是,我发现它们只是有点相似。似乎数据包嗅探器正在捕获与服务器正在捕获的相同数据,但它也在记录具有 6 字节长有效负载的额外数据包,这些数据显然没有被服务器程序接收。

因此,数据包嗅探器正在拾取服务器不应该知道的数据包,或者服务器程序丢失了它应该接收的数据包。但是,我对服务器程序运行正常并接收到正确的消息感到有些信心,因此数据包嗅探器检测到的这些额外数据包让我感到困惑。有谁知道这些额外的数据包可能是什么,以及我如何将它们过滤掉?

笔记:

向我正在侦听的端口发送数据的客户端是小型网络中的一台旧 Windows NT 机器,它基本上是将二进制数据传递给服务器程序进行处理。

不幸的是,由于工作场所政策,我无法上传代码。但是,可以在这里找到我的代码的示例: http : //www.tcpdump.org/pcap.html http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html

再次感谢!

4

2 回答 2

0

一种是使用 libpcap 库编写的简单数据包嗅探器,它进行过滤,使其仅侦听在特定端口上接收到的数据包,然后解析数据包,以便将有效负载长度和有效负载内容写入二进制文件。

TCP端口还是UDP端口?

如果它是 TCP 端口,您的程序可能会收到 3 次握手数据包和 ACK-only 数据包。

你是如何计算有效载荷长度的?您应该通过获取 IP 数据包的总长度,从中减去 IP 标头长度(不是 20 个字节,而是版本/标头长度字段的长度,以便您处理 IP 选项;如果该长度小于 5,即< 20 字节,丢弃数据包,这是伪造的),得到 TCP 数据包总长度然后从中减去TCP 标头长度(不是 20 字节,而是“数据偏移”字段,因此您可以处理 TCP 选项;如果该长度< 5,即< 20 字节,只需丢弃数据包,这是伪造的)以获取 TCP 有效负载长度。

这应该处理 mfontanini 所指的选项以及IP选项。

如果它是 UDP 端口,您仍应处理 IP 选项并获取总 UDP 数据包长度,然后:

  • 如果这小于 UDP 标头中的长度,则丢弃数据包,这是伪造的;
  • 如果 UDP 标头中的长度 < 8,则丢弃该数据包,它是伪造的;
  • 否则,使用 UDP 标头中的长度减去 8 作为有效负载长度。

另一个程序是一个简单的 bsd 套接字服务器程序,它被设置为使用 recv() 函数在特定端口上接收消息,然后类似地将接收到的消息长度和消息内容写入二进制文件。

那将看不到初始握手或仅 ACK 数据包。

于 2013-06-18T18:19:50.950 回答
0

我的魔术球表明那些 6 字节长的有效载荷可能只是 TCP 选项。如果您只想使用有效负载,则应该跳过这些选项。请注意,某些数据包可能同时包含有效负载和某些选项。

TCP 数据包中的数据偏移字段指示有效负载从哪个点开始。您可以在第 3.1 节中查看。

无论如何,我建议您使用一些在内部处理这些东西的更高级别的库。使用libtins,您可以使用一些简短的片段来完成该任务,例如:

#include <tins/tins.h>

using namespace Tins;

bool callback(const PDU &pdu) {
    const RawPDU &raw = pdu.rfind_pdu<RawPDU>();
    // raw.payload() returns a std::vector<uint8_t>
    process_payload(raw.payload());
    return true;
}

int main() {
    Sniffer some_sniffer(
        "eth0", 
        Sniffer::NON_PROMISC,
        "some pcap filter"
    );
    some_sniffer.sniff_loop(callback);
}
于 2013-01-30T21:42:41.443 回答