通过 OpenVPN 实现非 NAT 网关

通过 OpenVPN 实现非 NAT 网关

我有几个服务器(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 时AA将以太网帧内的 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不匹配,因此不传输帧。这就是普通网关无法在此网络上工作的原因。B10.128.140.204

相关内容