61 Commits

Author SHA1 Message Date
Wez Furlong 403f80ac26 simple_policy/sink: use temporary file for acct db
These files are used by me (wez!) while hacking things together locally
as a non-privileged user (myself).  They should not contribute to the
overall message accounting database.  Let's give each instantiation a
separate temporary path.
2024-03-28 07:14:35 -07:00
Wez Furlong 15b1fab110 checkpoint some local testing/hacking in my test configs 2024-03-27 16:33:17 -07:00
Wez Furlong 7ff5c4115e dkim helper: give a clearer error message when From: header is missing
Previously, we'd just generate an attempt to index `nil` error
message, and the result would be a 421 technical difficulties.

Promote this to a 522 with an explanation about the missing
From header.
2023-12-13 10:21:37 -07:00
Wez Furlong a03fcb2bf1 docs: fix sqlite auth example 2023-11-10 07:01:58 -07:00
Wez Furlong 929d51deba events: plumbing for registering multiple handlers
Previously, we'd restrict `kumo.on` to allowing just a single
instance of an event to be registered. The purpose of this was
to help surface logical errors where copypasta would result in
a bogus configuration.

With multiple helper lua modules now wanting to take responsibility
for some portion of the event handling, it is becoming more complex
to stitch things together.

It is desirable to allow multiple handlers for certain events,
so that a module can handle just its area of responsibility
without worry other modules about it.

This commit introduces a CallbackSignature type that allows
defining the function signature for event callbacks.

The signature can be pre-created and registered ahead of setting
up any lua contexts, which allows declaring whether an event
can have multiple callbacks registered.

The `get_queue_config` event handler has been set to allow multiple
callbacks.
2023-11-02 18:11:17 -07:00
Wez Furlong 4c36489681 First pass at accounting db
This keeps track of the volume of receptions and deliveries over time.
2023-10-12 20:43:58 -04:00
Wez Furlong 3b10d637f9 docs: show how to use dkim verification
refs: https://github.com/KumoCorp/kumomta/issues/82
2023-09-14 13:03:41 -07:00
Wez Furlong 06bb8d0492 add msg:add_authentication_results
This method will prepend an Authentication-Results header
to the message with the specified set of results and
local server name.

We need a more convenient way to default the server name;
ideally we'd pick this up from the listener, but that is currently
awkward in the policy.

refs: https://github.com/KumoCorp/kumomta/issues/82
2023-09-14 13:03:41 -07:00
Wez Furlong e4bb5d674d add msg:dkim_verify()
This method returns an array of AuthenticationResult reflecting
the verification status.

refs: https://github.com/KumoCorp/kumomta/issues/82
2023-09-14 13:03:41 -07:00
Wez Furlong 0b21193b8a add msg:check_fix_conformance()
This is for check and/or fixing message conformance issues.
2023-08-29 16:18:59 -07:00
Wez Furlong a6a711e72f simple_policy: remove rollup from testing policy 2023-08-11 12:36:54 -07:00
Wez Furlong 67b71a8b83 policy-extras: add rollup.lua
This is a prototype of a means for dealing with rolling up microsoft's
domains so that shaping can be applied holistically over both eg:
hotmail.com and outlook.com.

Those domains don't work with our default automatic MX based rollup
because they don't return the same MX hostnames.

Checking this in to make it easier for others to test/evaluate.
In the future, we may find a way to integrate this with our main
shaping helpers.
2023-08-10 11:48:07 -07:00
Wez Furlong 3fd76dd45a introduce routing_domain concept
Augments our queue name format to be
`campaign:tenant@domain!routing_domain`.

The routing_domain is optional.  If the routing_domain is not set, its
effective value is that of the recipient domain.

You can `msg:set_meta('routing_domain', 'bar.com')` to set the
routing_domain for a message, so if the original recipient was
`user@foo.com`, that would cause the computed queue name for it to be
`foo.com!bar.com`.

The routing_domain is used when deciding on the ready_queue name
and destination MXs, so continuing our example, instead of resolving
`foo.com` MX records we'd resolve `bar.com` and deliver to that site.

The `get_egress_path_config` event `domain` parameter is redefined to be
the effective `routing_domain`.

The `get_queue_config` event `domain` parameter is the regular recipient
domain. The `routing_domain` is not currently made available to
`get_queue_config`. If/when we expose it, it will likely be via a
queue name object instead of adding an additional parameter. That would
be a breaking change.

