我遇到了一个问题。我的所有机器都位于路由器后面,该路由器连接到调制解调器上的 ETH 端口。该端口的下载/上传功能太有限了。因此,我尝试将两根电缆从路由器连接到调制解调器的两个端口。我一直在研究如何解决这个问题,我不知道该尝试什么了。
我的路由器有4个接口:
enp1s0f0 172.16.0.3
enp4s0f1 10.0.0.6
enp1s0f1 192.168.0.3
enp4s0f0 192.168.0.6
正如你所看到的,eth3 和 eth4 在同一个网络上,这很奇怪。如果我想使用两个 ETH 端口连接到调制解调器 (192.168.0.1),就必须采用这种方式。
所以,这是我尝试过的:
echo "1 myorg" >> /etc/iproute2/rt_tables #added a custom routing table myorg
sudo ip route add 192.168.0.1 scope link dev enp4s0f0 #don't know if it is really necessary
sudo ip rule add from 192.168.0.6 table myorg
sudo ip route add default via 192.168.0.1 dev enp4s0f0 table myorg #second default gateway through myorg table
我得到这些路线的结果:
$ ip -4 route show table main
default via 192.168.0.1 dev enp1s0f1 onlink
10.0.0.0/24 dev enp4s0f1 proto kernel scope link src 10.0.0.6
172.16.0.0/24 dev enp1s0f0 proto kernel scope link src 172.16.0.3
192.168.0.0/24 dev enp1s0f1 proto kernel scope link src 192.168.0.3
192.168.0.0/24 dev enp4s0f0 proto kernel scope link src 192.168.0.6
192.168.0.1 dev enp4s0f0 scope link
$ ip -4 route show table myorg
default via 192.168.0.1 dev enp4s0f0
$ sudo route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.0.1 0.0.0.0 UG 0 0 0 enp1s0f1
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 enp4s0f1
172.16.0.0 0.0.0.0 255.255.255.0 U 0 0 0 enp1s0f0
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 enp1s0f1
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 enp4s0f0
192.168.0.1 0.0.0.0 255.255.255.255 UH 0 0 0 enp4s0f0
我使用ufw作为NAT防火墙。我在 *nat 部分添加:
:POSTROUTING ACCEPT - [0:0]
-A POSTROUTING -s 172.16.0.0/24 -o enp1s0f1 -j MASQUERADE
-A POSTROUTING -s 10.0.0.0/24 -o enp4s0f0 -j MASQUERADE
或者,问题是 10.0.0.0 网络中的计算机接收来自调制解调器(网关 192.168.0.1)的 ping 响应,或者来自 172.16.0.0 网络的计算机。根据具体情况,可能会出现相反的情况,我不知道为什么。
我的调制解调器在两个 ETH 端口上看到客户端 192.168.0.3 和 192.168.0.6。
那么,是否可以在具有此拓扑(同一网络上有两个接口的路由器)的所有计算机和所有网络上进行 WAN 访问?
答案1
虽然没有明确写入,但我想目标是分割流量,以便:
- 172.16.0.0/24 流量流经 enp1s0f1
- 10.0.0.0/24 流量流经 enp4s0f0
正如OP所写,这需要基于策略/源的路由。iptables和网络过滤器很少有用(至少单独使用):
- 一般来说iptables和网络过滤器不路由也不关心路由。网络路由堆栈路由。一些iptables' 操作仍会导致路由决策更改(如此处所述示意图)
- 进行的任何操作后布线顾名思义,发生了后路线决定已做出:更改路线为时已晚。在这里,虽然nat/后路由需要规则,它们不会改变路线。
每当iptables可以避免解决路由问题,最好避免它。有时它是无法避免的(然后通常iptables用于向数据包添加标记,并且该标记用于ip rule
条目中)。
路线
我会假设rp_filter=1
在所有接口上设置,因为它是大多数发行版的默认设置,以启用严格反向路径转发。
源地址由规则选择,目的地由路由表选择。当只应选择多个路由中的一个时(然后仅将这一个添加到表中),附加路由表应具有足够的信息来覆盖(无歧义)路由。通常还必须复制主表中的其他路由,否则可能会发生不好的事情。
在我的回答中,我不会优先考虑一个网络或另一个网络:每个网络都会有自己的路由表。我将忘记表 1,并使用表 10 表示 LAN 10.0.0.0/24,使用表 172 表示 LAN 172.16.0.0/24。保留 NAT 规则,删除规则和附加路由表,以及192.168.0.1 dev enp4s0f0 scope link
从 main.conf 中删除规则和附加路由表。
10.0.0.0/24 <--> 10.0.0.6 enp4s0f0 | 的路由enp4s0f1 192.168.0.6 <--> 192.168.0.1/默认:
ip rule add from 10.0.0.0/24 lookup 10 ip route add table 10 10.0.0.0/24 dev enp4s0f1 ip route add table 10 192.168.0.0/24 dev enp4s0f0 src 192.168.0.6 ip route add table 10 default via 192.168.0.1
上面,如果没有 10.0.0.0/24 的重复路由条目,系统本身将无法访问此 LAN:它将解析该路由,因为必须经过默认网关,仅适用于严格反向路径转发(SRPF) 的目的使得调试变得困难。如果不添加的话,这就是一个坏事的例子。如有疑问,只需重复路线即可。
其他等效选项可以代替将上述规则更改为的附加路线:
ip rule add from 10.0.0.0/24 iif enp4s0f1 lookup 10
因此它不会匹配本地(非路由)流量,并且只会使用主表。
172.16.0.0/24 <--> 172.16.0.3 enp1s0f0 | 的路由enp1s0f1 192.168.0.3 <--> 192.168.0.1/默认:
ip rule add from 172.16.0.0/24 lookup 172 ip route add table 172 172.16.0.0/24 dev enp1s0f0 ip route add table 172 192.168.0.0/24 dev enp1s0f1 src 192.168.0.3 ip route add table 172 default via 192.168.0.1
在 Linux 系统上更改传出源 IP 地址时,还可以更改本地发起的传出流量的路由(链接)。这应该是可选的,但关于 ARP 流量的下一部分将其强制执行:
ip rule add from 192.168.0.6 lookup 10 ip rule add from 192.168.0.3 lookup 172
任何涉及规则中覆盖路由的非特殊情况也必须重复
这里唯一缺少的路由是两个特殊 LAN 本身之间的路由:
表 10 中达到 172.16.0.0/24
表 172 中达到 10.0.0.0/24
因为每个附加表还没有到另一端的路由,所以它将使用默认路由(但会再次被 SRPF 阻止),从而防止两个特殊网络之间再进行通信。因此,只需为每个表复制缺少的路由即可:
ip route add table 10 172.16.0.0/24 dev enp1s0f0
ip route add table 172 10.0.0.0/24 dev enp4s0f1
使用此模型,例如,如果要添加另外两个“正常”内部网络,它们可以在彼此之间进行通信(并且将使用主表的默认路由到外部),而无需额外设置,但再次需要在每个附加路由表用于与两个特殊 LAN 进行通信。
现在路线已经很好了,但是还有...
这ARP通量问题
Linux 遵循弱宿主模型。 IP 路由就是这种情况,Linux 应答 ARP 请求的方式也是如此:来自任何接口的任何 IP,但当然使用接口自己的 MAC 地址。由于当多个接口位于同一 LAN 上时,这种情况可能会同时发生在所有接口上,因此通常最快的获胜。然后 ARP 信息会缓存在远程系统上,并会在那里保留一段时间。最终缓存过期,同样的情况也会发生,但结果可能不同。那么这怎么会导致问题呢?这是一个例子:
- 路由器(调制解调器)向 192.168.0.6 发送 ARP 请求,以发回对最初从 10.0.0.0/24 发送的流量的路由和 NAT(通过 Linux)回复。
- Linux 回复于enp1s0f1(enp1s0f1赢得比赛)使用enp1s0f1的 MAC 地址回复告诉它有 192.168.0.6。
- 在几秒钟到几分钟内,来自 192.168.0.6 的路由器的未来入口 IP 数据包到达enp1s0f1,
- 同时出口来自 192.168.0.6 的数据包使用enp4s0f0。
这种非对称路由被捕获严格反向路径转发(rp_filter
)并且流量将会失败。这甚至可能会随机工作几秒钟,然后再次失败。根据总体流量,问题甚至可能稍后切换到其他链路(然后问题切换到其他 LAN)。
幸运的是,为了防止这种情况发生,Linux 提供了一个仅与策略路由一起使用的设置,以使 ARP 遵循路由定义的相同规则:arp_filter
。
arp_filter - 布尔值
1 - 允许您在同一子网上拥有多个网络接口,并为每个接口提供 ARP界面回答基于内核是否会将来自 ARP 的 IP 的数据包路由到该接口(所以您必须使用基于源的路由为了这个工作)。换句话说,它允许控制哪些卡(通常是 1 个)将响应 arp 请求。
sysctl -w net.ipv4.conf.enp4s0f0.arp_filter=1
sysctl -w net.ipv4.conf.enp1s0f1.arp_filter=1
现在 ARP 行为是正确的,如果设置刚刚到位,应该强制刷新 ARP 缓存同行(此处:调制解调器)通过执行重复地址检测arping
(从iputils/iputils-arping)它将向对等点广播并让他们更新缓存:
arping -c 5 -I enp4s0f0 -D -s 192.168.0.6 192.168.0.6 &
arping -c 5 -I enp1s0f1 -D -s 192.168.0.3 192.168.0.3
请注意,上一部分第 3 点中的两个规则现在是强制性的,因为 IP 地址 192.168.0.3 和 192.168.0.6 必须在策略路由规则中匹配才能进行正确的 ARP 解析arp_filter=1
。
如何调试
ip route get
对于检查路由和反向路径过滤非常有用:
上面第 4 点的新测试用例:
# ip route get from 10.0.0.111 iif enp4s0f0 172.16.0.111
172.16.0.111 from 10.0.0.111 dev enp1s0f0 table 10
cache iif enp4s0f0
# ip route get from 172.16.0.111 iif enp1s0f0 to 10.0.0.111
10.0.0.111 from 172.16.0.111 dev enp4s0f1 table 172
cache iif enp1s0f0
删除规则或路由时:
# ip route get from 10.0.0.111 iif enp4s0f1 8.8.8.8
8.8.8.8 from 10.0.0.111 via 192.168.0.1 dev enp4s0f0 table 10
cache iif enp4s0f1
# ip rule del from 10.0.0.0/24 lookup 10
# ip route get from 10.0.0.111 iif enp4s0f1 8.8.8.8
8.8.8.8 from 10.0.0.111 via 192.168.0.1 dev enp1s0f1
cache iif enp4s0f1
# ip route get from 192.168.0.1 iif enp4s0f0 192.168.0.6
local 192.168.0.6 from 192.168.0.1 dev lo table local
cache <local> iif enp4s0f0
# ip rule delete from 192.168.0.6 lookup 10
# ip route get from 192.168.0.1 iif enp4s0f0 192.168.0.6
RTNETLINK answers: Invalid cross-device link
这显示了结果如何根据(缺乏)规则和附加路线而改变。最后的结果是错误消息,告诉反向路径转发检查失败(=>丢弃)。
然后有ip neigh
(最有用的同行系统)来检查 ARP 条目tcpdump
等。