LWN: Rustls - 采用内存安全的方法来实现TLS!
关注了就能看到更多这么棒的文章哦~
Rustls: memory safety for TLS
By Jake Edge
May 4, 2021
DeepL assisted translation
https://lwn.net/Articles/853712/
在过去的一两年里使用 memory-safe 语言(具体来说就是 Rust 语言)的运动已经越来越受重视。它能避免缓冲区溢出(buffer overflows)、释放后仍继续使用(use-after-free)以及其他那些跟未管理好的指针有关的问题,尤其是考虑到如今大多数的漏洞都来自于 memory-safety 问题。4月 20 日,互联网安全研究小组(ISRG,Internet Security Research Group)宣布了一项针对 Rustls TLS 库的资助计划,希望能完善它从而可以被更广泛的采用起来,包括用在 ISRG 的 Let's Encrypt 项目中。
谷歌提供了这部分资助,使得 ISRG 能与 Dirkjan Ochtman 签订合同对该库进行一些改进。公告中列出的两项的目标都是希望使 Rustls 能更容易地同目前大量在使用的 C 代码集成配合起来。这些现有程序大多在使用基于 C 的 OpenSSL 库来实现 TLS 功能。可以预料,ISRG 及其执行董事 Josh Aas(这个公告的作者)对 Rust 和 Rustls 的发展前景相当兴奋:
Rustls 是 OpenSSL 和类似的库的一个很好的替代品。它的大部分关键代码都是用 Rust 编写的,所以它在很大程度上是内存安全的,并且不会牺牲性能。它已经经过审查,并被认为是一个高质量的实现。下面是报告中我们最喜欢的一句话。
"使用类型系统(type system)来对属性(如 TLS 状态转换函数)进行静态编码(encoding),这仅仅是伟大的深入防御(defense-in-depth)设计决策的一个例子。"
[……]我们目前生活在这样一个世界:经常会在网络的边缘侧部署几百万行的 C 代码来处理各种 request,尽管我们有无数证据表明这种做法是不安全的。我们的行业需要达到这样一个共识:部署不符合内存安全的代码来处理网络流量应该被公认为是危险和不负责任的。不过,人们需要能满足他们需求的内存安全软件,这就是为什么我们要开始这个工作。
Rustls 项目(这个名字的发音是 "rustles",并不是指不用 Rust。。。)自 2016 年以来一直存在,但在过去一年里发布的速度变快了。它的底层是用 Rust、C 和汇编编写的 ring cryptographic library,以及同样用 Rust 编写的用于证书验证的相关 webpki 库。Rustls 项目正在努力解决早期 TLS 实现中的错误(比如过时的协议版本和 cipher),希望成为一个强大的库,来避免这种场景(处理来自广大互联网的不可信任的输入内容)下的代码所存在的诸多陷阱,。
根据公告,ISRG 已经开始将 Rustls 整合到 curl 和 Apache 网络服务器中。针对 Apache 来说,ISRG 认为用一种内存安全的语言来建立一个完整的网络服务器会是非常有好处的,但需要巨大的努力。而将 TLS 处理改为由 Rustls 完成就是很好的一步。谷歌已经为 Stefan Eissing 提供了资金,让他做网络服务器方面的工作,而 ISRG 正在资助 curl 的作者和维护者 Daniel Stenberg,让他致力于使 curl 更符合内存安全。除了允许使用 Rustls 之外,curl 的改造还增加了对 hyper 这个基于 Rust 的 HTTP 库的支持。可以看出,对于这一领域来说,拥有内存安全库的生态系统将会不断增长。
作为 Ochtman 的工作的一部分,ISRG 正在针对 Rustls 进行几个方面的改进,包括努力消除 panic 的函数,因为这些函数会导致程序 crash。正如 Rust 文档所指出的,使用 panic!() 会使得调用者函数无法从错误中恢复过来,这在许多 Rust 代码中不是一个正确做法。Linus Torvalds 在审查中强调,正在试图合入 Linux kernel 的 Rust 代码中存在的 panic 调用是一个问题。Rustls 项目正在努力消除自己代码中的 panic,以及消除对可能出现 panic 的库函数的调用,以便为应用程序提供一组不会 panic 的 API。
Rustls 的 C 语言 API 也是这次资助工作的一个重点。由于今天很多使用 TLS 的软件都是用 C 语言编写的,因此 Rustls 库与 C 语言的接口很重要。公告中提到了将 API 转移到 Rustls 的主仓库中,尽管 GitHub 上跟踪这个问题的 issue 里面并没有明确的倾向性。不过,开发人员似乎确实更加倾向于这个方向。
ISRG 的另一个改进目标是支持证书中 SAN(Subject Alternative Name)字段中的 IP 地址。SAN 是 X.509 格式的扩展,用在公钥证书(如网站使用的 SSL/TLS 证书)里。有些环境下会使用 IP 地址,而不是域名,因为相应的主机没有使用 DNS。公告列出的最后一个功能是允许根据客户端提供的信息来配置 server connection。这个功能是用于处理 SNI(Server Name Indication)和应用层协议协商(ALPN,Application-Layer Protocol Negotiation)TLS 扩展的,也就是允许客户端告知服务器自己的偏好。
从安全的角度来看,处理那些用户控制的(或者说攻击者控制的)输入信息显然是一个更大的关注领域。互联网上最早的 "攻击 "之一也就是 1988 年的莫里斯蠕虫病毒,就是部分依赖于网络服务中的缓冲区溢出问题。在此后的几十年里还出现了许多类似的漏洞。这些问题可以通过使用像 Rust 这样的内存安全语言来避免,尽管还会有小概率的出错机会,这可以从 C 语言的 API 中看出来。
当两种语言一起使用时,C和 Rust 处理内存的方式不匹配仍然是一个潜在问题领域。例如,Rustls C API 提供了一种分配和释放 structure 的机制,以便在调用库时使用,但在使用时有一些重要的注意事项。程序需要确保在任何时候只有一个线程在访问该结构(可以使用 mutex 或其他互斥保护机制来实现),并且该结构也只能被释放一次。这些限制对 C 语言程序员来说也很容易理解,但这确实说明了从 C 语言调用 Rust 时内存安全保证相关的(明显的)限制。
在接下来的几年里,我们将有很多机会可以看到这种处理 C 语言程序中缺乏内存安全的混合使用方法的效果如何。这有很好的前景,而且 Rust 语言已经获得了相当多的欢迎,希望它能成为我们未来内存安全的主要部分。很期待看到现实是否和愿景(以及在某种程度上来说的炒作)一样宏伟,这将会是很有趣的事情。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~