Ubuntu 20.04 原生 WireGuard 初体验

前不久 Ubuntu 20.04 正式 release 了,挺多期待已久的新特性都转正成为了“原生”,如zfs、WireGuard. 而作为一名 gopher, 我留意到,负责维护 golang 标准库中网络相关(net/http)的 committer Bradfitz 前不久从Google离职加入了基于 WireGuard 技术创业公司 Tailscale. 这引发我强烈的好奇,因此 Ubuntu 20.04 发布,自然是要体验一下 WireGuard.

WireGuard 的关键特性

WireGuard 一直宣传自己是现代的快速安全的VPN。快速主要体现在部署的便捷、高性能(通过内核原生+CPU友好的加密算法实现);安全则是从设计之初就考虑到了了前辈的一些安全问题,以及学院派研究的加持,更多细节可以参考 technical whitepaper. 当然,从当前的limitation看,ID还无法做到前向安全,因此无法做到 no-tracking。

WireGuard 安装及配置

安装直接参考官方Installation文档,配置可以参考 Set Up WireGuard VPN on Ubuntu.

几点疑问及思考

WireGuard 能作为你特殊用途协议吗?

不能。主要原因有两点:

  • 协议没有做混淆,也没有隐藏包特征,过不了DPI(Deep Packet Inspection)检测。
  • ID非前向安全。因此通信一方compromised以后,会泄露历史通信peer.

WireGuard Server 支持 DDNS 吗?

支持。在一些场景,可能 server 端并没有一个固定IP,这种时候我们一般是使用DDNS将动态IP绑定在一个域名上面。这种场景下,配置client端配置时,将Server Public IP配置为域名即可:

[Peer]
PublicKey = <server public="" key="">
Endpoint = <server ddns="" domain="">:51820
AllowedIPs = 10.0.0.2/24, fd86:ea04:1115::5/64

WireGuard Server 是否可以动态添加 peer?

不可以也可以。因为 WireGuard 理念认为提前设计和分配自己的网络更佳好的方式。不过,也并不是完全没有work around的方式。如果你有动态IP和配置的需求,个人用户可以参考wg-dynamic, 企业用户推荐直接使用 Tailscale 的产品。

一个出生在内核的VPN到底有何特殊的意义?

回到本源,VPN本身的目的是什么?私以为是anytime, anywhere, 简单、快速、安全的网络互联。而这与WireGuard的设计目标是完全一致的。互联网底座这几年的发展趋势之一是加密整个互联网:元老级应用层协议http在发展过程中不断进化,来到http/2 的时候我们看到的一个显著改变那就是 mutilplex 和 force https。而作为更加底层的网络基建VPN却一直没有出现这样的角色。WireGuard的出现让我们看到了这个可能,但也只是一个更好的VPN的定位。而直到20.04确认将其加入内核,为其加密整个网络插上翅膀,我们才有理由相信这个角色到位了。

从这个角度来看,WireGuard无限接近理想的VPN,或者说它重新定义了VPN的初心。因此,不要拿个人日常运动小需求来揣测WireGuard的鸿鹄之志。顺着这个方向继续看,可以看到 WireGuard 的(潜在)应用场景有:

  • 远程办公网络基建。传统的VPN能不能解决?能。但是都解决得不好,要么是部署太过复杂,要么协议本身就因为历史原因漏洞一大把。而WireGuard部署成本极低(如果你按照上述文档部署一次,应该不会超过10分钟),全客户端支持,code base 只有4000行,非常容易发现、修复、迭代。而这次疫情的出现,让远程办公成为新常态推进了一大步。但是扪心自问,有多少所谓的远程办公是战斗力残废,又有多少其实是临时让IT开了个网络口子裸奔办公?因此,私以为基于WireGuard的远程办公在未来一两年是能看到几家公司成长起来的。
  • 异地多活架构。K8S生态解决单IDC可用性问题是足够的,但是在当前越来越强调稳定、体验产品时代,很多公司都开始走上异地多活的架构。WireGuard可能带来两个契机:1. 云厂商IDC互通的大一统;2. 自主异地多活架构的标准化,而这可能带来一波IDC异地多活网络中间件的开源生态繁荣。
  • 智能家居网络路由器。虽然现在的家电只要搭配一个wifi就号称自己是智能家电,但大多数不过是把家电连到厂家的服务器。这只能算是智能家电社会主义初级阶段,未来理想的形态是家庭中的设备与业主anytime, anywhere的互通。以前的解决方案都太trick了,而WireGuard找了个好爹,并且其极低的门槛都有希望在这个系分领域有所建树。

