背景介绍:
老家有几台老旧的电脑装了一些web服务,但是我在出租屋中如何访问到这些web服务呢?这个涉及到2个局域网通信问题,本文使用wireguard单向打通2个局域网,实现出租屋中任意主机均可以访问老家web服务。
0x00 使用wireguard虚拟组网
WireGuard 是一个易于配置、快速且安全的开源 VPN,它利用了最新的加密技术。目的是提供一种更快、更简单、更精简的通用 VPN,它可以轻松地在树莓派这类低端设备到高端服务器上部署。Linux创造者Linus Torvalds非常喜欢WireGuard,以至于将其合并到 Linux Kernel 5.6 中。
阿里云上申请一个公网ip服务器(Server),家中局域网有一个虚拟机A,在老家192.168.0.0/24网段申请一台虚拟机做跳板机,使用wireguard组虚拟局域网。部署成功后可以实现虚拟机A、公网服务器、老家虚拟机B三台主机互相通信。其网络拓扑图如下所示:
0x01 wireguard访问同局域网其他机器
经过第一步后,其实并没有达到我们最终目的。此时在出租屋里使用虚拟机已经可以访问老家虚拟机B了,但是无法访问虚拟机B同网段的web服务器。参考 https://iliasa.eu/wireguard-how-to-access-a-peers-local-network/
根据数据流向,依次做如下几个配置更改:
- 虚拟机A作为请求发起方,修改Peer中
AllowedIPs
允许192.168.0.0/24流量包流入公网服务器。 - wireguard公网服务器收到192.168.0.0/24流量包后,应该转发给虚拟机B节点,将192.168.0.0/24加入Peer为虚拟机B的
AllowedIPs
。 - 虚拟机B的wg0网口接受到了来自公网服务器的192.168.0.0/24流量包后,应该将该流量经过源ip修正后由ens192网口发出。主要规则是
iptables -t nat -A POSTROUTING -o ens192 -j MASQUERADE
,该规则用于当流量包从ens192网口发出时将源ip地址从10.0.2.0/24
统一修正为192.168.0.82
。
至此网络拓扑图依然没有改变,相比于上一步新增制定了192.168.0.0/24流量包在整个wg虚拟网络中的处理规则。虚拟机A在wireguard的帮助下,可以直接访问老家web服务器了。
0x02 配置wireguard节点为网关服务器
经过第二步已经实现了出租屋虚拟机A访问老家web服务器。仔细思考下,发现一个用户体验的问题:我出租屋里还有手机/平板,别的电脑和虚拟机。每增加一个设备都要部署一套wireguard服务,那这个维护成本就太高了。理想情况是将虚拟机A配置为网关服务器,出租屋中其他机器流量都从虚拟机A转发一下实现访问老家的web服务。于是我在出租屋找到了另外一台电脑C,尝试将电脑C的网关设置为A服务器ip地址(192.168.93.128)。相比第一步,网络拓扑图增加了一台电脑C,如下图所示:
但是此时虚拟机C并不能成功ping通web服务器。下面通过抓包排查问题。
保持在虚拟机C中执行ping 192.168.0.81
,同时在虚拟机A中执行 tcpdump -nn -i any icmp
进行抓包:
spring@spring-virtual-machine:~$ sudo tcpdump -nn -i any icmp
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
20:38:40.192152 ens33 In IP 192.168.93.129 > 192.168.0.81: ICMP echo request, id 3, seq 11, length 64
20:38:40.192201 wg0 Out IP 192.168.93.129 > 192.168.0.81: ICMP echo request, id 3, seq 11, length 64
20:38:41.215779 ens33 In IP 192.168.93.129 > 192.168.0.81: ICMP echo request, id 3, seq 12, length 64
20:38:41.215816 wg0 Out IP 192.168.93.129 > 192.168.0.81: ICMP echo request, id 3, seq 12, length 64
20:38:42.240394 ens33 In IP 192.168.93.129 > 192.168.0.81: ICMP echo request, id 3, seq 13, length 64
20:38:42.240432 wg0 Out IP 192.168.93.129 > 192.168.0.81: ICMP echo request, id 3, seq 13, length 64
20:38:43.263821 ens33 In IP 192.168.93.129 > 192.168.0.81: ICMP echo request, id 3, seq 14, length 64
20:38:43.263860 wg0 Out IP 192.168.93.129 > 192.168.0.81: ICMP echo request, id 3, seq 14, length 64
在公网网关服务器也执行tcpdump -nn -i any icmp
相同的命令抓包,发现没有任何显示。
根据以上信息可以推断出icmp包从虚拟机A的wg0网卡出去,但是公网服务器没收到。
那么到底是包没发出去还是服务器没收到呢?看虚拟机A的wg0.conf:
[Interface]
PrivateKey = xxxxxxxxxxx
Address = 10.0.2.3/32
[Peer]
PublicKey = xxxxxxxxxxx
AllowedIPs = 10.0.2.0/24,192.168.0.0/24
Endpoint = xx.xx.xx.xx:xx
PersistentKeepalive = 25
根据wg0.conf显示,wireguard不认识192.168.93.129这个ip,所以不会把这个包真的发出去。
那么如何在流量包由wg0网卡发出去前将源地址换掉呢?SNAT(Source Network Address Translation源网络地址转换)功能闪亮登场,其作用是将ip数据包的源地址转换成另外一个地址。关于NAT/SNAT/DNAT的关系及日常运用场景网上有非常多的文章讲,这里就不深入讲原理了。
通过下述2条命令实现当流量包目标地址为10.0.2.0/24或者192.168.0.0/24时将源ip地址修正为10.0.2.3:
iptables -t nat -I POSTROUTING -s 192.168.93.0/24 -d 10.0.2.0/24 -j SNAT --to-source 10.0.2.3
iptables -t nat -I POSTROUTING -s 192.168.93.0/24 -d 192.168.0.0/24 -j SNAT --to-source 10.0.2.3
每次wg服务启动时都敲这么一串也不是个办法,可以加入到wg0.conf文件的PostUp和PostDown配置中。
看下目前最新的虚拟机A的wg0.conf配置文件:
[Interface]
PrivateKey = xxxxxxx
Address = 10.0.2.3/32
DNS = 223.5.5.5,114.114.114.114
PostUp = iptables -t nat -I POSTROUTING -s 192.168.93.0/24 -d 10.0.2.0/24 -j SNAT --to-source 10.0.2.3; iptables -t nat -I POSTROUTING -s 192.168.93.0/24 -d 192.168.0.0/24 -j SNAT --to-source 10.0.2.3
PostDown = iptables -t nat -D POSTROUTING -s 192.168.93.0/24 -d 10.0.2.0/24 -j SNAT --to-source 10.0.2.3; iptables -t nat -D POSTROUTING -s 192.168.93.0/24 -d 192.168.0.0/24 -j SNAT --to-source 10.0.2.3
[Peer]
PublicKey = xxxxx
AllowedIPs = 10.0.2.0/24,192.168.0.0/24
Endpoint = xx.xx.xx.xx:xx
PersistentKeepalive = 25
至此,出租屋里面的主机只要将网关设置为虚拟机A的ip地址(192.168.93.128)均可以访问老家的web服务器。
网友评论