简体   繁体   English

使用C ++的libpcap数据包结果与bsd套接字recv数据之间的差异

[英]Differences between libpcap packet results and bsd socket recv data using C++

I have relatively limited network programming experience and was hoping someone could help me with perhaps a n00bish question, thanks in advance for any help! 我的网络编程经验相对有限,希望有人可以为我解决一个问题,在此先感谢您的帮助! :) :)

I have two C++ programs running separately. 我有两个单独运行的C ++程序。 One is a simple packet sniffer written with the libpcap library that is filtering such that it only listens to packets received on a specific port, and then parses the packet such that it writes out the payload length and payload content to a binary file. 一种是使用libpcap库编写的简单数据包嗅探器,该嗅探器正在过滤,以使其仅侦听在特定端口上接收到的数据包,然后解析该数据包,以便将有效载荷长度和有效载荷内容写到二进制文件中。

The other program is a simple bsd socket server program that is set to receives messages on that specific port with the recv() function, and then similarly writes the received message length and message content out to a binary file. 另一个程序是一个简单的bsd套接字服务器程序,该程序设置为使用recv()函数在该特定端口上接收消息,然后类似地将接收到的消息长度和消息内容写出到二进制文件中。

Everything appears to be running fine, so when I check the binary output files I expect the content to be the same... but unfortunately, I am finding they are only somewhat similar. 一切似乎都运行良好,因此当我检查二进制输出文件时,我希望内容是相同的...但是不幸的是,我发现它们只是有些相似。 It seems that the packet sniffer is catching the same data that the server is catching, but it is also recording extra packets with 6-byte long payloads, that apparently aren't being received by the server program. 数据包嗅探器似乎正在捕获与服务器捕获的数据相同的数据,但是它也正在记录具有6字节长的有效负载的额外数据包,这些显然是服务器程序未接收到的。

So, either the packet sniffer is picking up packets that the server isn't supposed to know about, or the server program is missing packets that it's supposed to be receiving. 因此,要么数据包嗅探器正在拾取服务器不应该知道的数据包,要么服务器程序丢失了它应该接收的数据包。 However, I feel somewhat confident that the server program is functioning properly and is receiving the right messages, so these extra packets being detected by the packet sniffer baffle me. 但是,我对服务器程序能够正常运行并且正在接收正确的消息充满信心,因此,这些包嗅探器会检测到这些多余的包,这使我感到困惑。 Does anyone know what these extra packets may be, and how I might filter them out? 有谁知道这些额外的数据包可能是什么,以及如何将它们过滤掉?

Notes: 笔记:

The client that is sending data to the ports I'm listening on is an old Windows NT machine in a small network, it's basically passing binary data to the server program for processing. 将数据发送到我正在侦听的端口的客户端是小型网络中的一台旧Windows NT计算机,它基本上是将二进制数据传递给服务器程序进行处理。

Unfortunately, I can't upload the code thanks to workplace policies. 不幸的是,由于工作场所的政策,我无法上传代码。 However, examples of what my code is like may be found here: http://www.tcpdump.org/pcap.html http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html 但是,可以在以下位置找到我的代码的示例: http: //www.tcpdump.org/pcap.html http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html

Thanks again! 再次感谢!

My magic ball indicates those 6 bytes long payloads might be just TCP options. 我的魔球表明那些6字节长的有效负载可能只是TCP选项。 You should skip those options if you only want to work with the payload. 如果只想使用有效负载,则应跳过这些选项。 Note that some packets might contain both a payload and some options. 请注意,某些数据包可能同时包含有效载荷和某些选项。

The data offset field in the TCP packet indicates at which point the payload starts. TCP数据包中的数据偏移字段指示有效负载从哪一点开始。 You can have a look at that here in section 3.1. 您可以在第3.1节中查看

I'd anyway recommend you using some higher level library which deals with that stuff internally. 无论如何,我还是建议您使用一些更高级别的库来内部处理这些东西。 Using libtins you could do that task using some short snippet such as: 使用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);
}

One is a simple packet sniffer written with the libpcap library that is filtering such that it only listens to packets received on a specific port, and then parses the packet such that it writes out the payload length and payload content to a binary file. 一种是使用libpcap库编写的简单数据包嗅探器,该嗅探器正在过滤,以使其仅侦听在特定端口上接收到的数据包,然后解析该数据包,以便将有效载荷长度和有效载荷内容写到二进制文件中。

TCP port or UDP port? TCP端口还是UDP端口?

If it's a TCP port, your program might receive the 3-way handshake packets and ACK-only packets. 如果是TCP端口,则您的程序可能会收到3向握手数据包和仅ACK数据包。

How are you calculating the payload length? 您如何计算有效载荷长度? You should do it by taking the IP packet's total length, subtracting from it the IP header length (not 20 bytes, but the length from the version/header length field, so that you handle IP options; if that length is < 5, ie < 20 bytes, just discard the packet, it's bogus), to get the total TCP packet length, and then subtract from that the TCP header length (not 20 bytes, but the "Data Offset" field, so you handle TCP options; if that length is < 5, ie < 20 bytes, just discard the packet, it's bogus) to get the TCP payload length. 您应该通过获取IP数据包的总长度,减去IP标头长度(不是20个字节,而是从版本/标头长度字段中减去该长度)来进行处理,以便处理IP选项;如果该长度<5,即<20个字节,只是丢弃该数据包,这是假的),得到总的TCP数据包长度,然后 TCP报头长度(不是20个字节减,但“数据偏移”字段,所以你处理TCP选项;如果长度小于5,即小于20个字节,只是丢弃数据包,这是假的)以获取TCP有效负载长度。

That should handle the options to which mfontanini refers, as well as the IP options. 那应该处理mfontanini所引用的选项以及IP选项。

If it's a UDP port, you should still handle IP options and get the total UDP packet length, and then: 如果它是UDP端口,则仍应处理IP选项并获取UDP数据包的总长度,然后:

  • if that's less than the length in the UDP header, discard the packet, it's bogus; 如果该长度小于UDP标头中的长度,则丢弃该数据包,这是伪造的;
  • if the length in the UDP header is < 8, discard the packet, it's bogus; 如果UDP标头中的长度<8,则丢弃该数据包,这是伪造的;
  • otherwise, use the length in the UDP header, minus 8, as the payload length. 否则,使用UDP标头中的长度减去8作为有效载荷长度。

The other program is a simple bsd socket server program that is set to receives messages on that specific port with the recv() function, and then similarly writes the received message length and message content out to a binary file. 另一个程序是一个简单的bsd套接字服务器程序,该程序设置为使用recv()函数在该特定端口上接收消息,然后类似地将接收到的消息长度和消息内容写出到二进制文件中。

That won't see the initial handshake or ACK-only packets. 那将看不到初始握手或仅ACK数据包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM