数据包在libnetfilter_queue中永远循环



我想为 TCP/UDP 流量实现一个网络延迟模型,如 Linux libnetfilter_queue延迟数据包问题中所述。我在那里遵循了Andy的建议,将整个数据包复制到我的程序中,并将其置于优先级队列中。随着时间的流逝,优先级队列中的数据包将被删除并使用RAW套接字进行调度。

我面临的问题是:libnetfilter_queue对数据包的初始捕获是通过匹配端口来完成的(sudo iptables -A OUTPUT -p udp --dport 8000 -j NFQUEUE --queue-num 0)。当这些数据包被RAW套接字重新注入时,它们会再次被libnetfilter_queue拾取(因为端口保持不变),因此会永远继续循环。

我真的很困惑,想不出路。请帮助我。

使用 skb->mark。这是一个仅存在于主机 IP 堆栈中的标记。它不会影响网络数据包本身中的任何内容。

您可以使用"--mark"过滤器使用iptables对其进行过滤。使用它从延迟链返回,以便重新插入的数据包不会再次延迟。

iptables -A DELAY -m mark --mark 0xE -j RETURN
iptables -A DELAY -j DELAY

您可以使用 setsockopt(fd, SOL_SOCKET, SO_MARK, ...) 配置原始套接字以应用标记。打开套接字后,您只需执行此操作一次。标记值将自动应用于您通过套接字发送的每个数据包。

这可能不是最好的方法,但这里有一个可能的解决方案。您可以使用 IP 标头中的 DSCP 字段来区分新数据包和要重新注入的数据包。 将 iptables 规则更改为仅将 DSCP 为 0 的数据包排队(请参阅 http://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#DSCPMATCH)。这假设当您的操作系统发送数据包时,它会将 DSCP 设置为 0。现在,操作系统生成的所有新数据包都将发送到您的程序,因为它们仍然与iptables规则匹配。使用 RAW 套接字在程序中创建新数据包时,请将 DSCP 值设置为非零值。重新注入新数据包时,它将不再与 iptables 规则匹配,并将通过网络发出。

如果您不希望数据包在设置 DSCP 值的情况下通过网络发出,则可以添加另一个 iptables 规则以将 dscp 值重写为 0。

最新更新