记 WireGuard 部署及注意事项

接上一篇 斐讯 N1 -> Armbian 后, 我往上面丢了一些服务(Gitea, vlmcsd, Transmission 等). 玩了一阵后我就因为别的事情搁置了最开始的目的 - 跳板, 直到四月份回坑 Apex Legends 后才因为联通的外网想起这台小机器.

接下来就开始填坑吧emoji

选型

  • PPTP/L2TP/IPSEC/SSTP

这些就很烦,不怎么想搞

  • OpenVPN/Softether

其实我是想直接用 Softether 的, 毕竟服务端启动后就能用有 UI 的管理工具, 点点点就搞好了.

问题是我到现在都没找到 ARM64 的预编译文件(官方不支持此架构)…

  • WireGuard

新玩具 - 轻量/性能不差/IP 漫游/配置相对简单/未来会支持混淆

好了就你了, 开搞开搞

部署

下文中部分参数意义请查看下表

参数意义
server_private_key_value服务器私钥
server_public_key_value服务器公钥
client_private_key_value客户端私钥
client_public_key_value客户端公钥

安装

WireGuard 官网 安装对应系统的版本, 你也可以下源码自己编译, 有现成的我一般都不会自己编译(哈哈).

Armbian (Debian or Ubuntu) 为例:

1
2
3
4
5
6
7
echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list

printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable

apt update

apt install wireguard

看看装好了没有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# lsmod | grep wireguard
[email protected]:~# lsmod | grep wireguard

wireguard 155648 0
ip6_udp_tunnel 16384 1 wireguard
udp_tunnel 16384 1 wireguard
ipv6 487424 42 nf_nat_ipv6,wireguard

# dpkg -l | grep wireguard
[email protected]:~# dpkg -l | grep wireguard

ii wireguard 0.0.20190406-1 all fast, modern, secure kernel VPN tunnel (metapackage)
ii wireguard-dkms 0.0.20190406-1 all fast, modern, secure kernel VPN tunnel (DKMS version)
ii wireguard-tools 0.0.20190406-1 arm64 fast, modern, secure kernel VPN tunnel (userland utilities)

这就装完了, 就下来就是配置了.

配置

  • 生成公私钥
1
wg genkey | tee privatekey | wg pubkey > publickey

服务器私钥存好, 丢了就要把所有客户端的配置收回来了.

服务器端

  • 开启端口转发
1
2
3
4
5
6
# 打开转发
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

# 应用规则
sysctl -p
  • 看下要连外网的网卡是哪个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# ip addr

[email protected]:~# ip addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether ##:##:##:##:##:## brd ff:ff:ff:ff:ff:ff
inet #.#.#.#/24 brd #.#.#.# scope global dynamic eth0
valid_lft 71134sec preferred_lft 71134sec
inet6 ffff::f/64 scope global noprefixroute dynamic
valid_lft 586sec preferred_lft 586sec
inet6 ffff::f/64 scope link
valid_lft forever preferred_lft forever
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
link/ether ##:##:##:##:##:## brd ff:ff:ff:ff:ff:ff

这里可以看见我的外网网卡名称是 eth0 , 这个记下来.

  • 建配置
1
2
3
# 目录不存在时就给它建个
# mkdir /etc/wireguard
vim /etc/wireguard/wg0.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[Interface]
# 服务器私钥, 就是上面生成的 privatekey
PrivateKey = server_private_key_value

# 绑定地址
Address = 10.0.0.1/24

# 是否保存配置, 可以在运行中通过命令行添加新客户端, 并保存到此配置
SaveConfig = true

# 启动动作, 这里就要把 eth0 替换成之前记下的外网网卡名称 , wg0 是等下创建的虚拟网卡名称
# 配置防火墙规则
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# 关闭动作, 操作同上
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# 监听端口
ListenPort = 56660

# 客户端配置
[Peer]
# 客户端公钥, 生成步骤同服务器, 两端都可生成
PublicKey = client_public_key_value

# 分配给客户端的地址, 我这里让他随便选, 你也可以指定给他
AllowedIPs = 10.0.0.0/24
#AllowedIPs = 10.0.0.2/32

# 加客户端就在 Peer 节点下加公钥和 IP 就可以了, 操作同上
  • 提权, 免得出问题
1
chmod 777 -R /etc/wireguard
  • 测试启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# wg-quick up wg0

[email protected]:~# wg-quick up wg0

