1

我已经设置了一些路由规则,以确保数据包通过与套接字绑定的相同接口发送。(C++ 中的 sendto 函数将尝试根据目标地址选择最佳接口)。我正在向本地网络内外的其他设备发送 UDP 数据包,作为回报,它们通过向同一地址发送 UDP 数据包来响应。使用Wireshark,我可以验证是否发生了这种情况。

但是,尽管数据包到达网络堆栈,因此可以被 Wireshark 读取,但它们不会被绑定到特定接口的套接字接收。

我的 Ubuntu 系统上的路由规则如下:

iptables -A OUTPUT -o wlan0 -t mangle -p udp -s 193.156.108.78 --sport 12346 -j MARK --set-mark 21
ip rule add fwmark 21 table 21
ip route add dev wlan0 default via 193.156.108.1 table 21

我认为我需要对传入流量的iptables进行更改,但我不确定什么不起作用,因为以太网帧和 ip 标头上的地址似乎都是正确的。

编辑:

在 iptables 中使用 LOG 目标我已经确定数据包使用mangle表中的PREROUTING ,而不是nat表中的PREROUTING 。它也不会通过INPUT表。我不知道为什么在这一点上。

在PREROUTING in raw中设置为规则的 iptables TRACE跟踪数据包。它通过PREROUTING mangle中的规则(我没有尝试过但没有让我到任何地方)并最终以一些策略停止在那里 #。该数字代表选择了该特定表中的哪个规则。默认策略是ACCEPT ,它是可用的最高数字。(用户规则数+1)

使用iptables -L -nvxiptables -S -v接受数据包的数量和规则可以可视化。

所以即使我的数据包似乎被接受了,它仍然被丢弃在某个地方。我真的可以在这里使用一些帮助。

这是一个这样的数据包的完整跟踪:

Nov  1 09:18:23 XXX kernel: [ 2377.505697] TRACE: raw:PREROUTING:policy:3 IN=wlan0 OUT= MAC=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX SRC=XXX.XXX.XXX.XXX DST=193.156.108.67 LEN=83 TOS=0x00 PREC=0x00 TTL=50 ID=0 DF PROTO=UDP SPT=6428 DPT=12346 LEN=63
Nov  1 09:18:23 XXX kernel: [ 2377.505721] TRACE: mangle:PREROUTING:policy:2 IN=wlan0 OUT= MAC=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX SRC=XXX.XXX.XXX.XXX DST=193.156.108.67 LEN=83 TOS=0x00 PREC=0x00 TTL=50 ID=0 DF PROTO=UDP SPT=6428 DPT=12346 LEN=63

编辑2:

从同一无线网络中的设备发回的 UDP 数据包确实有效。它也适用于本地和外部网络绑定到 eth0 的套接字。这些路由通常也会跳过nat PREROUTING部分,直接进入 ip 路由表。(可视化)这显然是哪里出了问题。我无法验证重定向到另一个表是否确实有效(使用MARKip rule add from "source" table #),也欢迎提出有关此问题的建议。此外,我还无法弄清楚路由表中应该有什么以允许数据包继续输入 INPUT

不满意的解决方案:

在/etc/sysctl.conf中设置log_martians变量我终于可以看到数据包被丢弃了,大概是由于反向路径过滤。幸运的是,在同一个文件中将rp_filter变量设置为2可以解决问题。

正如这里所解释的,如果数据包进入的接口找不到到源的路由,数据包将被阻止。将此rp_filter值设置为 2 将解决我的问题,因为它依赖于我的默认接口实际上可以路由到此源的事实。

剩下的问题:

由于某种原因,将此rp_filter值设置为 0 并不总是有效(它根本不应该丢弃任何火星数据包)。不知道为什么会这样。

此外,我不太喜欢这个解决方案,如果有的话,我很乐意实施一个更好的解决方案。在我看来,我需要找到一种方法来为 wlan0 接口提供一种标准方法来路由到此源,而不仅仅是通过标记数据包。建议?

4

1 回答 1

0

这个问题的简单答案是将rp_filter值设置/etc/sysctl.conf2. 您可以分别为每个接口执行此操作,也可以将它们设置为默认和全部。我不完全确定这些值是如何工作的,但我认为默认将每个新接口设置为该特定值,并将所有当前接口设置为该值(但可能有例外?)。

net.ipv4.conf.default.rp_filter=2
net.ipv4.conf.all.rp_filter=2

请注意,您必须重置 sysctl 和网络管理器以确保使用新设置。

sysctl -p /etc/sysctl.conf
service network-manager restart

编辑:

更好的方法是将路由调用更改为:

ip rule add from 193.156.108.78 table 21
ip route add dev wlan0 default via 193.156.108.1 table 21

这样,您的系统将能够找到到源地址的路由路径,这将使包通过而无需设置rp_filter

于 2013-11-04T09:47:45.763 回答