使用NFQUEUE发送排队的数据包?

我正在使用libnetfilter_queue和带有NFQUEUE目标的iptables,使用–queue-num x将传入的数据包存储在三个不同的队列中.

我用libnetfilter_queuefunctions成功创建了三个队列,绑定它们,听取它们并从它们读取如下:

/* given 'h' as a handler of one of my three queues */
fd = nfq_fd(h);
while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
    nfq_handle_packet(h, buf, rv);
}

用nfq_handle_packet触发的回调函数有nfq_set_verdict(qh,id,NF_ACCEPT,0,NULL);命令在它处理完成后立即发送数据包.
问题是:我不希望立即发送每个数据包,因为我需要将它们存储在自定义结构中(如下所示).

所以我遇到了一个潜在的解决方案:我可以在我想要排队的每个数据包上调用NF_DROP判决而不是NF_ACCEPT(因此不会立即发送),将其存储在我的自定义结构中,然后(迟早)重新根据我的需要注入它.

听起来很棒,但情况是:我不知道如何从我的用户空间应用程序中重新注入我的排队数据包.在我的代码的同一点再次使用nfq_set_verdict是正确的,但使用NF_ACCEPT判决?或者我应该打开一个插座(也许是一个原始插座)?

这是我的自定义结构

struct List {
    int queue;
    int pktsize;
    unsigned char *buffer;
    struct nfq_q_handle *qh;
    struct nfqnl_msg_packet_hdr *hdr;
    struct List *next;
};

表示符合上述规则的数据包.

这些是我存储数据包的队列.

struct List *List0 = NULL;  // low priority
struct List *List1 = NULL;  // medium priority
struct List *List2 = NULL;  // high priority

我有Ubuntu 14.04 3.13.0-57-generic.

任何建议,将不胜感激.

最佳答案
你的想法很有意义.事实上,我已经看到在我工作的商业产品中实施了一个非常类似的方案.它必须以高速率处理单个数据包,因此它总是复制传入的数据包并立即设置NF_DROP判决.然后它将执行处理,如果它决定应该转发数据包,它会将副本发送到出站接口.所以你并不孤单.

据我所知,每个数据包只能调用一次nfq_set_verdict.一旦设置了判决,NFQUEUE就会将数据包发送到目的地(在您的情况下是数据包天堂).它不会保留数据包的额外副本,以防您改变主意.因此,要将数据包发送回网络,您必须存储它的副本并使用您自己的套接字发送它.是的,如果你想按原样发送收到的数据包(包括标题),那么出站套接字必须是原始的.

转载注明原文:使用NFQUEUE发送排队的数据包? - 代码日志