使用wireguard打通不同的内网。

为什么会有这种需求?

我们在云上构建一个网络环境的时候,通常会进行如下操作:
创建一个VPC,VPC里面有很多交换机。会有不同类型的资源例如ecs、rds、redis、lb等等接在交换机上。然后会有NAT网关来配置出VPC的流量。因为通常不是每个服务器都有公网ip。

但是像阿里云、aws这种云厂商,VPC是region级别的。不同region之间内网默认无法互通。而我们有可能生产环境部署在上海,测试环境在杭州。而运维平台的控制面通常只会有一份例如在上海。那么操作测试环境的机器的时候,就需要能直接访问测试环境的内网地址。这时候需要将两者的内网打通。

当然,云上面会有相关的产品来帮助我们实现这个需求,以阿里云为例有VPN网关、VPC对等连接、高速通道。我们可以根据需求来进行选择。

但是有时候更加复杂的环境例如多云、物理机房和云混合等等。云厂商为了解决这个问题也都出了一些产品,但是有时候出于成本的考虑或者仅是做测试环境的用途,就需要自己实现。

当然,生产环境的内网互通还是建议使用云上的产品,可靠性保障好一些。

这里我们就是使用wireguard来实现这个需求。wireguard性能优异、配置简单。相关的介绍网上很多,这里就不赘述了,本篇文章着重来说明如何配置。

当然,wireguard最为人熟悉的功能就是做VPN,实际上也是一种打通不同内网的一种行为。

环境介绍

在阿里云上开了两个VPC,分别位于北京和上海,每个VPC分别创建一个交换机,每个交换机上分别开两台ECS,其中一台有公网ip,IP地址列表如下:

上海:

机器A:172.16.8.61
机器B:172.16.8.60(公网IP:47.100.199.233)

北京:

机器C:192.168.0.142
机器D:172.16.8.60(公网IP: 47.100.199.233)

其中上海和北京的内网地址不能重叠。所以提前进行网络规划是非常重要的。

我们最终想要达到的效果就是从上海的 172.16.8.61 能访问 北京的 192.168.0.142 ,反之也成立。其实访问另外两个地址也行,但是为了验证不是直接通过公网地址联通,这里特地选用两个没有公网地址的内网地址进行测试。后续会介绍这个区别。

原理分析

通过wireguard将机器B和机器D联通之后,两者之间建立了一个隧道。这个时候机器B和机器D的内网地址已经就可以互通了。那么要实现两个内网互通,就要上海所有的内网地址都能与北京所有的内网地址互通。这才是我们要的最终的结果。

要实现机器A能访问机器C,就要告诉A访问C的网段的时候要将网络包转发到机器B进入隧道,然后机器B通过公网地址将A的数据包发送到机器D上出隧道。机器D再将数据包发送到机器C上。回程包再按照相同的路径回来。

这个告诉的行为就是加一些路由规则。这也就是上述所说的区别所在了。有些人搭建完成之后,直接用B访问D发现内网是互通的就以为成功了,其实还差一步。这也是要用A访问C进行测试的原因。

动手实践

在机器B和机器D上安装wireguard,我这里的系统是Ubuntu

apt update
apt install wireguard resolvconf -y

开启IP转发:

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p

分别在机器B和机器D上生成wireguard的公钥和私钥,公私钥生成方式:

#私钥
wg genkey > server.key
#用私钥生成公钥
wg pubkey < server.key > server.pub
当前目录下会生成两个文件 server.key和server.pub

分别配置机器B和机器D

机器B:
编辑 /etc/wireguard/wg0.conf
注意wireguard默认配置文件目录是/etc/wireguard/,配置文件的命名规则是”网卡名称.conf”,这里是wg0

[Interface]
#机器B的server.key
PrivateKey = sIh/2wLQSSQ29VoBBE/vi4aCCP0VoJcToqzGgMMEuVw=

#机器B的隧道地址
Address = 10.0.8.1

#wireguard启动后添加一些iptables规则。
PostUp   = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

#wireguard关闭后删除上述的iptables规则。
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

#监听的UDP端口。
ListenPort = 50820
MTU = 1420

[Peer]
#机器D的server.pub
PublicKey =  59uFxm7XV926zDKb2ciIAFcG9oSGW6WjOPHsV1eofRU=

#这里表示允许对端的ip地址访问,这里写了机器D的隧道地址和北京交换机的内网地址段。
AllowedIPs = 10.0.8.100/32,192.168.0.0/16 

#机器D的地址和wireguard端口
Endpoint = 123.56.86.241:50820

机器D:

[Interface]
#机器D的server.key
 PrivateKey = 8NS4ccU3paaj8uumt0kq4+x+cd5+p0WRrPMJimiOCE0=

#机器D的隧道地址
 Address = 10.0.8.100

 PostUp   = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
 PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
 ListenPort = 50820
 MTU = 1420

 [Peer]
#机器B的server.pub
 PublicKey =  R2L31pXX2tUz9KYrUROldqEzfdMphElxIQOjUUAd9kk=

#这里写了机器B的隧道地址和上海交换机的内网地址段。
 AllowedIPs =  10.0.8.0/24,172.16.0.0/16

#机器B的地址和wireguard端口
 Endpoint = 47.100.199.233:50820

确保北京和上海的安全组放开了UDP 50820 端口后,分别在机器B和机器D上启动wireguard。

wg-quick up wg0

这个时候机器B和机器D已经建立隧道连接。使用wg命令查看

机器B
# wg
 interface: wg0
   public key: R2L31pXX2tUz9KYrUROldqEzfdMphElxIQOjUUAd9kk=
   private key: (hidden)
   listening port: 50820
 peer: 59uFxm7XV926zDKb2ciIAFcG9oSGW6WjOPHsV1eofRU=
   endpoint: 123.56.86.241:50820
   allowed ips: 10.0.8.100/32, 192.168.0.0/16
   latest handshake: 6 seconds ago
   transfer: 19.82 KiB received, 85.73 KiB sent
机器D 
# wg
interface: wg0
   public key: 59uFxm7XV926zDKb2ciIAFcG9oSGW6WjOPHsV1eofRU=
   private key: (hidden)
   listening port: 50820
 peer: R2L31pXX2tUz9KYrUROldqEzfdMphElxIQOjUUAd9kk=
   endpoint: 47.100.199.233:50820
   allowed ips: 10.0.8.0/24, 172.16.0.0/16
   latest handshake: 2 minutes, 16 seconds ago
   transfer: 85.73 KiB received, 19.85 KiB sent

然后分别在上海和北京的路由表中加上路由规则。

上海

北京

配置完之后,从A访问C,直接从A ssh 到C,成功登录

从C ssh 到A,成功登录

至此我们成功打通了上海和北京之间的内网。

留下评论