haraka / Haraka

A fast, highly extensible, and event driven SMTP server
https://haraka.github.io
MIT License
5.01k stars 661 forks source link

Disable outbound delivery #1873

Closed thetrompf closed 7 years ago

thetrompf commented 7 years ago

Hi I'm trying to implement an email journaling system, where I would like to queue up incoming mails to a rabbitMQ queue and process the mails with another system, but I don't want any outbound capabilities.

The communication between the other SMTP server (which sends the journals) and Haraka is encrypted via TLS. I use GMail's SMTP server for sending the journals for all the company emails.

My question is, how do I go by implementing this, is it already possible with Haraka core or with existing plugins, or will I have to write my own plugin(s) for this, and if that's the case, where should I "hook" in?

Thanks in advance.

thetrompf commented 7 years ago

After a little digging I have found a solution, but it feels pretty hacky.

Due to restrictions in connection.js https://github.com/haraka/Haraka/blob/cc508cb3d44f728d99f86996cb66e16d12e398e4/connection.js#L1316-L1319 relaying must be enabled when binding to 465 or 587 (TLS ports). Since I want TLS to be enabled, I must enable relaying as well, but I don't want to send anything outbound, so I have to disable relaying again as soon as possible after the "Authentication required" check.

So If I hook into the mail hook and disable relaying there, no mails will be send outbound, and no other plugins will pick up on relaying was enabled in the first place.

exports.register = function () {
    var plugin = this;
    plugin.register_hook('connect', 'enable_relaying');
    plugin.register_hook('mail', 'disable_relaying');
};

// We fake that we want to relay, to bypass
// the authentication required step upon connection.
// We don't want to setup any authentication.
exports.enable_relaying = function(next, connection) {
    connection.relaying = true;
    return next(CONT);
};

// We disable relaying right after connect is done.
// So we do it in the mail hook which is the on right after connect.
// This is important so other plugins and hooks don't pick up on
// relaying is enabled and possibly change their behavior.
exports.disable_relaying = function(next, connection) {
    connection.relaying = false;
    return next(CONT);
}

Again this feels pretty hacky, so I ask if there is an easier way?

msimerson commented 7 years ago
thetrompf commented 7 years ago

Will you suggest this hypothetical option should allow bypassing the "Authentication required" check in connection?

msimerson commented 7 years ago

Exactly. Relaying is just a proxy for AUTH, so wrap that relaying/auth check in connection.js with:

if (server.cfg.msa_requires_auth) {
    // Require authentication on connections to port 587 & 465
}

Then make sure to add that new option to the booleans declaration in server.js where it loads smtp.ini, with a default of true (so that it doesn't inadvertently disable that feature for upgrades where that setting is missing from their smtp.ini file), and then your good to go.

chasent commented 7 years ago

I've run into this as well. I bypassed this in my setup by just removing that block. The solution @msimerson proposed is probably a better idea as I'm not sure what it is the check is accomplishing. I will write up pull request when I get the chance. 😄

msimerson commented 7 years ago

There's no good reason for remotes to be sending email via port 465 and 587 on your server unless they are the MUA's of your users that have local relay privileges. That check mandates that connections to port 465 and 587 have relaying privileges, either via IP relay or SMTP AUTH.

msimerson commented 7 years ago

Closing due to lack of activity. The current behavior suites the needs of the vast majority of users so it's unlikely @haraka/core is going to implement this. However, should someone want this feature, PRs that include test coverage for the changes are welcome.