前言
最近遇到一个典型的网络访问场景:需要通过 WireGuard VPN 访问位于远程服务器局域网内的机器,而自己不在该局域网中。虽然 VPN 能成功建立,但在访问局域网内的目标机器时,总会遇到路由和 NAT 问题,导致 ping 或服务访问不通。
为了理清网络流向和解决问题,我记录了整个排查和配置过程,供大家参考。本文以 Debian 系统 + WireGuard VPN + 局域网访问 为例,结合具体 IP 拓扑,展示问题分析与解决方案。
问题描述
- 网络拓扑:
本机 A:WireGuard 客户端,wg0 IP 为 172.32.100.2
服务器 B:WireGuard VPN Server,wg0 IP 为 172.32.100.1
服务器 C:WireGuard 客户端,wg0 IP 为 172.32.100.3,物理网卡 eth0 为 172.16.100.2
目标机器:局域网内 IP 172.16.100.3,直接连接在服务器 C 所在的物理网段 - 需求:
本机 A 可以成功连接 WireGuard VPN,并且要能够访问 172.16.100.3 。
目标机器与服务器 C 在同一局域网,但本机 A 并不在这个局域网中。 - 网络拓扑图

实战步骤
本机wg配置
首先需要在本机的wg配置中的allowips中添加一个路由172.16.100.3/32
这代表当本机访问172.16.100.3的时候会通过wg网卡发送至B
服务器B配置
作为组网的服务端,也需要在对应的peer中增加allowips 172.16.100.3
[Peer]
PublicKey = eWlvr
AllowedIPs = 172.32.100.3/32,172.16.100.3/32这代表B收到172.16.100.3的请求知道发往172.32.100.3
服务器 C配置
此时服务器C中使用 tcpdump -i any -n icmp抓包,然后本机A ping一下172.16.100.3 应该是可以抓到流量包了,但是还无法转发
服务器C首先一定要开启ip转发
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sysctl -p然后,如果我们操作抓包,则应该会注意到:
16:33:00.570423 IP 172.32.100.2 > 172.19.100.3: ICMP echo request, id 1, seq 62, length 40看上去没什么问题,但是源ip是172.32.100.2,如果不做snat,极有可能是无法发到172.19.100.3的,所以我们还要做snat,执行命令
iptables -t nat -A POSTROUTING -s 172.32.100.0/24 -o eth0 -j MASQUERADE这样当从eth0出口的流量就会转为eth0网卡的ip,这样就可以成功发送给同在局域网的172.19.100.3了
此时Aping172.19.100.3即可通过
菜鸟标注
因为我不太懂snat以及网卡出入这个抽象概念,,第一次看到snat,就好奇如果设置了这个东西,那我本机ping 172.32.100.2的时候,虽然走了wg网卡(出口网卡),但是最终不是还会通过eth0发到公网,是否会被snat,但是答案显然易见是不会,我没找到让我能非常理解的概念,不过大体可以理解为只有一个出口网卡,你设置了路由,把172.32.100.0/24的流量路由到wg网卡,那wg就是出口网卡,然后无论最终他又通过什么方式由eth0发出去,那出口就是wg网卡不是eth0,所以snat命令也只对出口网卡是eth0的生效,如果有更好的解释方式请务必留言
评论 (0)