[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip address add 10.0.0.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# wg

[email protected]:~# wg

interface: wg0
public key: server_public_key_value
private key: (hidden)
listening port: 56660

peer: client_public_key_value
endpoint: [ffff::f]:port
allowed ips: 10.0.0.0/24

接下来就是配置客户端了

客户端

这里以 Windows 平台, 客户端 TunSafe 为例, 其他平台就不多讲了, 区别不大

  • 安装

TunSafe 下载客户端和虚拟网卡驱动(TunSafe-TAP), 安装完成即可.

TunSafe 界面

  • 配置

点击 File - Generate Key Pair 来生成公私钥

TunSafe 选项 - 生成公私钥

TunSafe 选项 - 生成公私钥 - 生成

记下生成的公私钥, 点击 Edit Config ,开始配置.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Interface]
# 上文生成的客户端私钥
PrivateKey = client_private_key_value

# 使用的 DNS 服务器
DNS = 114.114.114.114

# 绑定地址
Address = 10.0.0.3/24

[Peer]
# 上文生成的服务器公钥
PublicKey = server_public_key_value

# 要代理的地址, 这里是全局代理, 可根据需求调整
AllowedIPs = 0.0.0.0/0

# 服务器地址
Endpoint = server_ip:port

# 心跳包间隔时间
PersistentKeepalive = 25

完事, 开始测试

  • 测试启动

点击 Connect 测试

TunSafe 连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[user.DESKTOP-DEV] ➤ ping 10.0.0.1

正在 Ping 10.0.0.1 具有 32 字节的数据:
来自 10.0.0.1 的回复: 字节=32 时间=56ms TTL=64
来自 10.0.0.1 的回复: 字节=32 时间=78ms TTL=64
来自 10.0.0.1 的回复: 字节=32 时间=76ms TTL=64
来自 10.0.0.1 的回复: 字节=32 时间=52ms TTL=64

[user.DESKTOP-DEV] ➤ ping 114.114.114.114

正在 Ping 114.114.114.114 具有 32 字节的数据:
来自 114.114.114.114 的回复: 字节=32 时间=63ms TTL=80
来自 114.114.114.114 的回复: 字节=32 时间=78ms TTL=66
来自 114.114.114.114 的回复: 字节=32 时间=75ms TTL=67
来自 114.114.114.114 的回复: 字节=32 时间=59ms TTL=87

到这里就部署完毕了.

  • 坑啊

你以为到这就结束了? 接下来才是重点, 耗时一个月才解决的血泪史

连接成功后,我 ping 了服务器和外网, 都能正常连接, 我兴冲冲跑去 Speedtest 测试速度, 却发现所有网站都连接超时, 连路由的管理页面都上不去

于是开始检查, 防火墙和转发都配置了, ssh 没问题, traceroute 没问题, 还是不能上

这什么情况emoji

妈耶, 搞不定啊, 放狗!

于是就断断续续搜索了一个月(你没看错, 是一个月, 这篇文章本来是要在四月发的emoji), 还是没找到头绪.

反反复复配置, 问题依然存在

我差点都认命去装 OpenVPN 了, 这时脑子一抽, 想起以前瞎折腾给网卡开了巨型帧, 导致无法连接网络的情况, 会不会是 MTU 设置不正确导致出现碎片?

  • 调查

赶紧连到小机器, 查看网卡情况

1
2
3
4
5
6
7
8
9
10
11
12
# ip link

[email protected]:~# ip link

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether ff:ff:ff:ff:ff:ff brd ff:ff:ff:ff:ff:ff
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DORMANT group default qlen 1000
link/ether ff:ff:ff:ff:ff:ff brd ff:ff:ff:ff:ff:ff
33: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/none

这里可看到 wg0mtu 是 1420, 编辑客户端配置

1
2
3
4
5
6
7
8
9
10
11
12
13
[Interface]
PrivateKey = client_private_key_value

DNS = 114.114.114.114

Address = 10.0.0.3/24
...

MTU = 1420

...
[Peer]
...

保存后重新连接, 问题依旧, 这到底是怎么肥事啊emoji

不死心, 放狗搜索后找到了这个邮件列表: [WireGuard] Header / MTU sizes for Wireguard , 里面提到了 WireGuard 协议的开销:

The overhead of WireGuard breaks down as follows:

  • 20-byte IPv4 header or 40 byte IPv6 header
  • 8-byte UDP header
  • 4-byte type
  • 4-byte key index
  • 8-byte nonce
  • N-byte encrypted data
  • 16-byte authentication tag

妈耶, 我看见曙光了!

  • 填坑

赶紧去改配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Interface]
PrivateKey = client_private_key_value

DNS = 114.114.114.114

Address = 10.0.0.3/24
...
# 这里按照最大开销计算, 实际的 mtu 为 1420 - (40 + 8 + 4 + 4 + 8 + 16) = 1344
# 我怕有坑, 再给点余量
MTU = 1300

...
[Peer]
...

保存 -> 重新连接 -> Speedtest

速度

好了, 坑填上了, Apex Legneds 启动!

以下是一些参考链接, 供有意者研究(多看文档少踩坑):