我有以下服务器
- Linux 主机服务器 A,10.0.0.2
- qemu-kvm 客户机 vmA1,192.168.0.2
- qemu-kvm 客户机 vmA2,192.168.0.3
- Linux 主机服务器 B,10.0.1.2
- qemu-kvm 客户机 vmB1,192.168.1.2
- qemu-kvm 客户机 vmB2,192.168.1.3
主机网络是 10.0.0.0/16,没有 192.168.0.0/16 的路由,并且我无法访问网络路由器,因此无法在路由器中添加路由。
主机和客户机使用桥接网络,因此 vm1 可以与 vm2 通信。并且主机之间也可以相互通信。
现在我想让不同主机上的虚拟机可以通信,例如 192.168.1.2 可以 ping 192.168.0.2
因此我在服务器 B 中添加以下 iptables:
iptables -t nat -A OUTPUT -j DNAT -d 192.168.0.2 --to-destination 10.0.0.2
那么192.168.1.2确实可以ping通192.168.0.2
我以为我已经成功了,但事实并非如此。
数据包只发往 10.0.0.2,而不是 192.168.0.2。
如果我ssh 192.168.0.2
,我发现我实际上是 ssh 10.0.0.2。
所以我认为这是因为目标 IP 被 iptables 更改了,所以数据包永远不会到达 192.168.0.2
由于我无法在路由器中添加路由,我该如何实现呢?
我在想有没有办法让一个从 192.168.1.2 到 192.168.0.2 的数据包,先wrapped
通过某种协议或软件,以目的 IP 10.0.0.2 为目标,发送到网络,而当这个数据包到达 10.0.0.2 时,unwrap
又通过这种协议或软件,将目的 IP 10.0.0.2 还原为原始 IP 192.168.0.2,这样这个数据包就会发往 192.168.0.2。
这只是我的想法,也许还有其他方法可以实现这一点。
答案1
请注意,会有如果;你仍然没有提供太多有关你的网络的信息,所以我必须涵盖不同的情况。在最佳情况下,一个提供完整的网络图,其中包含所有重要细节(地址、NAT 的设置方式等)。根据细节,可行的解决方案可能是显著地更简单,只需在主机上添加两条路由即可。
通用的安全解决方案是:
在每个主机上安装额外的虚拟机,这些虚拟机将可以访问彼此的单个 UDP 端口。如果它们之间有任何 NAT,则需要转发该端口。(实际上只有一个需要端口可以从另一个访问,但您的总体结构似乎是对称的,我建议也使其对称。)
这些虚拟机中的每一个还需要在其相应的网桥中有一个接口和 IP 地址。为了便于描述,我将其设为“192.168.x.254”。在主机上需要访问另一台主机的虚拟机的其他虚拟机上,您应该通过本地 VPN VM 安装路由:来自的虚拟机
192.168.1.0/24
应该有ip route add 192.168.0.0/24 via 192.168.1.254
。
请注意,这些可能是相同的接口:VM 可以使用单个地址访问其他 VM 192.168.x.254
。
- 在两个 VPN VM 上安装 WireGuard 并设置隧道
192.168.<a>.254
:
ip link add dev wg0 type wireguard
ip address add dev wg0 192.168.2.<a> peer 192.168.2.<b>
wg set wg0 listen-port 51820 private-key /path/to/private-key peer <key-b> allowed-ips 192.168.<b>.0/24 endpoint <ip-b>:51820
其中<a>
和<b>
对于一个VM分别为0和1,对于另一个VM则为反之。
<ip-0>
和<ip-1>
是它们应该用来访问彼此的 UDP 端口的地址,本例中两者都是 51820。如果有 NAT,这些将是 NAT 盒的地址(例如,如果 NAT 由主机执行,这些是主机的地址)。
- 在这些虚拟机上设置路由:
ip route add 192.168.<b>.0/24 via 192.168.2.<b>
在虚拟机上<a>
。
如果NAT由主机执行,您可以直接在主机上设置隧道,并且配置会更简单,因为您不需要额外的虚拟机,也不需要现有虚拟机上的额外路由。
如果主机位于同一 L2,则只需在主机上添加两条路由:(ip route add 192.168.1.0/24 via 10.0.1.2
在另一台主机上添加反向路由),并设置 NAT,这样它们就不会转换这些数据包。这是最简单、最有效的解决方案。