【发布时间】:2020-09-16 19:23:50
【问题描述】:
我有一个在用户空间中运行的缓存应用程序。通常,它使用 DPDK 直接与 NIC 交互,无需内核交互,从网络中抓取数据包,然后将它们传递出去,从缓存中生成响应,或者在某些情况下阻止它们。它对端点是透明的,并且被写入直接从 NIC 处理原始数据包数据。值得注意的是,我在这里没有进行普通的套接字编程 - 一切都在数据包级别处理,无需与 TCP/IP 堆栈交互。
由于冗长而无聊的原因,我想添加一些 NAT 功能。作为概念证明,我希望使用 iptables/netfilter 在我的应用程序中放置一个前端。所以我用这样的命令做了 NAT 部分:
sudo iptables --table nat --append PREROUTING --in-interface seg1a -j DNAT --to-destination $SERVERIP
sudo iptables --table nat --append POSTROUTING --out-interface seg1b -j MASQUERADE
sudo route add $SERVERIP seg1b
这很适合我的目的。客户端现在连接到我系统上的接口,但它们的流量被重定向到服务器。我保证他们的流量会通过我的系统,所以一切都很好。
但要作为缓存有用,我需要能够响应我从客户端获得的一些请求。我原以为我可以为此使用 NFQUEUE,它有一个小型应用程序,它从 netfilter 队列中读取数据并通过 IPC 将数据包传入和传出我的应用程序。我使用了这样的 iptables 规则:
sudo iptables --table mangle --append FORWARD -j NFQUEUE
只要我的应用程序不响应任何内容,它就可以正常工作。但是,当我的缓存尝试从某个端点响应某些内容时,事情就出错了。缓存会反转所有 L2-4 标头,管理序列和确认号等。但是数据包不会返回到客户端。
我认为发生的情况是数据包的路由决策是在发送到 NFQUEUE 之前做出的。因此,即使缓存返回的源 IP 地址和目标 IP 地址颠倒了,这与数据包的路由无关。
我尝试了很多方法来更改响应数据包的路由,但似乎没有任何效果。如何更改从 netfilter 队列中读取的数据包的路由?如果做不到这一点,有没有一种好方法可以将数据包从 netfilter 队列中注入到线路上?如果可行,我可以阻止原始请求,然后将缓存的回复作为全新的东西发送。
提前感谢您的任何建议。
【问题讨论】:
-
请您理解
I need to be able to respond to some requests that I get from clients and the packets don't get back to the client.。客户端是否使用非 dpdk NIC 在您的服务器上运行?您是否需要响应来自非 DPDK NIC 的客户端请求?如果您知道需要回复的客户端数据包签名,为什么不使用 eBPF 或 XDP 重定向到您的 DPDK 缓存应用程序,然后通过 DPDK-TAP 接口注入回内核? -
客户端位于网络上的其他位置。我正在拦截网络流量并做出响应。我没有使用任何 DPDK 接口,因为我希望能够使用现有的 iptables NAT 功能,而不是为这个快速的概念证明编写自己的功能,因此确实没有 DPDK-TAP 接口可供使用。跨度>
-
所以您当前的解决方案不使用任何 DPDK NIC 接口。如果不是 DPDK-TAP,则不清楚用户空间 DPDK 缓存应用程序如何获取数据包。是 DPDK-KNI 吗?第二个问题,如果真正的意图是发送来自特定请求的回复,XDP eBPF 将是更好的选择,因为它可以从内核访问表和 FIB。很抱歉跟进,因为我无法清楚地理解设置。
-
请忽略我之前的评论,我已经重新阅读了多次以了解问题所在。您当前的设置是
NIC <==> iptables/netfilter <= application reads from NFQUEUE and forwards via IPC => Caching userspace application。问题是关于packets not getting forwarded after getting modified from caching application by reversing L2-4 headers, manages sequence and ack. numbers。正如所讨论的,来自用户空间的任何具有正确 dst-ip 的分路接口都应该路由数据包。但你怀疑routing is not considered。是这样吗? -
如果你是用IPC本身注入回来,你能不能尝试通过TAP接口注入修改后的数据包。这样应该就可以访问Linux中的路由FIB表,在接口上发送数据包了吧?
标签: network-programming netfilter