从 NFQueue 读取数据包时的零序号

Posted

技术标签:

【中文标题】从 NFQueue 读取数据包时的零序号【英文标题】:Zero sequence number when reading packets from NFQueue 【发布时间】:2015-11-17 06:43:49 【问题描述】:

我正在尝试使用 C++ 从在 NFQueue 中排队的数据包中读取 TCP 序列号。但是当我打印出序列号时,我注意到偶尔会得到零作为序列号。我用 Wireshark 检查过,但没有序列号为零。所有的序列号都是按顺序排列的。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <iomanip>
#include <netinet/in.h>
extern "C" 
#include <linux/netfilter.h>  /* Defines verdicts (NF_ACCEPT, etc) */
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <linux/tcp.h>
#include <linux/ip.h>


using namespace std;

static int Callback(nfq_q_handle *myQueue, struct nfgenmsg *msg,
                nfq_data *pkt, void *cbData) 

    uint32_t id, tSeq;
    unsigned char *pktData;
    nfqnl_msg_packet_hdr *header;

    header = nfq_get_msg_packet_hdr(pkt);
    struct iphdr *iph = ((struct iphdr *) pktData);
    id = ntohl(header->packet_id);

    nfq_get_payload(pkt, &pktData);
    struct tcphdr *tcp = ((struct tcphdr *) (pktData + (iph->ihl << 2)));
    tSeq = ntohl(tcp->seq);

    printf("%u\n", tSeq);



int main(int argc, char **argv) 

    int fd, res;
    char buf[262124];
    struct nfq_handle *nfqHandle;
    struct nfq_q_handle *myQueue;
    struct nfnl_handle *netlinkHandle;

    nfqHandle = nfq_open();
    nfq_unbind_pf(nfqHandle, AF_INET);
    nfq_bind_pf(nfqHandle, AF_INET);

    myQueue = nfq_create_queue(nfqHandle,  0, &Callback, NULL);
    nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff);

    netlinkHandle = nfq_nfnlh(nfqHandle);
    fd = nfnl_fd(netlinkHandle);

    while(true)
        res = recv(fd, buf, sizeof(buf), 0);
        nfq_handle_packet(nfqHandle, buf, res);
    

    nfq_destroy_queue(myQueue);
    nfq_close(nfqHandle);
    return 0;

我需要检索正确的序列号以用于其他用途。我真的很想知道零序背后的原因。任何帮助将不胜感激。

【问题讨论】:

随机猜测:但TCP Offloading 会影响您所看到的吗?您是否尝试过使用ethtool 或类似设置将其关闭? @selbie 感谢您的回复。我是一名正在学习网络的学生,所以我不确定 TCP 卸载是什么。我的教授给了我这个项目作为挑战。也许您可以在我阅读时教我如何禁用 TCP 卸载?非常感谢这条线索。 Zero sequence number when reading packets from NFQueue的可能重复 【参考方案1】:

我刚刚在您的回调函数中切换了两个语句的顺序。

static int Callback(nfq_q_handle *myQueue, struct nfgenmsg *msg,
                nfq_data *pkt, void *cbData) 

    uint32_t id, tSeq;
    unsigned char *pktData = NULL;
    nfqnl_msg_packet_hdr *header;

    header = nfq_get_msg_packet_hdr(pkt);
    nfq_get_payload(pkt, &pktData);
    struct iphdr *iph = ((struct iphdr *) pktData);

    id = ntohl(header->packet_id);
    struct tcphdr *tcp = ((struct tcphdr *) (pktData + (iph->ihl << 2)));
    tSeq = ntohl(tcp->seq);

    printf("%u\n", tSeq);


iph 的值来自pktData,但是您在初始化pktData 之前将pktData 分配给了iph,这可能是您的程序获得序列号0 的原因。我在我的机器上测试过。如果它不适合你,请告诉我。

【讨论】:

我正在使用 iptables 将数据包过滤到队列中。这是我的 iptables 规则:iptables -I INPUT 1 -s 10.217.131.234 -p tcp --sport 80 -j NFQUEUE --queue-num 0。我认为 iptables 做得很好,所以我没有在我的代码中检查它。 太棒了!感谢您的帮助。我现在可以得到所有的序列号了。

以上是关于从 NFQueue 读取数据包时的零序号的主要内容,如果未能解决你的问题,请参考以下文章

在读取初始通信数据包时失去与 MySQL 服务器的连接,系统错误:111

在Google Cloud SQL中读取通信数据包时出错

从文件读取数据时的无限循环

读取边带数据包时安装 HomeBrew 意外断开连接时出错

音视频技术 即时通讯SDK

怎么才能减缓读取kafka数据的速度