WireGuard wg-quick PostUp的高级玩法

真的很高级。

wg-quick是WireGuard用来启动网络设备的**脚本**。

注意了,迄今为止,wg-quick是用bash写的一个脚本,不知道未来会不会变,至少目前shebang是

回到正题。
我在服务器端配的WireGuard配置文件是 /etc/wireguard/wg0.conf,内容大致如下:

大致解释一下:
[Interface] 这里定义的是虚拟网络设备的配置。
Address 是网络设备的地址,IP地址。
MTU 默认MTU是1420。改MTU的原因最后边会解释的。
ListenPort 监听的UDP端口。
PrivateKey 私钥,用 wg genkey > private.key 生成的文件内容。

[Peer] 对端的地址,如果这里是C,对面就是S,如果这里是S,对面就是C。至于谁是C谁是S,鉴于是UDP,那姑且认为先发请求的是C。
PublicKey 对端PrivateKey对应的私钥,用 wg pubkey < private.key 生成。
AllowedIPs 这里解释一下,不管上边谁是C谁是S,想像一下传统的VPN需求,如果你要把流量全量转发到设备里,那直接配 0.0.0.0/0,而此时对端的设备就是S了,那对端的配置,把你的Interface.Address 和你本地的网段填入,不过后边这个理论上不是必须。
Endpoint 上边的例子里没有,但是,作为C要连到S,那就需要告诉C连到哪个IP:PORT,至于S会自动生成对应C的Endpoint。

蛋疼的需求来了。
我希望我服务器的端口是不固定的。或者换句话说,我希望我服务器上WireGuard监听的端口是不固定的。
那我就在我VPS上的wg0.conf里,注释掉 ListenPort,同时 Peer里加上 Endpoint = 我家路由IP:端口
完了。服务器端用 wg-quick down wg0; wg-quick up wg0 重启wireguard后,家里的网络连不上VPS了,因为作为现实的C,我的VPS没有主动连接我家路由,以更新我家路由上这个设备记录的上次连接对端的IP/端口。

好在,wg-quick支持在配置文件里使用 PreUp, PreDown, PostUp, PostDown。
那我需要做的,就是用 PostUp 在VPS上的WireGuard重启后,主动请求一下我家路由这端的网络,但是不用care请求是否有效。
于是我试了 ping -c,但是,如果有任意一个Peer连不上,wg-quick就会退出,并关闭wg0。
我试过 ping -c 1 ip1; ping -c 1 ip2; ping -c 1 127.0.0.1,不行,超时。我也试过 ping -c 1 -w 1,依旧退出。

然后我就发现了这个问答 进而知道了这篇文章
于是现在的配置文件变成了

再回到 MTU 的问题。
问题出现在,我在EdgeRoute Lite上配好wireguard之后,发现,cn.engadget.com 加载的资源打不开了,直接请求超时;community.ubnt.com 打不开了,请求超时。
在我路由和VPS上同时抓包:
路由上: [TCP Window Update], [TCP Previous segment not captured], [TCP Dup ACK 3#1], [TCP Dup ACK 3#2] …
VPS上: Destination unreachable (Fragmentation needed), [TCP Retransmission], [TCP Dup ACK 3#1], [TCP Retransmission]… [TCP Dup ACK 3#2], [TCP Retransmission]…

这个问题我之前遇到过,当时应该用的还是pptp,从路由连到我的VPS。community.ubnt.com下的某些资源域名怎么都打不开,电脑上连接超时,但是VPS上正常,ping也能通。

搜了搜,有这篇文章:Why Can’t I Browse the Internet when Using a GRE Tunnel?
文章里给了几个解决方案:调低客户端设备MTU以减小MSS;加代理;加大隧道两端设备的MTU,把协议保的‘overhead’加上去。
当然,作为思科,还提供了一个解决方案是在他家路由上‘clear-df’,这个选项在EdgeRouter没看到。

所以WireGuard可能的‘overhead’有多大呢?继续搜:https://www.mail-archive.com/wireguard@lists.zx2c4.com/msg00029.html,这篇里WireGuard作者提到:

于是我就保守地在我VPS端的wg0上,直接使用 ‘ip link set wg0 mtu 1557’,结果都能访问了。
至于路由端,保守起见,我就没有改mtu了。

如果要走这个tunnel上ipv6,那安全的做法估计得是 1500 + 40 + 8 + 1 + 4 + 8 + 16 = 1577了?
但是,本身我VPS eth0的mtu是1500,所以1557,1577,也只是没有意义的数字而已。
于是我尝试把mtu直接改成1500,cn.engadget.com页面上所有o.aolcdn.com的资源加载都正常,一个都不超时,community.ubnt.com也正常载入。

然后调mtu,做个表格

到1499就不用测了。。。

WireGuard wg-quick PostUp的高级玩法 by @sskaje: https://sskaje.me/2017/06/wireguard-wg-quick-postup%e7%9a%84%e9%ab%98%e7%ba%a7%e7%8e%a9%e6%b3%95/