Commit Graph
121 Commits
Author SHA1 Message Date
Wez Furlong 722876a144 first pass at memory awareness
This commit introduces awareness of memory limits that may
have been established for the process.

The idea is that the hard/soft limits are read from the active
cgroup, falling back to classic ulimit hard/soft limits, falling
back to the system RAM size.

In the absence of an explicitly configured hard limit, the RAM size
is used for the hard limit.

In the absence of an explicitly configured soft limit, 75% of the
hard limit is used for the soft limit.

A background thread monitors the memory usage and (potentially
adjusted) memory limits.

A low memory state is when the usage is within 10% of the soft limit.
In this state, we start to trim back memory usage, shrinking loaded
data when messages are placed into the ready queue.

A more severe memory state is when the usage exceeds the soft limit.
In this state, new message reception is rejected until the usage
recovers.

kumod doesn't do anything directly with the hard limit, but assumes
that the system will terminate the process with no opportunity to
safely clean up if that value is reached.

In order to reduce the memory usage, the allocator has been switched
to jemalloc which has superior management of fragmentation and
a control interface to request release of various memory caches.

We make use of jemalloc specific functions in the tokio thread pools;
when they park (idle), we release the thread local cache, and when
we reach the soft limit we aggressively flush the caches until
memory usage falls below the limit.

There's like some room for tuning of the thresholds around this,
but this is a reasonable start.

Note that there are no explicit config options in kumod to set
the soft and hard limits: those are taken from the process
environment and can be simply set either via ulimit in a calling
shell script, or via systemd service configuration.

We may introduce some knobs for the low memory state threshold
in the future.
2023-03-09 18:50:24 -07:00
Wez Furlong 4cd913e7bf improve some error handling; enable printing panics, capture core
and report non-zero exit status if initialization failed
2023-03-08 18:15:31 -07:00
Wez Furlong 50a123a0e3 Add version info to kumod 2023-03-08 17:38:15 -07:00
Wez Furlong 55d3343ac5 config: implement pooling of lua contexts
and export some counters so that we can see into their usage
2023-03-08 16:53:04 -07:00
Wez Furlong 8152c0c24a traffic-gen: allow configuring message size, message count 2023-03-08 16:53:04 -07:00
Wez Furlong b458bbced1 refactor integration testing to make it a bit easier to use
Helpers for generating messages, summarizing deliveries,
reducing boilerplate in the tests themselves.

Add SMTP line length test.
2023-03-08 10:32:01 -07:00
Wez Furlong 1d485d9fba dump delivery logs in integration test 2023-03-07 20:20:13 -07:00
Wez Furlong 257dc4a25a flesh out integration testing some more
This has our first end-to-end integration test that validates
smtp -> source mta -> sink mta -> maildir
and confirms that the message has the right bits inside it.

The end to end test will get refactored into more easily usable
pieces in follow-up commit(s).
2023-03-07 18:42:14 -07:00
Wez Furlong 51d1408aa6 scaffolding for integration tests 2023-03-07 14:54:19 -07:00
Wez Furlong 6d23055570 deps: update to revised maildir PR 2023-03-07 07:20:57 -07:00
Wez Furlong 3e203eb0d1 switch to my redis-cell fork to avoid shared object in the build 2023-03-07 06:47:17 -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 af327d7e21 add tokio-console support
We don't show much of anything at the moment; will need to make
a pass through and instrument a bunch of things
2023-03-06 07:53:27 -07:00
Wez Furlong 4ae2c1abca allow redirecting diagnostic logs to a log directory
While in there, expose a few options for the logging format
2023-03-06 07:41:43 -07:00
Wez Furlong 0ca585bd5a Optionally use redis for throttles 2023-03-05 10:39:56 -07:00
Wez Furlong eaaddbb6b6 add redis client 2023-03-05 09:57:03 -07:00
Wez Furlong 2cf3d2387c add sqlite data access
A bit of a big commit because I wanted sqlite queries to run
async and there isn't a sane way to tell in mlua whether a
given context is safe to yield for an await, which meant making
every case where we call into lua be fully async.

This adds a simple but powerful binding to sqlite that performs
its IO in a blocking tokio thread pool, and returns the results
back to lua.

