![在两个 NIC 之间共享相同的 IP,以便通过专用 NIC 路由一个 IP](https://linux22.com/image/752896/%E5%9C%A8%E4%B8%A4%E4%B8%AA%20NIC%20%E4%B9%8B%E9%97%B4%E5%85%B1%E4%BA%AB%E7%9B%B8%E5%90%8C%E7%9A%84%20IP%EF%BC%8C%E4%BB%A5%E4%BE%BF%E9%80%9A%E8%BF%87%E4%B8%93%E7%94%A8%20NIC%20%E8%B7%AF%E7%94%B1%E4%B8%80%E4%B8%AA%20IP.png)
我有几台主机连接到同一台交换机,它们都位于同一子网 (10.0.0.0/16)。其中两台主机有更快的网络接口,所以我将它们连接在一起,这意味着这两台机器现在可以直接相互连接,而无需通过交换机。
我现在需要设置路由,以便当这两台机器尝试互相通信时,数据包优先通过这个更快的直接链路,而不是通过交换机的较慢链路。
最简单的方法是将直接链接配置为不同的子网,但随后我将需要根据要使用的接口使用不同的 IP 或主机名,并且因为我希望能够将标准配置部署到所有机器(例如,使用主机名的 NFS 挂载)而不必维护自定义 IP 覆盖/etc/hosts
,我觉得这种解决方案很容易导致主机名错误并通过错误的接口发送流量。
我正在寻找一种方法来告诉两台 Linux 机器,即使eth0
处理 10.0.0.0/16,当您想要与 10.0.0.5 通信时,即使它位于 eth0 的子网中,eth1
也要发送数据包。
我尝试添加一个主机路由规则,通过route add -host 10.0.0.5 dev eth1
该规则将数据包发送到正确的接口,但它来自错误的 IP 地址(直接链接的子网而不是原始子网)。
我猜想解决此问题的唯一方法是在两个接口上设置相同的 IP 地址,但这会导致任何问题吗?一台机器是否可以在多个 NIC 上正确使用相同的 IP 而不会导致问题?我假设我需要正确设置路由指标,以便优先考虑连接到交换机的 NIC(以避免子网的所有流量被错误地发送到另一台主机),但是对于此设置,我还需要注意什么吗?它会导致任何其他问题或难以解决的问题吗?
或者有没有更好、更强健的方法来实现这一点?
编辑:这是@AB 请求的额外内容:
$ ip -br link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eth0 UP ec:f4:xx:xx:xx:a4 <BROADCAST,MULTICAST,UP,LOWER_UP>
eth1 UP ec:f4:xx:xx:xx:a5 <BROADCAST,MULTICAST,UP,LOWER_UP>
$ ip -br address
lo UNKNOWN 127.0.0.1/8
eth0 UP 10.0.0.4/16
eth1 UP 10.0.99.4/24
$ ip route
default via 10.0.0.1 dev eth0 proto static
10.0.0.0/16 dev eth0 proto kernel scope link src 10.0.0.4
10.0.0.5 dev eth1 scope link
10.0.99.0/24 dev eth1 proto kernel scope link src 10.0.99.4
我在单独的子网上设置了直接链接 ( eth1
),然后尝试了route
原始帖子中的命令,这就是现在的情况。看来我可能需要src
为我的直接路由设置属性。
答案1
由于 10.0.99.4 是 10.0.0.0/16 的一部分,因此应避免使用此 IP 地址。否则,即使在eth0考虑到 Linux 使用弱主客体模型并默认会响应此 IP 地址的 ARP 请求eth010.0.99.4,造成 ARP 冲突。请勿使用冲突的 IP 地址。
清理:
ip route flush dev eth1
ip address flush dev eth1
使用粘合 IP 地址的标准方法
让我们选择两个不相关的地址供两台主机使用。它们必须不与网络上正在使用的任何其他地址冲突,但由于它们是点对点 /32 地址,因此可以做任何事情,它们不会用作 LAN 的一部分,而只能用作点对点/对等地址。我将任意使用 192.168.100.4/32 和 192.168.101.5/32。如果以后有 2 台以上的主机继承了更快的交换机并使用这个单独的交换机连接在一起,则可以稍微修改一下,这样将相关的 IP 地址放在同一个块中就更容易了。
主机 10.0.0.4 的配置:
# /32 : no route gets created (beside the hidden *local* routing table)
ip address add 192.168.100.4/32 dev eth1
# add the peer (point to point) route on the same link
ip route add 192.168.101.5/32 dev eth1
实际上,上面的两个命令都有一个快捷方式,您可以用下面的单个命令替换它们:
ip address add 192.168.100.4 peer 192.168.101.5/32 dev eth1
现在告诉主机,要到达 10.0.0.5/32(比 10.0.0.0/16 更具体),有一个使用对等 IP 地址的路由,但是倾向于使用不同的源 IP 地址比默认选择的要多(过时的route
命令无法做到这一点):
ip route add 10.0.0.5/32 via 192.168.101.5 dev eth1 src 10.0.0.4
通过这个,您可以获得:
# ip route get 10.0.0.5
10.0.0.5 via 192.168.101.5 dev eth1 src 10.0.0.4 uid 0
cache
有一个小缺点:IP 广播仍然会发送到eth0而如果严格反向路径转发处于活动状态(或sysctl net.ipv4.conf.eth0.rp_filter
给出sysctl net.ipv4.conf.all.rp_filter
1,而不是 0 或 2),这些广播在由对等端发送时(例如在对等端主机 10.0.0.5 上运行类似于 的东西echo test | socat udp4-datagram:10.0.255.255:5555,broadcast -
)将被忽略,因为现在接收到错误的接口。因此,如果您正在使用依赖于此的协议,并且已经应用了严格反向路径转发,请切换eth0如果需要,切换到松散模式:
sysctl -w net.ipv4.conf.eth0.rp_filter=2
主机 10.0.0.5 的等效配置:
ip address add 192.168.101.5 peer 192.168.100.4/32 dev eth1
ip route add 10.0.0.4/32 via 192.168.100.4 dev eth1 src 10.0.0.5
sysctl -w net.ipv4.conf.eth0.rp_filter=2
例如在类似 Debian 的下拉 interface
配置文件中,您可以使用pointopoint
关键字和一些up
附加命令来表示没有方向配置等效项的任何命令。(sysctl
宁愿放在/etc/sysctl.d
)。
无需额外(或重复)IP 地址的简化方法
实际上,192.168.100.4 和 192.168.100.5 的唯一作用是解析链路层地址以了解 10.0.0.4 和 10.0.0.5 的路由:它们用作某种粘合剂,不发挥任何其他作用。这些 IP 地址将完全不可见,并且没有 IP 数据包会在其内容中使用 192.168.100.4 或 192.168.100.5(除非明确使用这些地址),只有 ARP 请求和应答才会使用。根本不需要使用这样的粘合 IP 地址。
例如主机提供商Hetzner 举了一个例子:
ip route add 203.0.113.40/32 dev tap0
到达接口上的 IP 地址无需在此接口上配置 IP 地址(也不将此接口用作桥接端口)。在此示例中,对等端tap0
(以太网模式下链接到另一端 VM 的 tun/tap 设备)必须回答 ARP 请求以解析链路层地址。
但是出于对称原因,如果已经在其他地方配置了 IP 地址,则不需要在那里配置 IP 地址,以便正确响应通过eth1:又来了Linux 实现的一部分弱宿主模型。
因此,这可以简单地用于主机 10.0.0.4,而不涉及任何额外的 IP 地址,只需使用一个命令:
ip route add 10.0.0.5/32 dev eth1
或者指定来源(以避免在主机有多个的情况下产生歧义):
ip route add 10.0.0.5/32 dev eth1 src 10.0.0.4
对于主机 10.0.0.5:
ip route add 10.0.0.4/32 dev eth1 src 10.0.0.5
对于接受“慢速”广播eth0从同行来看,他们仍然像以前一样要求:
sysctl -w net.ipv4.conf.eth0.rp_filter=2
可以在两个接口上回答解析其 IP 地址的 ARP 请求(如上文链接所示Linux 默认这样做),但此处的分辨率或条目在通常(旧)一侧eth0 如果有的话(例如:在这些设置到位之前)不会触发以下效果ARP 流量因为双方都配置了一起使用eth1对于这些路线没有留下其他可能的解释。
选择你喜欢的方法。第一种方法更经典,第二种方法设置更简单(但你可能会从你的同伴那里听到一些“这行不通”的话)。请记住,当接口行政上放下然后抬起,因此这些设置必须放在适当的网络配置设置中才能保持正确有效。
答案2
使用 AB 的出色解释,这就是我最终做的事情,以使其发挥作用,以造福其他任何人systemd
:
# /etc/systemd/network/50-eth1.network
[Match]
Name=eth1 # NIC with the peer on it to take priority over the normal NIC
[Network]
# For IPv6 it only appears to work when setting the same address on both interfaces
Address=10::5/64 # Same address as on the main NIC
DefaultRouteOnDevice=false
[Route]
Scope=link
PreferredSource=10.0.0.5 # Host IP address from the main NIC
Destination=10.0.0.4/32 # Peer's IP address on the other end of the PtP link
[Route]
Scope=link
PreferredSource=10::5 # Host IPv6 address from the main NIC
Destination=10::4/128 # Peer's IPv6 address
当然,对于另一台主机来说,源 IP 地址和目标 IP 地址(但不是网络掩码)是翻转的。