而以上这些,不过是 Bradfitz 的新东家 Tailscale 已经发布的部分创业产品。过两年以后,我会回头再次审视以上判断,说不定,上面的判断全都错了。

HTTP/3 已经箭在弦上,你准备好了吗?

去年的这个时候,国内的 web 网络环境开始普及和部署 HTTP/2. 时隔一年,HTTP/2 的普及程度有了显著提升,而各大CDN厂商普及的广度和速度一直走在行业前列。甚至有不少CDN厂商在直播以及部分HTTP场景还引入了 QUIC.

在拙文《当我们在谈论HTTP队头阻塞时,我们在谈论什么?》中,我们提到,HTTP/2 over QUIC 是当前唯一应用落地解决了传输层队头阻塞问题的HTTP实现。那个时候,无论是 HTTP/2 over TCP 还是 HTTP/2 over QUIC(UDP) 都被我们认为是 HTTP/2,只是传输层使用的协议不一样。这种略带暧昧的模糊叫法在2018年11月成为了历史:

在2018年10月28日的邮件列表讨论中,互联网工程任务组(IETF) HTTP和QUIC工作组主席Mark Nottingham提出了将HTTP-over-QUIC更名为HTTP/3的正式请求,以“明确地将其标识为HTTP语义的另一个绑定……使人们理解它与QUIC的不同”,并在最终确定并发布草案后,将QUIC工作组继承到HTTP工作组。在随后的几天讨论中,Mark Nottingham的提议得到了IETF成员的接受,他们在2018年11月给出了官方批准,认可HTTP-over-QUIC成为HTTP/3。

虽然看起来像是之前的 HTTP/2 over QUIC 换了一个名称(从我个人角度理解,取名为 HTTP/2.1也许更合适),但是其背后却体现了 IETF 对 HTTP 未来标准的态度和方向,也许几年以后来看这次名称的确立会更加明白其重要意义。

HTTP/3 与 HTTP/2 over QUIC 的区别

QUIC 将成为一个通用安全传输层协议

当前阶段,Google 实现的 QUIC 与 IETF 实现的 QUIC 是不兼容的。Google 版 QUIC 只能用于 HTTP/2,且在协议层面与 HTTP/2 有一些强绑定。如 QUIC 帧映射 HTTP/2 frame. 这就导致很多大厂都没有跟进 QUIC,使得 HTTP/2 over QUIC 基本只能在 Google 自家的 Chrome, Gmail 等软件中普及使用,一度给行业造成“只有Google在弄”的错觉。

纳入 IETF 以后,显然 Google 就不能这么玩了。QUIC 定位为一个通用安全传输层协议:

可以近似的认为 QUIC over UDP 将成为下一代(或替代)TLS over TCP. 也就是说, QUIC 将能应用于任何应用层协议中,只是当前阶段将优先在 HTTP 中进行应用和验证。

统一使用 TLS 1.3 作为安全协议

2018年,有几个重要的WEB标准终于尘埃落定,其中一个便是 RFC 8446 TLS 1.3. 这个标准对于降低延迟,改善用户体验,尤其是移动端的体验有非常重要的意义。在拙文《TLS1.3/QUIC 是怎样做到 0-RTT 的》中,我们提到 虽然 TLS 1.3和 QUIC 都能做到 0-RTT,从而降低延迟,但是 QUIC 却自顾自地实现了一套安全协议。主要是因为当时 TLS 1.3 标准还没有发布,而 QUIC 又需要一套安全协议:

The QUIC crypto protocol is the part of QUIC that provides transport security to a connection. The QUIC crypto protocol is destined to die. It will be replaced by TLS 1.3 in the future, but QUIC needed a crypto protocol before TLS 1.3 was even started.

如今,TLS 1.3 标准已经发布,而 HTTP/3 也纳入 IETF,因此 QUIC 也就顺理成章的使用 TLS 1.3 作为其安全协议。Google 在这些方面倒是从来都不鸡贼和墨迹,点赞。

使用 QHPACK 头部压缩代替 HPACK

其实,QPACK与HPACK的设计非常类似,单独提出QPACK主要是更好的适配QUIC,同时也是 Google 将 QUIC 从与 HTTP/2 的耦合中抽离出来,与 IETF 标准完成统一的必要一步。

HTTP/3 问题与挑战

UDP 连通性问题

几乎所有的电信运营商都会“歧视” UDP 数据包,原因也很容易理解,毕竟历史上几次臭名昭著的 DDoS 攻击都是基于 UDP 的。国内某城宽带在某些区域更是直接禁止了非53端口的UDP数据包,而其他运营商及IDC即使没有封禁UDP,也是对UDP进行严格限流的。这点上不太乐观,但是我们相信随着标准的普及和推广落地,运营商会逐步改变对UDP流量的歧视策略。国外的情况会稍好一些,根据Google的数据,他们部署的QUIC降级的比例不到10%。

