Start with WHY #
As I mentioned in my OpenBSD 7.8
highlights post,
development of relayd(8) and httpd(8) had stalled. Many diffs appeared on
the tech@ mailing list from different contributors, but few were committed
into the repository. The main reason was simple: Established OpenBSD developers
weren’t interested in these daemons anymore. Call it momentum, or timing.
Around the same time, kirill@ and I started working
on these daemons more actively. We both use them regularly and have real-world
use cases. I support customers with OpenBSD setups that often involve complex
httpd(8) and relayd(8) configurations. This practical need motivated me on
many levels.
But the biggest motivation is and was LLMs.
For many years, I wrote modern C++ code professionally. Eventually, I moved away from development work and focused on solution architecture, platform engineering, and building teams. I wrote little actual code, mostly declarative YAML. The only coding I did was reading and porting code for OpenBSD ports(7).
Then LLMs arrived. As tech bros claimed “coding is solved”. I realized something: I wanted to challenge myself to code again. I think that at a time when this knowledge is being outsourced, it’s more important than ever to have it! C has always been the language that intimidated me most. C++ and Rust handle the hard thinking for you. C doesn’t. That’s exactly what I wanted: that kind of challenge.
So I decided to start contributing to relayd(8) and httpd(8)().
It is better to conquer self than to win a thousand battles. – Buddha
Discipline beats motivation #
I wrote this section with this title intentionally. We’re talking about open source. Even though I made the decision to contribute, it could have ended in frustration weeks later. “Why am I doing this to myself?“But I think I’m past that point now. The pain actually feels good.
At first, I read through the codebase passively and was discouraged by many parts. Maybe it’s just how C code is written. Maybe it’s the lack of comments. Maybe it’s poor design in places. Real spaghetti code. Or maybe it’s just me. Time will tell.
I talked to the some OpenBSD daemon maintainers and decided to start modernizing
the handcrafted imsg message system. I’m focusing on relayd(8) first. httpd(8) will
follow. Working on this is a great way to understand the codebase.
My next step was to go through the tech@ mailing list archives from 2024 to
2026. I collected all open diffs and issues. I think I’ve addressed most of
them. If anyone has something pending, please reach out.
relayd and httpd(8) were originally developed by Reyk Floeter (reyk@). He is now
retired from OpenBSD. I wish him all the best. Reyk also maintained a GitHub
mirror: https://github.com/reyk/relayd. I went through the old issues there too.
Everything can be closed, fixed, or is no longer relevant.
That mirror inspired me to create my own. I wanted to make it easier for new and young contributors. I also wanted to reach the community beyond the OpenBSD mailing lists. Also, I work on a git mirror of the CVS tree. (CVS and I will never be friends. I started my career with SVN, which was painful enough. No more version control pain.)
Development happens primarily on the Gothub instance. The other locations are kept in sync:
Primary: https://rsadowski.gothub.org/
Mirror: https://codeberg.org/rsadowski/relayd
Mirror: https://github.com/sizeofvoid/relayd
The same goes for httpd(8). I wrote a detailed README.md that covers everything you
need to know.
Achievements in httpd(8) and relayd(8) #
Everything should end on a positive note. Let’s look at what the OpenBSD team
has accomplished in httpd(8) and relayd(8):
relayd(8) #
Modernization and Code Quality #
- Converted the imsg system to use new safer getters (imsg_get_data, imsg_get_type, imsgbuf_get)
- Added proper error handling throughout imsg payload reading
- Standardized logging and comments with bgpd for consistency
- Moved HTTP start line logic into dedicated functions for better code organization
- Added proper knfmt formatting
Security Improvements #
- Switched default TLS cipher set from “HIGH:!aNULL” to “secure”
- Added ECDSA support to the CA privsep engine
- Reject duplicate Content-Length headers with HTTP 400 response
- Reject obs-fold headers to prevent parser differentials (RFC 9112 5.2)
- Restrict IMSG_CTL_PROCFD to parent process with ID checks
- Use explicit_bzero for sensitive password data
Bug Fixes and Stability #
- Fixed relayd reload race condition that caused crashes
- Removed multiple memory leaks (X509_dup, config_purge, tls_cfg)
- Fixed NULL checks and bounds tests
- Added proper error handling for OpenSSL failures
- Drain OpenSSL error queue on TLS failures
New Features #
- Added support for MKCALENDAR HTTP method
- Support for TLS with multiple listeners
- Support for multiple resolvable addresses
- Allow explicit paths for certificates, keys and OCSP staples
- Set User-Agent for HTTP healthchecks
- Handle HTTP responses without bodies correctly
httpd(8) #
Modernization and Code Quality #
- Converted proc.c to new imsg API for consistency with relayd
- Made token order more easily extendable for future configuration options
- Standardized logging with bgpd
- Removed code redundancy and empty functions
- Added proper knfmt formatting
- Move builtin logic into dedicated function
Security Improvements #
- Switched default TLS cipher set from “compat” to “secure”
- Reject CL.TE request framing to prevent request smuggling attacks
- Reject obs-fold headers with HTTP 400 (RFC 9112 5.2)
- Error out on simultaneous Content-Length and Transfer-Encoding headers
- Random-relink at boot time for additional protection
- Restrict IMSG_CTL_PROCFD to parent process with ID checks
- Add “no banner” option to hide server identification from responses
Bug Fixes and Stability #
- Fixed suffix range handling in HTTP requests
- Fixed server_http_time() to emit GMT times correctly
- Error check timegm(3) per manual specifications
- Fixed uploads using chunked transfer-encoding
- Fixed location fcgiparams being sent twice
- Proper error handling in dispatch_parent
- Drain abort responses via bufferevent correctly
- Fixed scan-build dead stores findings
- Validate return_uri_len before copying data
New Features #
- Add custom HTTP header support
- Inherit gzip-static in locations for better configuration inheritance
- Widen server flags to 64-bit integers for more flag options
- Add cache controls for static files
My personal highlights are in bold.
Honestly, my backlog has grown. But that’s fine. Let’s see where the rest of the year takes us. If you have ideas or feedback, please share them. You know where to find us.
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.