February 2021: nooSMTPD libtls-conversion, ciphers, curves and protocols
TL;DR: I converted nooSMTPD to libtls and implemented SMTP ciphers, curves and protocols selection.
Shout outs to my patrons !
Let’s start with some LoFi
I have a youtube channel (subscribe ! now !)
Nothing new in OpenSMTPD-portable
eric@ sent a libtls-conversion diff to
tech@ last month but there hasn’t been much progress since then.
I tested the diff extensively and I’m currently waiting for it to be merged to OpenBSD so I can bring it to OpenSMTPD-portable.
nooSMTPD is libtls-enabled
In nooSMTPD, I did the libtls-conversion by applying the diff and making the appropriate changes to the libtls compat layer.
I switched my machines from my custom FrankenOpenSMTPD to nooSMTPD and been running it since late January, with no regressions.
It’s interesting to note that while I ran OpenSMTPD from upstream repository without the autoconf build, I’m running nooSMTPD from autoconf which led to a lot of swearing as it was never meant to be used on OpenBSD. I fixed a few unpleasant things which I’ll be able to push to OpenSMTPD-portable as well.
smtp tls global configuration
OpenSMTPD allows setting up SMTP global configuration with the
smtp global keyword:
smtp max-message-size "30M" smtp sub-addr-delim "+"
Because it may be desireable to setup an alternate list of ciphers,
ciphers keyword was introduced a long time ago and a global option allows overriding the default ciphers:
smtp ciphers "HIGH:!aNULL:!MD5"
I decided to introduce the
tls keyword for TLS related options.
The libtls conversion unlocks several TLS-related features that may be confusing below
without any reference to TLS.
I have implemented TLS protocol selection and unless
tls appears in the configuration this will result in:
smtp protocols [...]
which is much more confusing than:
smtp tls protocols [...]
as it is unclear that the protocols are TLS related.
As a result,
smtp tls so in nooSMTPD it reads as:
smtp tls ciphers "HIGH:!aNULL:!MD5"
I’ll suggest this change to OpenSMTPD too.
TLS ciphers selection
As mentionned above,
I have changed the grammar to introduce a
tls namespace to the
smtp tls ciphers "HIGH:!aNULL:!MD5"
Because libtls supports cipher suite groups,
insecure groups can be used in place of a cipher suite,
secure is the default,
the global cipher selection only needs to be specified for other cases:
smtp tls ciphers "compat"
With this done, I also added the ability to setup the ciphers at the listener level:
listen on 0.0.0.0 tls ciphers "compat" listen on 192.168.0.1 tls ciphers "legacy" # use on legacy subnet
This was committed to nooSMTPD and I’ll submit a diff to OpenSMPTD when libtls-conversion is done upstream.
TLS curves selection
The selection of curves was never merged in OpenSMTPD,
as a result it is not possible to select specific curves at either one of the global or listener level.
The default curves (
X25519,P-256,P-384) in libtls are sensible choices but some use-cases require restricting to a specific curve,
or even an alternate one.
I introduced a
curves option which allows specifying curves to override the default:
smtp tls curves "X25519"
While at it, I added the ability to setup the curves at the listener level:
listen on 0.0.0.0 tls ciphers "X25519" listen on 192.168.0.1 tls curves "P-256,P-384"
This was committed to nooSMTPD and I’ll also submit a diff to OpenSMPTD when libtls-conversion is done upstream.
TLS protocols selection
Just like for curves, the selection of a TLS protocol was never merged in OpenSMTPD.
I introduce a
protocols option which allows specifiying protocols to override the default:
smtp tls protocols "tlsv1.3:tlsv1.2"
And again, I added the ability to setup the protocol at the listener level:
listen on 0.0.0.0 tls protocols "tlsv1.3"
Guess what… Yes, this was also committed to nooSMTPD and I’ll submit a diff to OpenSMPTD when libtls-conversion is done upstream.
smtp tls grammar needs to be reworked
smtp tls keyword was implemented as a placeholder for the
but it was not implemented the way it should.
protocols should be options to
tls so that it is possible to write:
smtp tls ciphers "secure" protocols "secure"
At the time being, this is not possible and it must be expressed as follows:
smtp tls ciphers "secure" smtp tls protocols "secure"
This requires a bit of grammar refactor which I’ll be working on in March.
tls grammar was reworked
tls keyword suffered from the same issue as the global
smtp tls keyword.
it was implemented in such a way that
protocols were standalone options.
This allowed avoiding the need to repeat
tls before every option,
you needed one
tls on the listener so it was flagged as TLS-enabled and the options would check for the flag.
This worked but it was not the right way to do it.
I reworked the grammar for
tls in listeners so that
This avoids having to repeat
tls before every keyword,
and it allows relying on the grammar rather than on a flag to determine if the configuration is valid:
listen on 0.0.0.0 tls ciphers "secure" curves "P-256,P-384" protocols "secure"
I’m happy with the result.
What’s next ?
I will rework the grammar for global settings and will implement these options for the MTA layer, as these options were done only for the incoming path.
I intend to publish a technical article in March regarding software design and data.
I might unveil a project that’s unrelated to computer programming too :-)