VPN 新宠 WireGuard 搭建

WireGuard 作为即将进入 Linux 内核的 VPN 新宠,以其简单优雅的设计和实现得到了 Linus Torvalds 的首肯

Can I just once again state my love for it and hope it gets merged soon? Maybe the code isn’t perfect, but I’ve skimmed it, and compared to the horrors that are OpenVPN and IPSec, it’s a work of art.

最近在推特看到 WireGuard for iOS 开放 TestFlight 测试的消息,于是迫不及待地下载测试一番,顺便在笔记本电脑上也搭建了 WireGuard 通道。

网络拓扑

本文所述搭建过程包括三个 WireGuard 节点(Peer),网络拓扑如下图所示:

为了便于理解,把家里的小米路由器也画出来了,同时将每个设备的网络接口及对应的 IP 地址也一并列出。

需要特别指出的是,在 WireGuard 协议中,各个节点的关系是完全对等的。每个节点都可以与多个节点连接从而组成非常复杂的网络拓扑。但在本文的应用中,仅 VPS 连接了两个节点,而其它两个节点相互之间不直接相连(图中虚线所示)。

安装

Ubuntu 安装

笔记本电脑和 VPS 运行的都是 Ubuntu 系统,参考 WireGuard 官网安装页面,二者的安装没有区别:

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

iOS 安装

iOS 要求升级到 12.0 或更新的系统,兼容 iPhone、iPad 和 iPod touch。安装 TestFlight 后点击 WireGuard for iOS 下载,目前对所有用户开放。

密钥生成

WireGuard 的每个节点都必须有一对 base64 编码的公钥和私钥。Ubuntu 在安装 WireGuard 后集成的 wg 命令可用于生成密钥:

$ umask 077
$ wg genkey | tee private | wg pubkey > public

上述命令生成私钥保存在文件 private 中,并从私钥派生出公钥保存在文件 public 中。

iOS 上在 WireGuard 主界面右上角点 + 号选择 Create from scratch,在弹出的 New configuration 界面中点击 Generate keypair 即可同时生成公钥和私钥。此界面同样用于节点配置。

记录下每个节点的私钥和公钥用于节点配置,例如:

  • VPS (10.10.10.1):
    • Private: EFkHNqKrLjjnVqeUfLd70extGCPHj7bsET1LNYjm51I=
    • Public: pJyCyGG5NAyqQte62JZ2d4tUDy1B06Y4kloQetAP/T0=
  • iPhone (10.10.10.2):
    • Private: qAsWByso80UOTNU0ZO37Gt7uIkwbStTCus/CjEZFcV4=
    • Public: 6ASrcQzy+hWVm1JEC/mz0AlyF2uASRE+SknTFqa4s1g=
  • Laptop (10.10.10.3):
    • Private: QJAWG0EVyt7DXfzK49KBniRm2XS698ptNr9wLfX4qG8=
    • Public: QEKrMGYh7VdGeuhdDR0VvSy2Gy+GESq1Y9SOXG2jShg=

节点配置

有了各个节点的密钥之后,即可根据网络拓扑图在各个节点上配置相互之间的连接关系。

VPS 配置

在 VPS 的 /etc/wireguard 目录下新建 wg0.conf 配置文件,内容如下:

[Interface]
PrivateKey = EFkHNqKrLjjnVqeUfLd70extGCPHj7bsET1LNYjm51I=
Address = 10.10.10.1
ListenPort = 54321
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE

[Peer]
PublicKey = 6ASrcQzy+hWVm1JEC/mz0AlyF2uASRE+SknTFqa4s1g=
AllowedIPs = 10.10.10.2/32

[Peer]
PublicKey = QEKrMGYh7VdGeuhdDR0VvSy2Gy+GESq1Y9SOXG2jShg=
AllowedIPs = 10.10.10.3/32

需要说明几点:

  • /etc/wireguard 目录下配置文件的名称将作为生成的虚拟网卡的名称,此处命名为 wg0
  • 每个节点的配置文件都必须有 [Interface] 部分,配置本节点的 IP 地址、私钥等属性。
  • 每个 [Peer] 对应一个对端节点,包括节点的公钥和允许的 IP 段,此处添加 iPhone 和笔记本电脑两个节点。AllowedIPs 属性对于出口流量来说是路由表,对于入口流量来说则是访问控制列表,参考 Cryptokey Routing
  • VPS 作为被动节点,需要配置 ListenPort,此处设置为 54321
  • PostUpPostDown 配置用于在节点创建和删除之后执行的操作,对于 WireGuard 协议本身非必需。此处用于实现流量转发的 iptables 添加和删除,对于代理服务器来说至关重要。

配置保存后,使用 wg-quick up wg0 根据配置文件快速创建 wg0 虚拟网卡并执行 PostUp 指定操作;使用 wg-quick down wg0 删除虚拟网卡并执行 PostDown 指定操作;使用 wg 查看各个节点的状态。

Laptop 配置

同样在笔记本电脑上新建 /etc/wireguard/wg0.conf 配置文件,内容如下:

[Interface]
PrivateKey = QJAWG0EVyt7DXfzK49KBniRm2XS698ptNr9wLfX4qG8=
Address = 10.10.10.3
DNS = 8.8.8.8

[Peer]
PublicKey = pJyCyGG5NAyqQte62JZ2d4tUDy1B06Y4kloQetAP/T0=
Endpoint = 149.28.171.194:54321
AllowedIPs = 0.0.0.0/0

与 VPS 的配置不同的是:

  • [Interface] 部分配置了 Google DNS,用于防止域名污染。
  • 仅有一个 [Peer] 即对应 VPS,且需要配置 Endpoint 为 VPS 公网 IP 和对应的 ListenPort54321
  • AllowedIPs 配置为 0.0.0.0/0 用于将所有流量都路由到 VPS,相当于全局代理。

wg-quickwg 命令的使用与 VPS 相同,不再赘述。

iPhone 配置

密钥生成的 New configuration 界面中,配置本端的 IP 地址等属性,再点击 Add peer 添加一个节点对应 VPS。完整配置如下图所示:

AllowedIPs 配置为 0.0.0.0/0 相当于全局代理,可添加具体的允许 IP 网段,例如把 AllowedIPs 设置为 Telegram 的全部网段:

149.154.160.0/20, 149.154.164.0/22, 149.154.168.0/22, 149.154.172.0/22, 91.108.4.0/22, 91.108.8.0/22, 91.108.12.0/22, 91.108.16.0/22, 91.108.56.0/22

则仅 Telegram 流量走代理。由此可见,目前 WireGuard for iOS 的分流功能非常有限,期待后续版本继续改进。

以上。

comments powered by Disqus