解决WireGuard在OpenWrt路由器上重启后无法连接问题的过程

发布日期:分类:Linux & homelab 解决WireGuard在OpenWrt路由器上重启后无法连接问题的过程无评论
时效性提醒:本文首次编写发布于5 年前。

先说结论,无法重连是因为重启后路由器上的系统时间不正确所导致的

以下废话

最近在OpenWrt便携路由器上部署WireGuard客户端,以在外出公共WiFi处实现更加可控的网络环境。

途中遇到了初次连接正常,但路由器重启后就无法连接的问题。如果此时重启VPS上的WireGuard服务端,则又可正常连接。(尽管WireGuard为对称式设计,但此处为方便表述,将出口节点称为“服务端”)

此问题非常奇怪,因为经测试每次路由器重启后在网络上都是可以正常与服务端主机进行通信的,ssh等服务一切正常。但路由器上的WireGuard显示从未成功进行HandShake,服务端显示Last HandShake时间为路由器重启前上一次成功连接的最后时间。该问题在网上的资料也很少,有相同案例但都没有成功的解决方法。

最后发现问题还是受到了一个Reddit上帖子的启发,一位用户贴出了其WireGuard服务端的详细日志:

[388310.229472] wireguard: wg0: Sending handshake initiation to peer 15 (XX.XX.XX.108:2154)
[388313.665606] wireguard: wg0: Invalid handshake initiation from XX.XX.XX.50:19326
[388315.605443] wireguard: wg0: Handshake for peer 15 (XX.XX.XX.108:2154) did not complete after 5 seconds, retrying 

…where .108 is my router’s old gray IP (before the reboot), and .50 is its current IP as of the time of these messages.

可以看出,服务端虽然还在尝试与旧的连接进行handshake,但却拒绝了路由器重启后新的handshake(用于建立新连接),这时可能有些读者会认为是残留的旧连接阻止了新连接,但这其实并不符合WireGuard的行为。真正的原因是,重启后路由器的系统时间不正确,导致WireGuard服务端拒绝了我们新的handshake。

WireGuard白皮书的5.1节中写道:

An attacker could replay initial handshake messages to trick the responder into regenerating its ephemeral key, thereby invalidating the session of the legitimate initiator (though not affecting the secrecy or authenticity of any messages). To prevent this, a 12-byte TAI64N [7] timestamp is included, encrypted and authenticated, in the first message. The responder keeps track of the greatest timestamp received per peer and discards packets containing timestamps less than or equal to it.

当WireGuard服务端重启后,路由器端首次连接时,服务端还没有记录到过该peer上次handshake发送的时间戳,所以无论路由器在handshake包中发送了一个怎样诡异的时间戳,都会被WireGuard服务端接收,handshake成功,WireGuard连接正常。

随后,由于路由器的网络连接通畅了,NTP时间同步成功,路由器的系统时间正确,于是在几分钟后下一次路由器发送的handshake包中,时间戳已经时正确的时间了,而这个时间戳也被WireGuard服务端记录了下来。

但这就导致的问题, 路由器每次重启后不正确的时间通常较早 ,远早于正确时间,也就意味着,但路由器重启后尝试再次连接时,其在handshake包中包含的这个较早的时间戳,早于WireGuard服务端中记录的上次handshake的时间戳,基于WireGuard防止重放攻击的逻辑,该handshake包会被认为无效并被丢弃掉。

而由于路由器的时间不正确,导致WireGuard无法正常连接,网络不通,也就没法与NTP服务器进行时间同步,去更正不正确的时间,是一个死循环,导致了WireGuard一直无法连接。

知道了问题所在,解决就很简单了,只要保证每次重启后系统时间的正确性就可以了。比如设置一个ipv6的NTP服务器,并让wireguard不要代理ipv6,或者为wireguard客户端设置一个延迟启动,都是可行的方法。

作者:WuSiYu

学生,Web开发者,智能硬件&IOT爱好者

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注