我为什么不鼓吹 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 有啥明显的缺陷,它们都支持现代加密方式,而且都经过了几十年的审计。不能仅仅因为某些东西是新的,就觉得它是好的。
加密方式总会过时,押注在一种加密方式身上,当这种加密方式不再安全时,你该何去何从?
Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12离线安装包发布地址http://store.lameleg.com ,欢迎体验。 使用了最新的sealos v3.3.6版本。 作了主机名解析配置优化,lvscare 挂载/lib/module解决开机启动ipvs加载问题, 修复lvscare社区netlink与3.10内核不兼容问题,sealos生成百年证书等特性。更多特性 https://github.com/fanux/sealos 。欢迎扫描下方的二维码加入钉钉群 ,钉钉群已经集成sealos的机器人实时可以看到sealos的动态。

我为什么不鼓吹 WireGuard的更多相关文章
- Kilo 使用教程
写了这么多篇 WireGuard 相关的保姆教程,今天终于牵扯到 Kubernetes 了,不然怎么对得起"云原生"这三个字.如果看到这篇文章的你仍然是个 WireGuard 新手 ...
- 今天我得鼓吹一波 Kotlin
Kotlin 被作为 Google 官方语言也有一年多了,但除了刚宣布那个月极度火爆以外,后面生活又回归了平静.不少小伙伴紧跟 Google 爸爸的步伐,也对 Kotlin 有了或多或少的了解,Git ...
- 新的WireGuard快照发布
导读 WireGuard首席开发人员Jason Donenfeld宣布发布WireGuard 0.0.20190123,作为Linux系统和其他平台的安全VPN隧道实施的最新快照. WireGuard ...
- WireGuard 隧道的安装和使用,测试地址 ca.6tu.me
WireGuard 端到端平等的网络隧道,测试地址 ca.6tu.me --------------------------------------------- 服务器:远程 Ubuntu18 , ...
- wireguard使用方法
1.翻墙访问网页:https://cryptostorm.is/wireguard.cgi 并下载客户端 2. 选者第二个并打开 3.复制publickey 4.黏贴在第二行并addkey: 5.将获 ...
- WireGuard 教程:WireGuard 的工作原理
原文链接:https://fuckcloudnative.io/posts/wireguard-docs-theory/ WireGuard 是由 Jason Donenfeld 等人用 C 语言编写 ...
- 那些鼓吹国内首个.NET 5框架的,该醒醒了!
前两天看过园子里有篇[国内首个 .NET 5 框架 XX 斩获 XXX stars,XXX 发布],一顿羡慕嫉妒恨啊.我这.net core 3.1才上手没几天,还没用热乎呢,你这.NET 5的框架都 ...
- wireguard使用
1.编译与安装 sudo apt-get install libmnl-dev libelf-dev linux-headers-$(uname -r) build-essential pkg-con ...
- WireGuard 教程:使用 DNS-SD 进行 NAT-to-NAT 穿透
原文链接:https://fuckcloudnative.io/posts/wireguard-endpoint-discovery-nat-traversal/ WireGuard 是由 Jason ...
随机推荐
- Docker实例开机启动
部署项目服务器时,为了应对停电等情况影响正常web项目的访问,会把Docker容器设置为开机自动启动. 在使用docker run启动容器时,使用--restart参数来设置: docker run ...
- Java通过IO流输出文件目录
//通过IO流输出文件目录,不同级的目录之间用*间隔 1 package com.fjnu.io; 2 3 import java.io.File; 4 5 public class dicOut { ...
- 工作中用的sql
//字段是空字符串或者null select * from blade_process_should_pay_invoice where is_deleted = 0 and process_inst ...
- 【Mongodb】后台主键_id自增(Java版本)
ObjectId的选择 创建MongoDB文档时,如果没有赋值ID,系统会自动帮你创建一个,通常会在客户端由驱动程序完成.得到的ObjectId类似于这种 ObjectId使用12字节的存储空间, ...
- CentOS安装TensorFlow
1.升级python 系统自带的python是2.6,不能用,升级到2.7,方法见:http://www.cnblogs.com/stAr-1/p/9055980.html 2.升级python带来的 ...
- Class的一些使用技巧?
1.forName和newInstance结合起来使用,可以根据存储在字符串中的类名创建对象.例如 Object obj = Class.forName(s).newInstance(); 2.虚拟机 ...
- vue中的插值操作
mustache语法 1.将data的文本数据插入至html语句中,使用mustache语法. v-once指令 2.在某些情况下,我们不希望界面随意的跟随改变,这个时候我们可以使用v-once的指令 ...
- Redis--部署操作
1.Redis 1.1 安装 当前ubuntu虚拟机中已经安装好了redis,以下步骤可以跳过 以后自己安装过程如下:redis下载链接:x 指的是版本号 http://download.redis. ...
- 第三章 IP地址规划设计技术(很重要)
知识重点: 选择题考点 IP基础(网络地址.子网掩码) 网络地址转换 NAT 的原理 CIDR (计算方法) IPv6 地址表示 综合题 IP地址的分类与计算 VLSM 地址规划 3.1 基础知识 3 ...
- java集合并发操作异常解决方法:CopyOnWriteArrayList
一.我们知道ArrayList是线程不安全的,请编写一个不安全的案例并给出解决方案 HashSet与ArrayList一致 HashMap HashSet底层是一个HashMap,存储的值放在Hash ...