原文链接: Why not WireGuard
最近有一款新型 VPN 工具备受瞩目,相信很多人已经听说过了,没错就是 WireGuard
,传言它有望取代 IPSec
和 OpenVPN
。那么 WireGuard 是否真的有传说中的那么神奇?今天我就来一一解读。
这是一篇非常长的文章,我建议你先去冲杯咖啡,然后边喝咖啡边看。
首先要声明:我并没有诋毁 WireGuard 的意思,WireGuard 很棒很优秀,但总是有某些无脑媒体天天说 WireGuard 即将取代 IPSec
和 OpenVPN
,这我就不能忍了,今天就来和你们好好掰扯掰扯 WireGuard。
WireGuard 白皮书#
本文所有的观点都是针对 Jason Donenfeld
撰写的 WireGuard 白皮书,其他的博客和文档不在我的讨论范围之内。白皮书的第一句话是这么说的:
WireGuard 的目标是在大多数场景下取代
IPsec
和其他基于用户空间和 TLS 的 VPN(例如OpenVPN
),与其他 VPN 相比,它更简单、更高效、更容易使用。
可以看到,WireGuard 最大的卖点就是简单,大多数新技术也都是这个营销套路。当然,作为一款 VPN 产品,它还有性能和安全这两个卖点。
有趣的是,作为 VPN,如果你不简单、不安全、性能不好,那你可能就没有机会了。这不止是你 WireGuard 的设计目标,其他的 VPN 产品也是这么干的好吗?
最有趣的部分是 “在大多数场景下” 这几个字,媒体报道时直接将其删除了,混淆大众的视听。
WireGuard 能否取代 IPSec?#
不!Cisco
和 Juniper
等大厂不可能使用 WireGuard,除非迫不得已,他们是不会上 WireGuard 的车的。后面我会详细解释为什么即使他们想卖 WireGuard 服务也卖不出去。
WireGuard 实现了 Road Warrior?#
当然没有。Road Warrior
是具有动态分配 IP
地址的移动客户端,比如笔记本电脑。你可以直接理解为漫游。WireGuard 目前不能使用动态 IP 来建立连接,要想实现漫游功能,还有很长的路要走。
WireGuard 有一个子项目叫
wg-dynamic,它增加了一个用户空间守护程序来使 WireGuard 支持动态 IP。然而这个项目最后一次更新是在 2019
年,不知道还维护不维护了。。。
大家都知道,IPv6 就是动态寻址的,如果将来全面进入 IPv6 的世界,WireGuard 还怎么用?从商业角度来看,这是相当令人失望的。
WireGuard 的设计目标之一是保持协议的精简,现在看来是精简过头了,以至于需要更多的辅助软件才能使它发挥强大的功效。
WireGuard 真的好用吗?#
并没有。我并没有说 WireGuard 最终不能替代其他 VPN 产品,我只是说目前 WireGuard 还不行,如果它的目标和我们理解的一样,目前它还只是处在 Alpha 阶段。
WireGuard 到底想解决什么问题?IPsec
真的很难用吗?
恐怕不是这样,如果厂商做了正确的功课,并提供了易于使用的界面(比如, IPFire),就不会难用。
要想建立一个 IPSec
隧道,只需要输入 5 组信息:你的公网地址、peer 的公网地址、子网、你的预共享秘钥和 peer 的预共享秘钥。这样看来,几分钟就可以建立一个隧道,而且每个厂商之间都是兼容的。
当然,也有一些例外,比如与 OpenBSD
系统之间建立隧道,过程可能会比较痛苦。
协议复杂度真的很重要吗?#
作为终端用户,其实无需考虑协议的复杂度。
如果复杂度真的影响很大,我们肯定早就摆脱 SIP
、 H.323
和 FTP
等不能很好地应对NAT的协议了,然而并没有。讲道理,IPsec 比 WireGuard 更复杂是有原因的:它能做的事情太多了。比如,使用用户名/密码或带有 EAP
的 SIM
卡进行用户认证;也可以扩展新的加密方式。
而 WireGuard 呢?这些功能都没有。这就意味着当某一天它的固定的那些加密方式被破解或削弱了之后,就彻底崩盘了。
WireGuard 作者说过:
WireGuard 在加密方式上比较偏执,故意砍掉了加密协议的敏捷性,不支持扩展加密协议,因为这么做会大大降低软件的复杂度。如果底层的加密协议出现了漏洞,只能更新所有端点来修复漏洞。
我非常同意他这句话里阐述的观点,因为协商使用何种方式来加密会使 IKE
和 TLS
等协议变得更复杂。那么,是我们想不开刻意要搞这么复杂吗?当然不是啊,即使这样,在握手过程中也会经常发现各种漏洞,不复杂能行吗?除此以外,别无他法。
如何更新密码?#
想象一下,你有一个 VPN 服务器,为 200
多个 Road Warrior 客户端提供服务,而且这些客户端分布在世界各地。假设现在你改了密码,那么就需要同时更新所有客户端的密码才能正常工作,这简直就是不可能的事情,作为管理员,你可能会需要几个月的时间来下方更改后的配置。
IPsec
和 OpenVPN
就没有这些烦恼,它们都有秘钥协商功能,可以将新秘钥逐步更新到所有客户端,在漫长的更新过程中,仍在使用旧秘钥的客户端仍然有效,直到所有客户端更新完毕后,才会弃用旧秘钥。整个过程中客户端不会有任何察觉,也不需要重启。
加密方式#
WireGuard 使用以下加密技术来保障数据的安全:
- 使用
ChaCha20
进行对称加密,使用Poly1305
进行数据验证。 - 利用
Curve25519
进行密钥交换。 - 使用
BLAKE2
作为哈希函数。 - 使用
HKDF
进行解密。
而 IPSec 和 OpenVPN 使用的都是标准的 ChaCha20-Poly1305
加密算法。
BLAKE2
算法是 BLAKE
算法的升级版,而 BLAKE
是 SHA-3
的入围者,与 SHA-2
非常相似,所以没有获奖。如果哪天 SHA-2 被破解了,BLAKE
也很有可能被破解。
IPSec 和 OpenVPN 使用的加密方式和 WireGuard 是类似的,比如对称加密使用的是标准的 ChaCha20-Poly1305
算法。唯一没有用到的就是 BLAKE2
,因为它目前没有列入标准。即使不用 BLAKE2,也没什么大不了的,因为 VPN 是使用 HMACs
来保障数据的完整性,即使使用 MD5
也仍然没问题。
我的结论是:实际上所有的 VPN 都可以使用相同的加密技术,WireGuard 在加密或数据完整性方面并没有比其他的 VPN 更安全或更不安全。
然而白皮书上说了,加密不是重点,速度才是。
好吧,那我们就来看看速度是不是真的有那么快。
WireGuard 真的很快吗?#
答案是否定的。
ChaCha20
是一种流加密算法,一次只加密一个比特,使用软件更容易实现。而像 AES 这样的分块加密方式,会将明文分成多个等长的模块,每次加密 128 位的模块。这种加密方式在硬件中实现时需要更多的晶体管,所以大型处理器都带有一个指令集扩展 –
AES-NI,它可以提高加密和解密的速度。
今天你能买到的任何一款智能手机都带有 AES 的硬件加速功能,在这些硬件中使用 AES
会比 ChaCha20
加密解密更快、更节能。几乎所有的个人 PC 和服务器的 CPU 都带有 AES-NI
,加密解密速度就更不用说了。因此,我预计 AES
在几乎所有场景下表现都会优于 ChaCha20
。
然而,WireGuard 的白皮书又说了,ChaCha20-Poly1305
的性能优于 AES-NI
,但该指令集只适用于大型处理器,对普通 PC 和移动硬件没有任何帮助,所以并没有什么卵用。
WireGuard 执着于一种加密算法,我觉得不好。而 IPSec 允许你选择不同的加密算法,这样就可以根据不同的使用场景选择最合适的加密算法,例如, 传输 10G 或更多的数据。
既然 WireGuard 选择了更现代的加密方式,就会带来很多问题。比如,由于 Linux 内核中缺乏支持这些加密方式的模块,导致 WireGuard 并没有使用 Linux 内核提供的模块,要推迟好几年才能用上 Linux 内核提供的模块。我不知道其他操作系统是什么情况,但可能也没有什么不同。
理想与现实#
假设 WireGuard 真的很完美,大厂就一定会用吗?
现实情况是,每次当客户要求我帮他们搭建 VPN 时,给到他们手里的证书都是使用旧的加密方式,通常是 3DES
和 MD5
结合,或者 AES-256
和 SHA1
结合。至于秘钥交换,我们一直在使用 RSA
,虽然速度很慢,但足够安全。
大部分客户都和政府机构或巨头公司有关,他们在我们这里的订单表还是几十年前的,根本就没有添加过 SHA-512
的选项。所以阻止创新的不一定是技术,而是缓慢的企业流程。
看到这种情况,我也很痛心?我就不想使用新技术吗?当然想啊。IPsec 从 2005 年左右就开始支持椭圆曲线加密算法了,Curve25519
算法现在也支持了,也有了 AES
的替代方案(比如 Camellia
和 ChaCha20
),但很显然并不是所有的大厂都愿意去适配,比如思科等。思科是这个领域的市场领导者,他们对推动创新其实并不感兴趣。
基准测试#
白皮书中还提到了 WIreGuard 的基准测试,虽然这不是一篇科学论文,但我仍然希望以科学的方法来进行基准测试。如果测试不能重复,那么它就毫无价值;如果测试没有考虑实际场景,也毫无价值。
WireGuard 的 Linux 版本使用 GSO
(Generic Segmentation Offloading,通用分段卸载)来创建一个 64k
字节的巨大数据包,并一次性对其进行加密或解密,以此来获得速度优势。这样一来,初始化和调用加密操作的开销就被节省了。如果你想最大限度地提高吞吐量,这倒是一个好主意。
然而现实不是这样的,你想向网络适配器发送如此大的数据包,就需要将其切割成许多小数据包,通常为 1500
字节。对于 64k 字节的超大数据包来说,会被切割成 45
个数据包(每个数据包有 1480
字节的有效载荷和 20
字节的 IP 头),这些数据包将会阻塞网络适配器相当长的时间,因为它们想要被一次性发送出去。像 VoIP
呼叫这样应该优先处理的数据包也不得不慢慢等着。
因此,WireGuard 宣称的高吞吐量是通过让其他应用变慢来获得的,官方团队已经承认了这一点。
我们再来看看基准测试的最终数据,吞吐量为 1011 MBit/s
!
这个数据令人印象深刻,我至今仍感到疑惑,在数据包大小为 1500 字节的情况下,一个千兆以太网链路的最大理论吞吐量为 966 MBit/s
,减去 20 个字节的 IP 头、8 个字节的 UDP 头和 16 个字节的 WireGuard 头,再减去封装数据包中的另一个 IP 头和另一个 20 个字节的 TCP 头,额外的带宽到底从哪来的?
OK,假设启用了巨型帧和 GSO
,9000
字节帧大小时的理论最大值将是 1014 MBit/s
。如果使用更大的巨型帧,理论最大值为 1023 MBit/s
。然而这在现实中是绝对不实用的,因为开销太大了,而且只能在服务器直连的情况下使用。通常 VPN 都是通过互联网连接的,完全不支持巨型帧,所以这样的基准测试根本不切实际,永远不可能在现实世界中使用。
最终幻想#
WireGuard 的官方网站写了很多关于容器的内容,很明显这应该就是 WireGuard 的目的。
通过一个简单迅速的 VPN 来实现容器通信的 CNI,可以通过 Kubernetes 等大型容器编排工具来快速部署,针对吞吐量和大于 9000
字节的数据包进行了优化,可以快速分发容器镜像,等等。
这一切的种种都好像是为容器而设计的,不得不承认超精简、超优雅、超快速。
但是,它根本不是为数据中心以外的世界而设计的,在外面的世界,你必须要在协议的设计和实现上做出妥协。
总结#
我最终的结论是:WireGuard 还没有准备好。
它是作为一个轻量级和快速的解决方案来起草的,以解决现有解决方案中的一些问题,但不幸的是,它牺牲了许多与用户相关的功能,因此无法取代 IPsec 和 OpenVPN。
你至少得有动态地址分配和推送路由等配置的功能吧?这些功能都是需要进行秘钥协商的。
此外,安全性是重中之重,目前我还没发现 IKE
或者 TLS
有啥明显的缺陷,它们都支持现代加密方式,而且都经过了几十年的审计。不能仅仅因为某些东西是新的,就觉得它是好的。
加密方式总会过时,押注在一种加密方式身上,当这种加密方式不再安全时,你该何去何从?