The consequence of not exposing this parameter is that per-message
routing scenarios for the same domain (but different routing domains)
cannot vary the scheduled queue parmeters (eg: retry intervals). Even
though they would have separate scheduled queue instances, those
instances would have the same scheduled queue parameters.  If you need
to be able to do that, then explicitly setting the domain portion of the
queue name would be a way to do that: `msg:set_meta('queue',
'foo.com-via-bar.com!bar.com')`.  `get_queue_config` would then be
called with `domain='foo.com-via-bar.com'` and your policy could then
respond accordingly.
2023-08-10 08:43:20 -07:00
Wez Furlong 8b2584f0f3 simple_policy.lua: tweak data timeouts 2023-06-22 13:25:35 -07:00
Wez Furlong 45c5d011d1 simple_policy.lua: s/max_connections/connection_limit/
use the correct name for this field
2023-06-16 08:47:33 -07:00
Wez Furlong b7c557c31a define_egress_(pool|source) -> make_egress_(pool|source)
Switch the configuration plumbing for pools and sources to be pull-based
rather than push based.

In other words, rather than defining them in the `init` event,
you now need to supply them to the new `get_egress_pool` and
`get_egress_source` events.

Data is cached by default for 1 minute. This allows for new sources
to come into being on-demand, and for data to age out and change
over time, without requiring that the server be restarted.

This commit updates the reference section, but there is some content
in the user guide that refers to the old style of configuration that
will need to be updated.

refs: https://github.com/KumoCorp/kumomta/issues/13
2023-05-30 14:08:07 -07:00
Wez Furlong 278bc81aa0 move shaping -> policy-extras/shaping, and deploy with package
The assets/policy-extras dir is now deployed to
`/opt/kumomta/share/policy-extras` and added to the require path,
so you can do:

```lua
local shaping = require 'policy-extras.shaping'
```

to pull it into your policy.
2023-04-26 14:51:52 -07:00
Wez Furlong b3f3f877df add functions for working with address headers 2023-03-14 18:53:47 -07:00
Wez Furlong 269e0702b4 add SMTP AUTH PLAIN support
Verified via:

