我有一台有两个互联网连接的电脑。第一个是以太网接口,用于连接到我的本地网络并通过路由器访问互联网。第二个使用 GSM 调制解调器与 ppp 连接。
我希望在指定接口时能够独立使用每个连接,例如:
ping -I eth0 www.google.com
ping -I ppp0 www.google.com
如果未选择任何接口并且通过 eth0 的连接有效,则默认情况下能够使用 eth0,但如果通过 eth0 的连接不起作用则使用 ppp0。
我读了这个文章并创建了以下规则:
# Main table
ip route add 10.0.0.0/24 dev eth0 src 10.0.0.100
ip route add 10.64.64.64 dev ppp0 src 10.123.122.101
ip route add default via 10.0.0.1
# Specific tables
ip route add 10.0.0.0/24 dev eth0 src 10.0.0.100 table eth0
ip route add default via 10.0.0.1 table eth0
ip route add 10.64.64.64 dev ppp0 src 10.123.122.101 table ppp0
ip route add default via 10.64.64.64 table ppp0
# Rules
ip rule add from 10.0.0.100 table eth0
ip rule add from 10.123.122.101 table ppp0
乍一看似乎有效。然而 eth0 表似乎从未被使用过。我预计会发生以下情况:
ping -I eth0 www.google.ch # Use default gateway in table eth0
ping -I ppp0 www.google.ch # Use default gateway in table ppp0
ping www.google.ch # Use default gateway (main)
但是,如果我删除默认网关(主),eth0 接口将根本无法工作。显然有一些我不明白的事情。你能解释一下如何实现我想要的吗?
根据@derobert 的回答进行编辑:
我测试了以下配置,但仍然遇到相同的错误(对于 ppp0 可以,但对于 eth0 不起作用)。
路线:
# ip rule list
0: from all lookup local
1500: from 10.0.0.100 lookup eth0
1501: from 10.123.122.101 lookup ppp0
2000: from all fwmark 0x1 lookup eth0
2001: from all fwmark 0x2 lookup ppp0
32766: from all lookup main
32767: from all lookup default
# ip route list table eth0
10.0.0.0/24 dev eth0 src 10.0.0.100
default via 10.0.0.1 dev eth0
# ip route list table ppp0
10.64.64.64 dev ppp0 src 10.123.122.101
default via 10.64.64.64 dev ppp0
# ip route list table main
10.64.64.64 dev ppp0 src 10.123.122.101
192.168.1.0/24 dev eth1 src 192.168.1.1
10.0.0.0/24 dev eth0 src 10.0.0.100
防火墙:
# iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
# iptables -L -t mangle
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
CONNMARK all -- anywhere anywhere CONNMARK restore
RETURN all -- anywhere anywhere mark match !0x0
MARK all -- anywhere anywhere MARK set 0x1
MARK all -- anywhere anywhere MARK set 0x2
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MARK all -- anywhere anywhere MARK set 0x1
MARK all -- anywhere anywhere MARK set 0x2
CONNMARK all -- anywhere anywhere CONNMARK save
# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 10.0.0.1 anywhere to:10.0.0.100
SNAT all -- 10.64.64.64 anywhere to:10.123.122.101
我删除了所有其他防火墙规则,以确保它们不会干扰。我得到这个结果:
# ip route get 8.2.1.1 from 10.0.0.100
8.2.1.1 from 10.0.0.100 via 10.0.0.1 dev eth0
# ip route get 8.2.1.1 from 10.123.122.101
8.2.1.1 from 10.123.122.101 via 10.64.64.64 dev ppp0
# ping -I ppp0 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=45 time=350.108 ms
64 bytes from 8.8.8.8: seq=1 ttl=45 time=349.768 ms
64 bytes from 8.8.8.8: seq=2 ttl=45 time=329.671 ms
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 329.671/343.182/350.108 ms
128# ping -I eth0 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
^C
--- 8.8.8.8 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss
规则看起来没问题,但显然还有另一个问题。我不太明白SNAT在这里的作用。我添加了规则来反映答案的配置,但它们可能是错误的。
答案1
我的配置稍微复杂一些,其中还包括机器上的 NAT 和动态(内部)路由。
它有几个部分。让我们从规则开始:
Maginot:~# ip rule ls
0: from all lookup local
1000: from all lookup main
1500: from 173.167.51.136/29 lookup comcast
1501: from 76.160.165.106/29 lookup cavtel
1502: from 151.200.251.90/31 lookup vzdsl
1502: from 151.200.251.92/31 lookup vzdsl
1502: from 151.200.251.94 lookup vzdsl
2000: from all fwmark 0x1 lookup comcast
2001: from all fwmark 0x2 lookup cavtel
2002: from all fwmark 0x3 lookup vzdsl
2500: from all lookup comcast
2501: from all lookup cavtel
2502: from all lookup vzdsl
32767: from all lookup default
(这些表的名称在 中/etc/iproute2/rt_tables
)
正如您所看到的,我们目前有三个 ISP,每个 ISP 都有几个静态 IP 地址。规则 1500–1502 将来自这些源 IP 地址的流量发送到适当的接口。规则 2000–2002 将具有给定防火墙标记(我们将对此进行说明)的流量发送到适当的接口。规则 2500–2502 给出了我们的 ISP 对于尚未分配给 ISP 的流量的优先顺序。如果其中一个出现故障,您可以删除它的规则,然后使用列表中的下一个。
每个路由表都相当简单:
Maginot:~# ip route ls table comcast
default via 173.167.51.142 dev comcast
(本地和主要有更多的内容,但分别是直接连接和内部路线。表格默认为空)。
接下来,重要的是,一旦连接被分配给 ISP,它就会保留在那里(包括传入连接)。尝试移动它是不可能的,因为我们每个接口上都有不同的 IP 地址,而且我们的 ISP 实际上有反向路径过滤。我们将它们保留在具有防火墙规则的同一 ISP 上。
请记住 SNAT 已完成后路由,所以ip rule
策略不会有帮助。你必须使用其他东西(也许这是你的问题?)
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j RETURN # if already set, we're done
iptables -t mangle -A PREROUTING -i wan -j MARK --set-mark $MARK_CAVTEL
iptables -t mangle -A PREROUTING -i comcast -j MARK --set-mark $MARK_COMCAST
iptables -t mangle -A PREROUTING -i vz-dsl -j MARK --set-mark $MARK_VZDSL
iptables -t mangle -A POSTROUTING -o wan -j MARK --set-mark $MARK_CAVTEL
iptables -t mangle -A POSTROUTING -o comcast -j MARK --set-mark $MARK_COMCAST
iptables -t mangle -A POSTROUTING -o vz-dsl -j MARK --set-mark $MARK_VZDSL
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark
这是来自设置它的 shell 脚本;变量$MARK_…
与您在上述规则中看到的标记相匹配。相当简单:恢复连接标记(记住,标记是针对每个数据包的);如果现在有一个标记(来自连接标记),那么我们就完成了。否则,根据涉及的接口设置标记。
注意它会恢复标记前路由,并且只在事后保存它。并且无论如何,该标记都设置为传出接口(这是有争议的)。
最后,还有实际的 NAT 规则。我们有几个本地前缀,此代码在 for 循环中运行,并$local
设置为每个前缀:
iptables -t nat -A POSTROUTING -s $local -o wan -j SNAT --to-source 76.160.165.106
iptables -t nat -A POSTROUTING -s $local -o comcast -j SNAT --to-source 173.167.51.137
iptables -t nat -A POSTROUTING -s $local -o vz-dsl -j SNAT --to-source 151.200.251.90
(注意:还有很多规则,包括一些 DMZ 服务器的 DNAT 等......我想我已经复制了所有相关的规则。)
答案2
您需要将 eth0 设备的权重设置为比 ppp0 设备更高的优先级。
例子:
ip route append default scope global nexthop via 10.0.0.1 dev eth0 weight 2 nexthop via 10.64.64.65 dev ppp0 weight 3