Haraka
Haraka copied to clipboard
Feature request: Expose SNICallback as a plugin hook
This would enable plugin-managed vanity MX domain names. There could be a plugin hook that is run on SNICallback. If the hook returns a secure context object then use it, otherwise go with the default.
I use such a system with WildDuck IMAP and ZoneMta MSA servers - there is a central certificate system that manages and renews Let’s Encrypt certificates. Whenever a SNI connection is established the certificate is pulled from that central system instead of using fixed certificates stored on disk.
a PR is welcome. I've looked at your TLS work and you did a nicer job than we have.
I tried to do something like this but ran into an obstacle. In general what I'd like the SNICallback to look like would be something like this:
function SNICallback (servername, sniDone) {
plugins.run_hooks('sni', pluginObject, ( ctx )=>{
if (ctx){
return sniDone(null, ctx);
}
if (ctxByHost[servername] === undefined) servername = '*';
sniDone(null, ctxByHost[servername]);
});
}
The problem is I can't figure out what to use as the plugin object? SNICallback method has no bound context.
SNICallback method has no bound context.
I recall running into this issue when I added SNI support and the ability to support more than one TLS certificate. IIRC, the reason there's no bound context is because plugins are run in node's vm.runInNewContext. That early design choice has proven to be a thorn in our side for ages. I worked around it by moving nearly all the TLS bits out of the plugin and into tls_socket.js. I figured it was just a matter of time before plugins/tls
disappeared entirely.
+1 on this. We are using a modified version of tls_socket.js to be able to dynamically load certs from a http/redis backend based on SNI but having that on a plugin would be awesome.
A currently open PR exports SNICallback
from tls_socket. (It also cleans up that file significantly, but that's a different issue). certsByHost
was already exported. That same open PR turns certsByHost
into a haraka-note but that's mostly just cleaning up JS object get/set safeguards.
Plugins have access to haraka_require
, so they can do crazy like const tls_socket = haraka_require('tls_socket')
.
Now, this isn't an endorsement or anything, but that should make it possible to:
exports.register = function () {
const tls_socket = haraka_require('tls_socket')
tls_socket.SNICallback = (servername, sniDone) => {
// do some stuff
sniDone(null, context)
}
}
moved to wiki/TODO