今天是路由日。阅读本文后,您应该已经了解如何添加 IP 路由、 的基本用法ip rule
,并且对 有了很好的理解。iptables
这是交叉发布(法语)Linux操作系统。
问题
我有一个桥接模式下的 ADSL 调制解调器 (Freebox) 和一个 DMZ 模式下的光纤 (Livebox)。除选定的流量外,所有流量都通过 ADSL 传输,另一个流量通过光纤通道传输。这是我的设置,在相反的情况下,问题仍然相同。
为了缓解这个问题,我将讨论通过运行 Debian GNU/Linux 的路由器的流量,而不是该路由器产生的流量。
我的 ADSL 地址是 82.236.xxx.xxx,光纤是 90.76.xxx.xxx。
应该怎么做
我们理所当然地认为mangle
桌子是空的。
> ip route show table livebox
default via 192.168.1.1 dev eth_livebox src 192.168.1.253
82.236.xxx.0/24 dev eth_adsl scope link src 82.236.xxx.xxx
192.168.0.0/24 dev bridge_local scope link src 192.168.0.253
192.168.1.0/24 dev eth_livebox scope link src 192.168.1.253
iptables -t mangle -I PREROUTING --destination 23.23.114.123 -j MARK --set-mark 1
ip rule add from all fwmark 0x1 lookup livebox
这不起作用。这意味着当我这样做时
curl http://api.ipify.org/ --resolve api.ipify.org:80:23.23.114.123
从 LAN 客户端来看,没有返回任何内容。
什么有效
表格livebox
没有变化。但是,刷新表格后mangle
,我们用以下内容填充它:
iptables -t mangle -I PREROUTING --source 23.23.114.123 -j TOS --set-tos 0x10
iptables -t mangle -I PREROUTING --destination 23.23.114.123 -j TOS --set-tos 0x10
ip rule add from all tos 0x10 lookup livebox
进而 :
> curl http://api.ipify.org/ --resolve api.ipify.org:80:23.23.114.123
90.76.xxx.xxx
答案1
为什么?
在这两个片段之间,我改变了两件事:
- 我用的是服务条款IP 头而不是防火墙标记,由内核及其模块内部管理。
- 我标记了返回的包裹。
我撒了谎(省略):rp_filter
我忘了说,在所有接口上,都rp_filter
设置为 1。根据内核文档,值 1 代表严格反向路径检查,定义在RFC 3704。
总而言之,当数据包进入接口时,内核会交换IP 地址source
字段destination
,并尝试路由这个新的假数据包。如果所选路由通过数据包来源接口发出,则检查成功。否则,数据包将被丢弃。
因此,根据What should work
,由于传入数据包未标记为1
,因此严格反向路径检查失败。事实上,返回数据包通过eth_livebox
,但没有标记,根据main
表格路由,该表格表示通过eth_adsl
。这是失败的。这是更改 2 的原因。
为什么是 TOS 而不是 MARK ?
是的,当然,我尝试过-j MARK
返回数据包。但这不起作用。经过几个小时挖掘旧邮件列表消息后,我发现这个:
好的,看看 fib_validate_source(),rp_filter 的工作方式似乎就是内核接收数据包,反转源地址和目标地址以及接口,然后尝试进行路由查找。它在构建路由密钥时完全忽略标记,但奇怪的是,它确实会检查 TOS。
好的。所以我阅读了一些有关 TOS 的文档,由于我仍在寻找解决方案,所以我快速而粗略地做了一下。它有效。这就是更改 2 的原因。
还有更好的吗?
我让你检查一下代码fib_validate_source()
。说实话,它对我来说太重了。
但在我看来,结果是不一致的。我知道那TOS
是在报头内部IP
,防火墙标记特定于主机内部。另一方面ip rule
TOS
有一个语法,可以使用 来在标头值或防火墙标记值上查找路由fwmark
。
我现在真正不知道应该做什么,以下是我的结论,非排他性的。
放弃rp_filter
公共接口
的目标rp_filter
是避免 DDoS,同时也过滤直接在我自己管理的网络中伪造数据包的恶意客户端。这有点像防晒指数,它可以保护其他参与者。
在我的公共接口上,我显然有一个像这样的路由条目default via IP
,所以无论如何,rp_filter
都会得出数据包可以应答的结论。事实上,如果数据包到达我的路由器,那是因为我的 ISP 让它通过了。他们设法路由了它。
所以我可以放弃并rp_filter
在所有这些接口上将其设置为 0(警告:应用了 net.ipv4.conf.eth_livebox.rp_filter 和 net.ipv4.conf.all.rp_filter 之间的最大值)。
编辑:用户rpfilter
来自iptables
LinuxFR 上的某个人引起了我的注意对此:该rp_filter
控件已弃用,或至少处于废弃状态。确实有一个rpfilter
模块对于iptables
,这是它的未来。例如,从这里:
iptables -A PREROUTING -t raw -m rpfilter --invert -j DROP
ip6tables -A PREROUTING -t raw -m rpfilter --invert -j DROP
它与防火墙很好地集成在一起,可以正常工作,并且返回的数据包甚至不需要标记,因为它们可以通过其状态识别。
向内核开发人员报告此“错误”
在我看来,这似乎非常不一致,而且记录非常糟糕。一方面,ip rule
让你制定适用于传入数据包的规则,但不能适用于返回数据包:行为不当。
但我现在的情况是:我没有时间去熟练地阅读、理解并修复这段代码。我甚至不知道这是否有一个好的理由,比如在调用时防火墙标记可能不可用fib_validate_source
。
但是如果有人告诉我可以向关心的人报告,或者解释,甚至修复和改进,我会很乐意这样做。
rp_filter
编辑:也许应该更新参数的文档……