```
swaks ... --auth plain --tls --auth-user scott --auth-password tiger
```
2023-03-11 16:23:49 -07:00
Wez Furlong 92a5509af5 update simple_policy for changes to the dkim vault parameters 2023-03-07 14:52:36 -07:00
Wez Furlong 7054fb31c9 switch to using human time for the queue related time intervals 2023-03-06 19:33:05 -07:00
Wez Furlong 00c253a9dd add maildir support
This is to facilitate end-to-end testing to validate that the
right bits come out at the end.
2023-03-06 19:05:49 -07:00
Wez Furlong 30e64c577f tweak simple policy to show sqlite usage for auth 2023-03-06 12:35:25 -07:00
Wez Furlong 0ca585bd5a Optionally use redis for throttles 2023-03-05 10:39:56 -07:00
Wez Furlong 52f7ab6150 add prohibited_hosts and skip_hosts for outbound resolving
While in that part of the code, handle null MX destination domains
(such as `example.com) more nicely.
2023-03-04 10:09:17 -07:00
Wez Furlong 7d76b3d9d7 add support for retrieving signing keys from hashicorp vault 2023-03-03 10:32:16 -07:00
Wez Furlong 35d90a72ab undo changes to simple_policy.lua
I'm not sure if these were intended to be committed, but
back them out so that they don't collide with my testing!
2023-03-01 16:23:45 -07:00
Wez Furlong c7a8405ddf fix code formatting 2023-03-01 09:45:22 -07:00
Wez Furlong 2b0ba702cb add scheduling constraints
This is implemented by allowing the Message:set_due method to
load the message metadata to consult the scheduling constraints,
which should mean that all scheduling updates have the constraints
applied to them.
2023-03-01 09:43:48 -07:00
Tom Mairs 2699111362 fixed page order in guide 2023-03-01 07:45:09 +00:00
Wez Furlong 557fff650d implement max_deliveries_per_connection 2023-02-28 15:12:15 -07:00
Wez Furlong c275c696ff implement message and connection rate throttles
These use the local/in-process throttles.
Seems to work in my very light testing so far.
2023-02-28 13:56:58 -07:00
Wez Furlong 9ab1727792 rename: dest_site -> egress path 2023-02-28 09:56:20 -07:00
Wez Furlong 327aef76d3 implement binding to a source address
The source address is defined by the egress source
2023-02-28 09:44:08 -07:00
Wez Furlong 93ff9e1991 adjust dest_site to queue based on source->site
There needs to be another pass over this for naming,
but this brings us closer to the state shown in the
diagram in the readme.
2023-02-28 06:29:26 -07:00
Wez Furlong 9338de3d06 delay ready queue when target site is persistently unavailable
Tidy up the logging around this; move some error logs to debug level,
especially since we log message events to the log file for that purpose;
there is no need to log errors to the console for this.
2023-02-26 22:26:03 -07:00
Wez Furlong 51d9928ead docs: add more reference content 2023-02-25 20:41:50 -07:00
Wez Furlong 79ff6354c7 format 2023-02-24 10:53:17 -07:00
Wez Furlong 12f1637087 http: add https and some plumbing for auth
* Reuse the tls acceptor stuff from the smtp_server.
  We'll automatically generate self-signed certs when
  none are provided.
* Add trusted_hosts setting for the http server
* Add an auth middleware that will accept connections from
  trusted hosts as pre-authenticated. Other hosts must provide
  http authorization.
* Add lua hooks for the policy script to validate either http
  basic auth (user+pass), or bearer auth (token).

There's not currently an authentication storage subsystem, but
the lua hook allows for very basic stuff to be configured, and
could also be used to employ eg: looking things up from a database
once we add some lua utility functions for that purpose.

The `/metrics` endpoint will only respond to trusted IPs.

Other endpoints all require some kind of successful authentication.
2023-02-24 10:47:06 -07:00
Wez Furlong 5438824ef3 smtp_server: add reception limits
allow limiting the number of messages and the number of recipients
that come in on a single connection
2023-02-22 23:12:39 -07:00
Wez Furlong bcd4a6fc6d take a crack at logging receptions and deliveries 2023-02-22 11:57:26 -07:00
Wez Furlong 5cfb086fed spool: remove sled
It's beta and rocksdb performs better; there's not a compelling
reason to retain it until it stabilizes.
2023-02-21 21:28:36 -07:00
Wez Furlong b25ff76118 add dkim signing
A fairly sprawling commit:

* Move config to its own crate to facilitate making things more modular
* Crates/modules can now provide a registration function that can be
  used to setup functions in the lua environment
* Message crate now has a dkim module with a signer type that can
  be loaded from lua; signers are cached (with ttl) and shareable
* Message now has a dkim_sign method that does the signing, as well
  as methods for appending and prepending headers that are necessary
  to support signing.
2023-02-21 21:18:49 -07:00
Wez Furlong ed8aa53d55 Add RocksDB as a spool option
Looks pretty good compared to Sled.

|kind         | flush | throughput |
+-------------+-------+------------+
|RocksDB      | false | 102mm/hr   |
|RocksDB      | true  | 96mm/hr    | *
|Sled         | false | 96mm/hr    |
|Sled         | true  | 34mm/hr    |
|LocalDisk    | false | 24mm/hr    |
|LocalDisk    | true  | 1mm/hr     |

These numbers are from a 5950x (32 core) with an nvme drive,
as reported by:

```
cargo run --release -p traffic-gen -- --target 127.0.0.1:2025 --duration 20 --concurrency 16024
```

Note that the flush implementation with rocksdb just adjusts the setting
of use_fsync when opening the database.

There is an explicit db-wide flush that can be called, but it is very
aggressive and thorougly tanks performance down to 0.25mm/hr.

Note as well that rocksdb has a number of configuration options that may
work better as a write-once spool than the currently selected defaults;
more analysis could be done, but at the time of writing this commit
message, the defaults are the best performing storage option and going
further isn't a priority.
2023-02-20 23:04:01 -07:00
Wez Furlong 973a3b6f10 spool: add Sled as an alternative local spool
Add a `kind` and `flush` fields when defining a spool.  Add a new
[sled](https://docs.rs/sled/latest/sled/index.html) based spool
implementation.

Initial benchmarking, especially at high concurrency, shows
promising numbers:

|kind         | flush | throughput |
+-------------+-------+------------+
|Sled         | false | 96mm/hr    |
|Sled         | true  | 34mm/hr    |
|LocalDisk    | false | 24mm/hr    |
|LocalDisk    | true  | 1mm/hr     |

These numbers are from a 5950x (32 core) with an nvme drive,
as reported by:

```
cargo run --release -p traffic-gen -- --target 127.0.0.1:2025 --duration 20 --concurrency 16024
```

What's the catch? sled is considered beta by its authors.
https://github.com/spacejam/sled#known-issues-warnings
2023-02-20 22:08:05 -07:00
Wez Furlong d944246595 remove a bottleneck, add deferred spool mode
During DATA, spawn the queue resolve and insertion into a separate
task so that we can respond to the injection with lower latency.
2023-02-20 13:52:04 -07:00
Wez Furlong caf47d4c4e add traffic generator 2023-02-20 10:30:58 -07:00
Wez Furlong e1e96b3931 tidy up some debug logging 2023-02-19 08:31:21 -07:00
Wez Furlong 9812eef7ac add prometheus metrics export
This commit adds in an http listener that provides a `/metrics`
endpoint that can be configured as a target by prometheus to
scrape and record metrics.

You may also curl it for yourself.

While playing around with this, I found and fixed a deadlock
in the case that the initial spool in logic found and expired
a message; it would reuse a helper function that wanted to acquire
a lock, but it already held the lock.
2023-02-19 00:17:58 -07:00
Wez Furlong 54e230ffca message expiration
* Switch uuids to v1 format, so that we can cheaply determine
  when a message was created without having to load its metadata
  from the spool
* Add some message delivery parameters; retry interval, limit, max age
* Respect those parameters when spooling in and when we encounter
  a transient failure.
2023-02-18 14:39:54 -07:00