QUIC 不支持明文传输

对于用户来说,这是一个优势,并不是问题。对于国内内容审查环境来说是个不可忽视的坎。但QUIC以后毕竟也是基于TLS协议的,国内HTTPS都能普及下来,QUIC的普及也许会更乐观一些。

UDP 消耗资源多

当前阶段,UDP消耗的CPU资源多,且处理速度慢。这是不争的事实,但是我相信随着UDP应用的增多,内核和硬件的优化一定会跟上,直至达到或超过TCP的性能。而 QUIC 因为实在应用层实现,因此迭代速度更快,部署和更新难度和代价更小,能够一定程度缓解如TCP那样的协议僵化问题。

进一步了解 HTTP/3

如果希望全面的了解 HTTP/3,推荐 Daniel Stenberg (CURL 作者)的 HTTP/3 explained, 如果不想看英文,可以翻阅 Yi Bai 同学翻译了中文版本HTTP/3详解

移除 macOS 中被企业策略强制安装的 Chrome 插件扩展的方法

公司配发的 Macbook 安装了一些监控软件,毕竟是办公设备,这点倒是无可厚非。但是,其中的 Forcepoint DLP Endpoint 会向日常使用的主力浏览器 Chrome 中安装一个 WebsenEndpoint 的扩展插件。

这个插件的作用不必多说,但是有一个副作用就是让 Chrome 无法自动填写任何网站用户名密码。每天要输入上百次的密码这种体力活是绝对不能忍受的。于是尝试卸载这个插件。但是这个插件是使用企业策略 (Installed by enterprise policy) 强制安装,无法在Chrome中下载。但是可以通过将与之关联的 Profile 删除实现卸载的作用:

但是过两天,Forcepoint 又会把这个插件装回来? 不过没关系,我们有的是办法。

方法一:通过占用 Chrome 插件文件位置,防止真正插件重新装回

原理是这样的:Chrome 的插件安装在 ~/Library/Application Support/Google/Chrome/Default/Extensions 目录下:

除去 Temp, 每个文件夹对应一个插件。我们希望移除的插件的文件夹名称是 kmofofmjgmakbbmngpgmehldlaaafnjn。由于 macOS 文件夹下,相同名称的文件和文件夹只能存在一个。因此,我们只需要在插件删除以后,在这个目录下新建一个名称为 kmofofmjgmakbbmngpgmehldlaaafnjn 的空文件:

然后,再通过文件系统的 Lock 功能锁定改文件,防止该文件被 Forcpoint 删除:

至此,大功告成,so easy!

方法二:修改 Forcepoint DLP Endpoint 插件安装脚本,禁止强奸 Chrome

法一虽然可以防止Chrome被重新安装插件,但是过几天以后,你会在你的 Profiles 配置下发现,虽然 Chrome 插件安装失败了,但是依然会成功安装这个 Profile:

虽然不会干扰系统的任何功能,但是估计很多强迫症患者看到这个还是挺难受的……从图中我们可以看到,这个插件的路径在 /Library/Application Support/Websense Endpoint/DLP:

其中 setup_chrome_ext.sh 就是强插 Chrome 的脚本:

脚本写得简单粗暴:通过 $PROFILES -I -F "/Library/Application Support/Websense Endpoint/DLP/WebsenseEndpointExtension.config" 向系统强行安装 profile. 要防止其安装插件,把这行代码删除即可。但是,这个文件是属于 admin 用户组的,我们平时使用的账号,即使集合 sudo 也只是 wheel 用户组,是干不过 admin 的,导致我们无法在正常模式下编辑该文件:

因此,我们需要通过 Command (⌘)-R 重启到恢复模式,然后在 /Volumes/mac.os/Library/Application Support/Websense Endpoint/DLP 目录下,将对应代码删除即可。

至此,自己基本满意了?

后记

稍微浏览了一下 /Library/Application Support/Websense Endpoint 文件夹,发现其实这个软件不仅强插 Chrome, 还会强插 FireFox:

艾玛……proxy…吓死宝宝了,已经不想改脚本了。直接在恢复模式下删除文件,然后用方法一的方法,建了一个 Lock 文件锁定这个位置。什么,还有 upgrade.sh? 你怎么不上天呢,也一并删除了……突然想起,自己在无所不能的恢复模式下,要不整个软件一起删除了?想到隔天IT技术小哥可能过来找麻烦,就此打住吧?