我有几个服务器(B、C 等)位于同一个地方,还有一台机器(A),位于普通的老式家用路由器后面。我希望它们都能互相连接。我觉得 OpenVPN 是个不错的起点,所以我在互联网上在 A 和 B 之间建立了一个隧道(tun0)。情况如下:
10.8.0.4 10.8.0.1
---------- 10.8.0.0/24 ----------
| | | |
| A tun0 ----------- tun0 B | 10.128.140.204
| | | |
---------- -- eth1 --
|
| 10.128.0.0/16
|
-- eth1 --
| |
| C | 10.128.13.224
| |
----------
具体来说,我需要 A 能够通过地址 10.128.13.224 到达 C,而 C 能够通过地址 10.8.0.4 到达 A。这意味着 NAT 不行 - 大多数资源都谈到在 B 上设置 NAT,以便 A 能够看到 C - 而这似乎就是问题所在。
所以这就是我现在一直在尝试做的事情:
- 告诉 A 使用 10.8.0.1 作为 10.128.0.0/16 的网关
- 告诉 B 使用 10.128.140.204 作为 10.8.0.0/24 的网关
- 让 B 充当网关
A上的路由表:
Destination Gateway Genmask Flags Metric Ref Use Iface
default [home router] 0.0.0.0 UG 0 0 0 enp0s3
10.8.0.0 * 255.255.255.0 U 0 0 0 tun0
10.128.0.0 localhost 255.255.0.0 UG 0 0 0 tun0
[home ip] * 255.255.255.0 U 0 0 0 enp0s3
A# ip route get 10.128.13.224
10.128.13.224 via 10.8.0.1 dev tun0 src 10.8.0.4
cache
看起来不错。C 上的路由表:
Destination Gateway Genmask Flags Metric Ref Use Iface
default gateway 0.0.0.0 UG 0 0 0 eth0
10.8.0.0 10.128.140.204 255.255.255.0 UG 0 0 0 eth1
10.13.0.0 * 255.255.0.0 U 0 0 0 eth0
10.128.0.0 * 255.255.0.0 U 0 0 0 eth1
[public IP] * 255.255.255.0 U 0 0 0 eth0
C# ip route get 10.8.0.4
10.8.0.4 via 10.128.140.204 dev eth1 src 10.128.13.224
cache
很好。在 B 上启用 IP 转发:
B# cat /proc/sys/net/ipv4/ip_forward
1
我猜默认接受一切iptables 中的规则也可以工作,但是为了更好,我对 FORWARD 链做了一些限制:
B# iptables -S
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-A FORWARD -s 10.128.0.0/16 -d 10.8.0.0/24 -i eth1 -o tun0 -j ACCEPT
-A FORWARD -s 10.8.0.0/24 -d 10.128.0.0/16 -i tun0 -o eth1 -j ACCEPT
嗯,他们没有。A# ping 10.128.41.180
什么也没做也没有C# ping 10.8.0.4
。
如果我添加NAT如下:
B# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.8.0.0/24 -d 10.128.0.0/16 -o eth1 -j MASQUERADE
然后从 A 到 C 的 ping 操作就可以成功了。
A# ping 10.128.13.224
PING 10.128.13.224 (10.128.13.224) 56(84) bytes of data.
64 bytes from 10.128.13.224: icmp_seq=1 ttl=63 time=120 ms
...
这不是我想要做的,但我猜这意味着某物正在工作。另一个奇怪的事情是,如果我反过来配置 MASQUERADE,从 C 到 A 的 ping 不会不是工作,所以我想这里可能有一个线索。
现在我开始怀疑我想要做的事情是否可以完成,或者我是否对网络的工作原理有一些基本的误解。这可能吗?我是否忽略了一些基本的东西?我将不胜感激任何提示或资源。
答案1
事实证明,上述方法在常规设置下可以完美运行。但是,服务器(B
、、C
...)所在的网络不允许发送源地址与发送方 IP 地址不匹配的数据包:
C
当从ping 时A
,A
将以太网帧内的 IP 数据包发送tun0
到 B,大致如下所示:
----------------------------------------------------
| source: A's tun0 MAC | destination: B's tun0 MAC |
| -------------------------------------------------|
| | source: 10.8.0.4 | destination: 10.128.13.224 ||
| | payload: PING ||
| -------------------------------------------------|
----------------------------------------------------
B
然后检查其路由并发送以下内容eth1
:
----------------------------------------------------
| source: B's eth1 MAC | destination: C's eth1 MAC |
| -------------------------------------------------|
| | source: 10.8.0.4 | destination: 10.128.13.224 ||
| | payload: PING ||
| -------------------------------------------------|
----------------------------------------------------
网络检查此情况,发现源地址与 eth1 地址10.8.0.4
不匹配,因此不传输帧。这就是普通网关无法在此网络上工作的原因。B
10.128.140.204