死而未僵的软件:relayd(8) 与 httpd(8) 的持续演进
摘要
一篇博客文章,详细介绍了 OpenBSD 的 relayd(8) 和 httpd(8) 守护进程正在进行的复兴与现代化,包括使 imsg 消息系统现代化以及处理待定补丁的努力,作者称 LLM 是促使自己回归 C 语言编程的动因。
<p><a href="https://lobste.rs/s/i6e5wp/dead_software_walking_ongoing_evolution">评论</a></p>
查看缓存全文
缓存时间: 2026/07/31 18:50
# 死软件行走:relayd(8) 和 httpd(8) 的持续演进
来源:https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/
## 从为什么开始(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#start-with-why)
正如我在我的 OpenBSD 7.8 亮点(https://rsadowski.de/posts/2025/openbsd-78/#daemons)文章中提到的那样,`relayd(8)` 和 `httpd(8)` 的开发曾经停滞不前。许多补丁出现在 `tech@` 邮件列表上,来自不同的贡献者,但很少有被提交到代码仓库中。主要原因很简单:OpenBSD 的资深开发者们对这些守护进程不再感兴趣。你可以称之为势头,或者时机问题。
大约在同一时间,kirill@(https://kirill.korins.ky/)和我开始更积极地研究这些守护进程。我们俩都经常使用它们,并且有现实世界的用例。我为使用 OpenBSD 的客户提供支持,这些客户的设置通常涉及复杂的 `httpd(8)` 和 `relayd(8)` 配置。这种实际需求在多个层面上激励了我。
但最大的动机过去是,现在仍然是 LLM。
多年来,我的职业是编写现代 C++ 代码。最终,我离开了开发工作,专注于解决方案架构、平台工程和团队建设。我很少写实际代码,主要是声明式的 YAML。我唯一做的编码工作是为 OpenBSD ports(7) 阅读和移植代码。
然后 LLM 出现了。当科技老哥们(https://en.wikipedia.org/wiki/Tech_bro)声称“编程已经被解决”时,我意识到了一件事:我想挑战自己,重新开始写代码。我认为,在这种知识正在被外包的时代,拥有这些知识比以往任何时候都更重要!**C** 一直是最让我望而生畏的语言。**C++** 和 **Rust** 会替你完成那些困难的思考。**C** 不会。这正是我想要的:那种挑战。
所以我决定开始为 `relayd(8)` 和 `httpd(8)` 做贡献。
> 战胜自己,胜过赢得千场战役。——佛陀
## 纪律胜过动力(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#discipline-beats-motivation)
我特意用这个标题写了这一节。我们谈论的是开源。即使我做出了贡献的决定,它也可能在几周后以挫败告终。“我为什么要这样对自己?”但我认为我现在已经过了那个阶段。这种痛苦实际上感觉很好。
起初,我被动地通读了代码库,并对很多部分感到沮丧。也许这就是 **C** 代码的写法。也许是缺少注释。也许是某些地方设计不佳。真正的意大利面条式代码。或者也许只是我自己的问题。时间会证明一切。
我与一些 OpenBSD 守护进程维护者进行了交谈,并决定开始现代化手工打造的 imsg 消息系统。我首先专注于 `relayd(8)`。`httpd(8)` 会紧随其后。做这项工作是一种理解代码库的好方法。
我的下一步是翻阅 2024 年到 2026 年的 `tech@` 邮件列表存档。我收集了所有未处理的补丁和问题。我想我已经解决了大部分。如果有人还有未处理的事项,请联系我。
relayd 和 `httpd(8)` 最初由 Reyk Floeter(reyk@)开发。他现在已经从 OpenBSD 退休。我祝他一切顺利。Reyk 还维护了一个 GitHub 镜像:https://github.com/reyk/relayd。我也浏览了那里的旧问题。所有问题都可以关闭、修复,或者已经不再相关。
那个镜像启发了我创建自己的镜像。我想让新的和年轻的贡献者更容易上手。我也想接触 OpenBSD 邮件列表之外的社区。而且,我在一个 CVS 树的 git 镜像上工作。(CVS 和我永远不会成为朋友。我的职业生涯始于 SVN,那已经够痛苦了。不要再有版本控制的痛苦了。)
开发主要发生在 Gothub 实例上。其他位置保持同步:
``
主要:https://rsadowski.gothub.org/
镜像:https://codeberg.org/rsadowski/relayd
镜像:https://github.com/sizeofvoid/relayd
``
`httpd(8)` 也是如此。我写了一份详细的 README.md,涵盖了你需要知道的一切。
## httpd(8) 和 relayd(8) 中的成就(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#achievements-in-httpd8-and-relayd8)
一切应该以积极的语气结束。让我们看看 OpenBSD 团队在 `httpd(8)` 和 `relayd(8)` 中取得了哪些成就:
### relayd(8)(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#relayd8)
#### 现代化与代码质量(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#modernization-and-code-quality)
- **将 imsg 系统转换为使用新的更安全的 getter(imsg\_get\_data、imsg\_get\_type、imsg\_buf\_get)**
- 在整个 imsg 负载读取过程中添加了适当的错误处理
- 与 bgpd 保持一致,统一了日志记录和注释风格
- 将 HTTP 起始行逻辑移入专门的函数,以改进代码组织
- 添加了适当的 knfmt 格式化
#### 安全改进(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#security-improvements)
- **将默认 TLS 密码组从“HIGH:\!aNULL”切换为“secure”**
- **在 CA privsep 引擎中添加了对 ECDSA 的支持**
- 以 HTTP 400 响应拒绝重复的 Content-Length 头
- 拒绝 obs-fold 头,以防止解析器差异(RFC 9112 5.2)
- 通过 ID 检查将 IMSG\_CTL\_PROCFD 限制为父进程
- 对敏感密码数据使用 explicit\_bzero
#### 错误修复与稳定性(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#bug-fixes-and-stability)
- **修复了导致崩溃的 relayd 重载竞态条件**
- 移除了多个内存泄漏(X509\_dup、config\_purge、tls\_cfg)
- 修复了 NULL 检查和边界测试
- 为 OpenSSL 失败添加了适当的错误处理
- **在 TLS 失败时排空 OpenSSL 错误队列**
#### 新特性(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#new-features)
- 添加了对 MKCALENDAR HTTP 方法的支持
- **支持多监听器的 TLS**
- 支持多个可解析地址
- **允许证书、密钥和 OCSP stapling 的显式路径**
- 为 HTTP 健康检查设置 User-Agent
- 正确响应没有正文的 HTTP 响应
### httpd(8)(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#httpd8)
#### 现代化与代码质量(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#modernization-and-code-quality-1)
- 将 proc.c 转换为新的 imsg API,与 relayd 保持一致
- 使令牌顺序更易于为未来的配置选项扩展
- 与 bgpd 保持一致,统一日志记录
- 移除了冗余代码和空函数
- 添加了适当的 knfmt 格式化
- 将内置逻辑移入专门的函数
#### 安全改进(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#security-improvements-1)
- **将默认 TLS 密码组从“compat”切换为“secure”**
- **拒绝 CL.TE 请求分帧,以防止请求走私攻击**
- **以 HTTP 400 拒绝 obs-fold 头(RFC 9112 5.2)**
- **在同时存在 Content-Length 和 Transfer-Encoding 头时报错**
- 启动时随机重新链接以提供额外保护
- 通过 ID 检查将 IMSG\_CTL\_PROCFD 限制为父进程
- 添加“no banner”选项,以隐藏响应中的服务器标识
#### 错误修复与稳定性(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#bug-fixes-and-stability-1)
- 修复了 HTTP 请求中的后缀范围处理
- 修复了 server\_http\_time() 以正确生成 GMT 时间
- 按照手册规范对 timegm(3) 进行错误检查
- 修复了使用分块传输编码的上传
- 修复了 location 中 fcgiparams 被发送两次的问题
- 在 dispatch\_parent 中进行适当的错误处理
- 通过 bufferevent 正确排空 abort 响应
- 修复了 scan-build 发现的死存储问题
- 在复制数据之前验证 return\_uri\_len
#### 新特性(https://rsadowski.de/posts/2026/dead-software-walking-relayd-and-httpd/#new-features-1)
- **添加自定义 HTTP 头支持**
- 在 location 中继承 gzip-static,以改进配置继承
- 将服务器标志扩展为 64 位整数,以提供更多标志选项
- **为静态文件添加缓存控制**
我个人最喜欢的内容用**粗体**标出。
老实说,我的待办事项清单越来越长了。但这没关系。让我们看看今年剩余时间会怎样。如果你有任何想法或反馈,请分享。你知道在哪里能找到我们。
相似文章
一台修复后的 PDP-11/83 在 211BSD Unix 上托管此页面
详细概述一台修复后的 PDP-11/83 系统运行 2.11BSD Unix,展示其硬件组件、软件设置和网络功能以托管网页。
使用 M4 减少重复
本文解释了如何使用 m4 宏处理器,通过创建自定义宏来减少 OpenBSD 的 httpd 配置中的重复代码。
OpenSMTPD 是未来的邮件服务器
Peter N. M. Hansteen 描述了他转向 OpenSMTPD 的过程,因为 OpenBSD 7.9 放弃了 exim,他认为 OpenSMTPD 是 21 世纪的邮件服务器。
为套接字接口喝彩
这篇文章回顾了1983年发布的BSD 4.2套接字接口的历史影响,该接口标准化了网络访问,为现代在线服务铺平了道路。
OpenBSD 反返回导向编程缓解措施的最终版本
本文讨论了 OpenBSD 中反返回导向编程缓解措施的最终实现。