在 Ubuntu 18.04 上建立 WireGuard 隧道组建 VPS 大内网

其实感觉非常矛盾,本身对于 WireGuard 隧道的建立不是一件非常复杂的事情,本来本文应该丢到自己的 Ignorance Notebook 上的,不过搜了一下中文的圈子基本上都是一键安装脚本之类的,遂还是打算放在自己的博客上了。

Current Problem

由于需要对自己的各个服务器进行监控,最近实践了一下 Grafana + InfluxDB + Telegraf 的栈,但是遇到了一个问题,即我的 Telegraf 需要安装在远程的主机上并向自己的 Master 节点返回数据,大致架构如下:

  • Master 节点:
    • Grafana
    • InfluxDB
    • Telegraf
  • Slave 节点:
    • Telegraf

这样就带来了一个访问控制的问题,由于 Slave 和 Master 多不在一个机房当中,所以没法享受内网数据传输,遂决定利用 VPN 的方式自建一个内网起来,保证数据的传输安全性,我知道我知道,如果要保护数据安全的话其实有很多的方式比如:

  • 利用反向代理保护 InfluxDB 并只允许某些自己的主机访问
  • 加入 SSL
  • 等等…

但是由于懒,加上希望有一个比较无缝的实现,且可以对上层其他的应用加以保护(比如 MySQL 的主从热备),所以便考虑了 VPN 的方式组网。同样,VPN 的选择也是多种多样,PPTP 由于感觉安全性不够最先被排除,OpenVPN 由于感觉配置过于复杂也被排除(而且据 Morgan Wu 讲这样的 VPN 有比较大的 Overhead),最后考虑了一个比较新兴且大家普遍比较喜欢的 WireGuard。

WireGuard Introduction

关于 WireGuard,有一下特点(来自 WireGuard 官网):

  • WireGuard securely encapsulates IP packets over UDP.(Wireguard 走的 UDP 协议,防火墙放行的时候别搞错了)
  • WireGuard aims to be as easy to configure and deploy as SSH.
  • A combination of extremely high-speed cryptographic primitives and the fact that WireGuard lives inside the Linux kernel means that secure networking can be very high-speed.
  • 加密方式是 ChaCha20-Poly 1305,Hash 算法是 BLAKE2s.

在一个官方的测试中,WireGuard 吞吐效率和其他同级别 VPN 对比图:

总的来说,由于集成在内核中且使用了对于移动设备友好的加密和 Hash 算法,吞吐效率较高。公私钥对的验证方式,部署方便,Overhead 较小。

Deploy WireGuard

虽然网上有许多的一键安装脚本,这里还是提及一下一个常规的安装方式,使用的服务器系统是 Ubuntu 18.04(Bionic)。

首先两边的服务器(假设称为 Server 和 Client 嘛)都需要安装 WireGuard:

$ sudo add-apt-repository ppa:wireguard/wireguard
$ sudo apt-get update
$ sudo apt-get install wireguard

Server 和 Client 上进入 /etc/wireguard/ 目录,然后生成自己机器的公私钥对:

$ wg genkey | tee privatekey | wg pubkey > publickey

这样在每台主机上都会有两个文件:privatekeypublickey

WireGuard 是通过创建一个虚拟接口的方式来转发流量的,这里我们暂时停一下来明确一下我们的网络规划。

Hostwg0 Address(Wireguard 内部使用)eth0 Address(服务商给的公网 IP)
Server192.168.1.1/241.1.1.1
Client192.168.1.2/242.2.2.2

Server 上开放 51820 端口(切记是 UDP)用于 Client 连接,在每台机器上 /etc/wireguard/ 目录下创建一个名为 wg0.conf 的文件,内容分别如下:

在 Server 上的 wg0.conf

[Interface]
Address = 192.168.1.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = < 这里填写 Server 上 privatekey 的内容 >

# Client
[Peer]
PublicKey = < 这里填写 Client 上 publickey 的内容 >
AllowedIPs = 192.168.1.1/24

在 Client 上的 wg0.conf

[Interface]
PrivateKey = < 这里填写 Client 上 privatekey 的内容 >
Address = 192.168.1.2/24

# Server
[Peer]
PublicKey = < 这里填写 Server 上 publickey 的内容 >
Endpoint = 1.1.1.1:51820
AllowedIPs = 192.168.1.1/24

然后在双方主机上各自 wg-quick up wg0 即可。

通过 wg 指令即可查看目前接口使用情况,比如从我的 Client 上:

interface: wg0
  public key: < Client 上的 publickey >
  private key: (hidden)
  listening port: 49992

peer: < Server 上的 publickey >
  endpoint: 1.1.1.1:51820
  allowed ips: 192.168.1.0/24
  latest handshake: 1 minute, 46 seconds ago
  transfer: 7.02 MiB received, 172.99 MiB sent

此时隧道已经建立,双方主机已经可以通过内网 IP (这里的例子中是 192.168.1.1192.168.1.2 进行加密地通讯了,无论是 MySQL 热备还是 Nginx 反向代理都可以爽快地使用内网地址跑起来啦~

References

1.WireGuard: fast, modern, secure VPN tunnel