用 wireguard 在两个网络之间打洞

0 缘起

基于管理和安全的考虑,我们制定了一个大内网计划(T13),希望将公司所有的网路(办公室,各个公有云的 VPC 等)的内网打通。具体可选方案很多,我们这里采用的是 wireguard

1 wireguard 安装

1.1 Ubuntu

1
2
3
4
5
6
7
# begin with 19.10(Eoan), the two following statement are not needed
# 19.10(Eoan) 之后,以下这两句不用再执行。
apt install software-properties-common;
add-apt-repository ppa:wireguard/wireguard;

apt-get update;
apt-get install wireguard;

1.2 CentOS

以下是以 CentOS 7.* 为例,RHEL 7.* 亦然,如果是 6 或 8 系列的话,将 7 改成 6 或 8

1
2
3
curl -Lo /etc/yum.repos.d/wireguard.repo \ 
https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo;
yum install wireguard-dkms wireguard-tools;

2 wireguard 配置

这里有一些假设:

网络 私网网段 网关私网 IP 网关公网 IP
A 10.0.1.0/24 10.0.1.1 1.1.1.1
B 10.0.2.0/24 10.0.2.1 2.2.2.2

2.1 生成密钥对

在两个网络分别用来打洞的主机(也就是网关) 10.0.1.1 和 10.0.2.1 上分别执行:

1
2
3
4
5
umask 077;
cd /root;
wg genkey > privatekey;
wg pubkey < privatekey > publickey;
umask 022;

2.2 生成配置文件

这也需要分别在两个网关上分别执行,以 10.0.1.1 上执行为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
cat >> /etc/wireguard/wg_A.conf <<EOF
[Interface]
ListenPort = 36725
PrivateKey = $(cat /root/privatekey)
PostUp = sysctl -w net.ipv4.ip_forward=1

[Peer]
PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
AllowedIPs = 10.0.2.0/24
Endpoint = 2.2.2.2:36725
PersistentKeepalive = 25
EOF

稍稍解释一下:

  • 36725:这个是 wireguard 服务所用的端口号,理论上来讲自己定就好了,不过要记得在防火墙、安全组里打开
  • xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=:这个是对端机器的 publickey,在这里就应该是 10.0.2.1 上的 /root/publickey 的文件内容
  • wg_A:这个其实也是随便取的。如果配置文件是 (/etc/wireguard/)wg_A.conf,那么做 wg-quick down/up 动作的时候,参数就应该是 wg_A
  • Peer 段可以有多个,代表这是一个一对多的“洞”(隧道)

10.0.2.1 上也要做类似的设置

2.3 启动 wireguard

同样以 10.0.1.1 为例:

1
wg-quick up wg_A;

在 10.0.2.1 上则是:

1
wg-quick up wg_B;

这时,在 10.0.1.1 上应该能 ping 通 10.0.2.1,在 10.0.2.1 上也能 ping 通 10.0.1.1 了(如果不行,请检查 10.0.1.1 和 10.0.2.1 的防火墙安全组设置)。

2.4 其他后续工作

  • 安全组、防火墙上打开 udp 端口 36725 的入权限
  • 在网络 A 和 B 上分别将 10.0.2.0/24 和 10.0.1.0/24 的路由指向 10.0.1.1 和 10.0.2.1

做完这个后,10.0.1.0/24 段和 10.0.2.0/24 段之间应该完全互通了。

3 wireguard 维护

这里依然以 10.0.1.1 的机器为例来谈 wireguard 服务的维护:

1
2
3
4
# 启动服务(端口)
wg-quick up wg_A;
# 停止服务(端口)
wg-quick down wg_A;

4 Troubleshooting

当出问题的时候,可以用命令:

1
dkms status;

来查看一下 wireguard 模块儿是否处于 installed 状态,如果没有,那么需要手工安装 wireguard 模块。手工安装时再看出了什么问题,见招拆招。多半原因是 kernel 源代码没安装,或者什么包不存在导致的。

5 多说几句

前面提到,一台机器(如前面的 10.0.1.1 和 10.0.2.1)要打多个洞到不同的地方,其方法有两种:

  1. 在一个配置文件(如上面的 /etc/wireguard/wg_A.conf)里写多个 Peer
  2. 在目录 /etc/wireguard 下用多个配置文件,比如 wg_A2B.conf、wg_A2C.conf 等

这两种方法各有什么优缺点呢?

以方案一为例:

  • 优点是配置清爽、直观,而且只需要一个 udp 端口;
  • 缺点是从系统层面看只会有一个 wireguard 的链路,这样以后如果做 ospf 之类的动态路由,就不太好弄了;

方案二就自己想吧:)