A memory safe alternative to the OpenSSL based Apache module providing https capability.
The new, and expirimental, Rust-based Apache httpd module mod_tls
has existed since Apache 2.4.52 (December 2021). The module was
commissioned by the Prossimo Memory Safety initiative,
which in turn is an Internet Security Research Group
project.
Prossimo contracted Stefan Eissing, an Apache
httpd maintainer and creator of the HTTP/2 and ACME modules.
It was about time that this was made available for FreeBSD, the not ABI-stable Rustls and Rustls-ffi libraries were blocking earlier, but have been updated in the Apache httpd 2.4.60 release.
Let's try this again!
So we have a new port to create, and the Apache httpd port to modify to allow mod_tls to be built as a module.
Rustls-ffi
So there I was, overcomplicating things. It's not that building Rust doesn't take forever-and-a-day, but I'm no Rust veteran either. I need to wrap my head around the "Rust way" of doing things every time.
No need to build aws-lc-rs
, then Rustls
to get to Rustls-ffi
, just
build the thing, everything's self-contained.
Ultimately, the port does need cargo, but Rust has no concept of installing
libraries in any way. The Rustls-ffi package ships with a regular gmake
file for building and installing the static library. So I've had to
override the build and install make targets to make this work. The port
still depends on Rust via USES= rust
but this is merely for creation of
the dependent crates and running the extract/patch.
So now there's the security/rustls-ffi
port. All it produces is the static library lib/librustls.a
and the
header file include/rustls.h
.
Modifying the Apache port
Wiring things into the port for mod_tls
to build was quite trivial.
Other than adding the option, the option description, a dependency
on the freshly created rustls-ffi
port, and passing this on to apache
httpd's configure
. Add the mod_tls.so
to the pkg-plist conditionally
and "Bob's your uncle".
And it WORKS!
NOTE: To enable mod_tls, you need to enable the option for the port. It is not enabled by default since the Apache httpd project labels it as "experimental".
Adapting your Apache config for testing
As it says on the tin: you can have either mod_tls
or mod_ssl
enabled
on an IP:port combination.
If you make your config conditional, you should be able to switch between
your mod_ssl
and mod_tls
config.
<IfModule !tls_module>
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.org.pem
SSLCertificateKeyFile /etc/ssl/priv/example.org.pem
</IfModule>
<IfModule tls_module>
TLSEngine 443
TLSCertificate /etc/ssl/certs/example.org.pem /etc/ssl/priv/example.org.pem
</IfModule>
Do read the mod_tls
module documentation
for caveats and hints. I've settled on creating files in
${PREFIX}/etc/apache24/modules.d
to enable/disable modules and the server
level configuration for the module. So I have a file
${PREFIX}/etc/apache24/modules.d/002_mod_tls.conf
containing
# TLS v1.2 and v1.3 implemented in memory-safe Rust via the rustls library
#
# https://httpd.apache.org/docs/2.4/mod/mod_tls.html
<IfModule !ssl_module>
LoadModule tls_module libexec/apache24/mod_tls.so
<IfModule tls_module>
TLSEngine 443
TLSStrictSNI on
TLSCiphersSuppress TLS_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
</IfModule>
</IfModule>
and I control which module's used by commenting out the LoadModule line in
the modules.d/001_mod_ssl.conf
file that has a similar structure.
Using @icing's mod_md
module makes this
even simpler, expect a follow-up blog-post!