There is no implicit caching of queries, and no implicit connection
pooling.
2023-03-04 18:07:31 -07:00
Wez Furlong c184214253 allow loading TLS key+cert from hashicorp vault
refactor to allow reusing the same key loader logic for dkim, smtp
and http.
2023-03-04 11:01:35 -07:00
Wez Furlong 6204642270 add trace headers configuration and link to ARF parsing 2023-03-04 07:22:02 -07:00
Wez Furlong 7d76b3d9d7 add support for retrieving signing keys from hashicorp vault 2023-03-03 10:32:16 -07:00
Wez Furlong f0909804a4 traffic-gen: allow loading the body from a file 2023-03-03 07:32:17 -07:00
Wez Furlong ef7fa59355 synthesize OOB log records from OOB reports
* When logging the reception of a message, if we can parse it
  as an rfc3464 oob report, then synthesize OOB records for
  each recipient
* Add config to allow relaying for domains for which bounces
  are received, so that we can accept their message content.
* If the domain config allows bounces but not relaying, then
  the message will not be spooled or queued after reception;
  it will be dropped with no additional logging.
2023-03-03 06:53:33 -07:00
Wez Furlong d5b13a263b Add kumo.configure_bounce_classifier
and connect it to the logger
2023-03-02 08:59:03 -07:00
Wez Furlong 74635be9fb Add extensible bounce classifier
The classifier can load and merge rules from multiple files.
A basic iana enhanced status codes ruleset is provided.
A deployment can define their own to augment that set.

This commit is just the core classifier functionality; it
is not yet connected to kumod.

The classification enum is a bit of an amalgam of categories
defined by other well-known vendors/products and the categories
defined by IANA.  Some classifications have no corresponding
rules at the current time.
2023-03-02 08:27:32 -07:00
Wez Furlong cd7ba3a2bb make smtp client timeouts configurable by command 2023-03-01 12:19:45 -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
Wez Furlong 39e08d602b add scheduling restriction datatype
This will be used in the future to adjust the message
sending schedule on a per-message basis.
2023-03-01 09:43:48 -07:00
Wez Furlong 2f63c24409 refactor: move MX resolution to its own module 2023-02-28 08:42:39 -07:00
Wez Furlong 006e166afb define some types that will manage egress configuration 2023-02-27 19:05:20 -07:00
Wez Furlong 6ec25431aa add ThrottleSpec type
This will be used in the config
2023-02-27 19:05:20 -07:00
Wez Furlong a65863bfc4 add throttle crate
This currently uses in-memory only throttles, but it uses literally
the same code that is used to implement the redis-cell based solution
we're planning to hit for sharing throttles across a cluster,
so it should be a fairly easy future code change to make it do that,
with no change in semantics.
2023-02-27 19:05:20 -07:00
Wez Furlong 6dfb44012e add some header manipulation functions 2023-02-26 15:01:05 -07:00
Wez Furlong c1849551ed http injector: make a first pass at it
Still needs to call out to lua for routing and meta updates.
May need to parallelize the generation stage if throughput
isn't where we want it to be.
2023-02-25 10:12:07 -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 daf3b87753 add num_attempts field, and zstd compress the logs
I don't plan to remove compression or to allow it to be disabled: it
makes a massive difference to the size of the log files and saves IO and
storage space.
2023-02-22 12:33:58 -07:00
Wez Furlong bcd4a6fc6d take a crack at logging receptions and deliveries 2023-02-22 11:57:26 -07:00
Wez Furlong 1cd30161e7 Allow starting as root in order to bind to port 25
We require that `--user username` be passed and specify
the user id that we should assume instead of running as
root.

We do the magic setup needed to preserve the ability
to bind to port 25 while dropping the other privs.
2023-02-21 22:38:51 -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 c049277d61 parallelize writing spool and metadata when saving the message 2023-02-20 18:21:24 -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 f8fc4582fc add counters for messages in different states 2023-02-19 15:39:51 -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 d88ae59c5c allow setting tls certificate and key for smtp listener 2023-02-18 18:13:31 -07:00
Wez Furlong 7336481e02 use OnceCell to init tls params once and share them 2023-02-18 18:00:44 -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