我在 VPS(Debian 10)上运行了一个 minecraft 服务器,但 VPS 太弱了,无法处理它,所以我想使用更强大的本地服务器来运行它(Ubuntu 22.04)。VPS 托管 OpenVPN 服务器,本地服务器作为唯一客户端进行连接。VPS 位于 10.8.0.1,本地服务器位于 10.8.0.6(本地网络上的 192.168.1.185)。
我使用 iptables 规则将 10.8.0.6:25565 处的 tun0 VPN 数据包转发到本地服务器的 IP。这工作正常:我可以从 VPS 查询 minecraft 服务器。然后我在 VPS 上设置了相同的规则集(当然交换了相关的 IP),以将连接从 vps_external_ip:25565 转发到 10.8.0.6:25565。此规则将数据包一直转发到本地服务器,但连接总是超时。奇怪的是,无论是从 VPS -> 本地服务器还是从外部 -> VPS -> 本地服务器的有效连接都不会增加任何 POSTROUTING MASQUERADE 规则的数据包计数器,但它们对 PREROUTING 规则有作用。当在 eth0:25565 上访问 VPS 时,TCP/UDP 连接只是超时,没有连接被拒绝的错误。
两台机器上都启用了 IPV4 转发,并且我尝试禁用 UFW,但没有成功。
我在两台服务器的 NAT POSTROUTE 上设置了日志规则,但由于找不到任何问题,因此我真的不确定如何修复该问题。
POSTROUTE 日志输出(iptables -t nat -I POSTROUTING -j LOG --log-prefix "NAT:" --log-level 7)
##### VPS
Apr 23 20:52:02 vpskernel: [1552376.122382] NAT1:IN= OUT=tun0 SRC=<my ip> DST=10.8.0.6 LEN=48 TOS=0x08 PREC=0x20 TTL=114 ID=21284 DF PROTO=TCP SPT=1806 DPT=25565 WINDOW=64240 RES=0x00 SYN URGP=0
#### Local server
<could not find any relevant logs grepping /var/log/kern.log for NAT1 and there were no logs at all for tun0>
我使用 /etc/ufw/before.rules 为每个服务器设置 iptables 规则。
VPS /etc/ufw/before.rules:
# START OPENVPN RULES
# NAT table rules
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
# END OPENVPN RULES
-A PREROUTING -i eth0 -d <vps external IP> -p tcp --dport 25565 -j DNAT --to-destination 10.8.0.6:25565
-A PREROUTING -i eth0 -d <vps external IP> -p udp --dport 25565 -j DNAT --to-destination 10.8.0.6:25565
-A POSTROUTING -s 10.0.0.0/8 ! -d 10.0.0.0/8 -j MASQUERADE
COMMIT
本地服务器 /etc/ufw/before.rules:
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -i tun0 -d 10.8.0.6 -p tcp --dport 25565 -j DNAT --to-destination 192.168.1.185:25565
-A PREROUTING -i tun0 -d 10.8.0.6 -p udp --dport 25565 -j DNAT --to-destination 192.168.1.185:25565
# setup routing
-A POSTROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -j MASQUERADE
COMMIT
PREROUTING 规则正在运行,但 POSTROUTING 规则计数器没有增加。
我在 25565 上运行了 tcpdump 进行调试。我看到数据包进来了,但在外部连接时,我没有看到任何接口返回。当直接从 VPS 查询时,我看到本地服务器在 tun0 上响应。问题似乎是本地服务器试图直接响应 en01 上的我的 IP,而不是 tun0 上的 VPS,但我不知道如何解决这个问题。
VPS tcpdump:
# eth 0
21:43:39.972647 IP my_ip.2729 > vps_ip.25565: Flags [S], seq 1483515507, win 64240, options [mss 1460,nop,nop,sackOK], length 0
# tun0
21:43:39.972739 IP my_ip.2729 > 10.8.0.6.25565: Flags [S], seq 1483515507, win 64240, options [mss 1460,nop,nop,sackOK], length 0
本地服务器 tcpdump:
#tun0
21:43:39.972566 IP my_ip.2729 > 10.8.0.6.25565: Flags [S], seq 1483515507, win 64240, options [mss 1356,nop,nop,sackOK], length 0
#en01
21:43:39.972618 IP 10.8.0.6.25565 > my_ip.2729: Flags [S.], seq 2141764446, ack 1483515508, win 64240, options [mss 1460,nop,nop,sackOK], length 0
答案1
终于搞明白了。网上大多数端口转发指南都有一个 POSTROUTING 规则,它不适用于 OpenVPN(或我的情况)。我不得不为任何非本地 IP 制定后路由规则,以便将其重写为 tun0 VPS IP,而不是允许本地 IP 作为源,而目的地不是本地 IP。
VPS /etc/ufw/before.rules (交换 s 和 d):
-A POSTROUTING -d 10.0.0.0/8 ! -s 10.0.0.0/8 -j MASQUERADE -t nat
此外,POSTROUTING 规则仅在 VPS 上需要。