我有两个上游提供商的多宿主设置。 我想限制一些连接只使用一个提供者 – 本地传出连接。 所以,我做了一个自定义的路由表,它具有直接连接的networking路由和默认路由:
$ ip route show table 2 default via 5.1.0.1 dev upstream_b 5.1.0.0/16 dev upstream_b scope link src 5.1.0.2
接下来,我在iptables中使用select器来添加fwmark到一些连接和ip-rule来覆盖路由表select:
# for output traffic # restore packet mark from connection mark iptables --table mangle --append OUTPUT -j CONNMARK --restore-mark # for !0 packet marks bail out iptables --table mangle --append OUTPUT -m mark ! --mark 0 -j ACCEPT # set packet mark iptables --table mangle --append OUTPUT -m cgroup --cgroup 0x00010002 -j MARK --set-mark 0x2 # save packet mark to connection mark iptables --table mangle --append OUTPUT -j CONNMARK --save-mark # for input traffic restoring mark from connmark iptables --table mangle --append PREROUTING -j CONNMARK --restore-mark # adding policy forwarding ip rule add from all fwmark 2 table 2
因此,对于某些进程(在指定的net_cls cgroup中),它的传出连接将命中连接标记规则,然后应该通过upstream_b接口进行路由。
但是这不起作用(对于放入net_cls cgroup中的bash shell):
$ curl --resolve ifconfig.co:80:188.113.88.193 -v http://ifconfig.co * Added ifconfig.co:80:188.113.88.193 to DNS cache * Rebuilt URL to: http://ifconfig.co/ * Hostname ifconfig.co was found in DNS cache * Trying 188.113.88.193... * Immediate connect fail for 188.113.88.193: Network is unreachable * Closing connection 0 curl: (7) Couldn't connect to server
以前的结果发生,而main路由表没有默认路由(即没有路由到ifconfig.co)。
但这不是全部。 由于我有多宿主设置,通常有一个ECMP路由来平衡通过两个提供商的stream量。 而对于上述testing,我得到了一个有趣的结果。 tcp-syn软件包转到正确的接口,但源地址不正确(来自其他接口)。
因此,join这些观察,首先,根据main路由表做出路由决策(因此networking不可达)。 接下来,当一个包被进一步处理时,它会触发标记规则,然后发生重新路由(基于自定义路由表)。 但是源地址已经在第一个路由决策中被设置,并且在这里没有被纠正。
我对问题来源的理解是否正确?
我需要为一些本地进程强制执行一个非默认路由表,上面的方法不起作用。 执法能否完成? 例如,是否可以触发源地址重新计算?
编辑。 考虑下面的图(这里的内核版本不是那么现代,但仍然有用;该图来自http://open-source.arkoon.net/kernel/kernel_net.png ):
看起来,第一个路由决策和软件包源地址select确实是在任何iptables规则可以启动之前执行的(见右下angular)。