Husk

Documentation

Installation

Husk is written in Rust, so you need a recent rust toolchain to compile the source. If your distribution doesn't provide such a toolchain (or it is to old), you can get an up-to-date version from here.

To compile Husk from source, clone its repository and compile:

$ git clone https://gitlab.com/husk-project/husk-milter
$ cd husk-milter
$ cargo install --locked --path .

Configuration

The configuration file of Hust uses the toml format.

Husk is a milter, which means it's a background process (daemon) which listens on a TCP port for incomming requests. This port is configured under the name connection.

connection = "localhost:3000"

This example tells Husk to listen on 127.0.0.1 (localhost), port 3000. There is a corresponding configuration for the MTA, so that the MTA knows where to find Husk (see below).

Husk uses OpenPGP certificates for encryption. It needs a storage location for these certificates. As Husk uses Sequoia PGP, the name for this parameter is sequoia_home.

sequoia_home = "/var/lib/husk/"

Husk queries online sources for missing certificates. For WKD and DANE the URL of the online source is derived from the email. Keyservers have to be configured separately.

keyservers = [ "hkps://keys.openpgp.org/", "hkps://mail-api.proton.me" ]

Husk uses log4rs for logging. The configuration of log4rs is merged into the main configuration file under the node named logging. That means that you take a log4rs configuration and prepend logging to each section:

[logging.appenders.console]
kind = "console"
[logging.appenders.console.encoder]
pattern = "{d(%Y-%m-%d %H:%M:%S)(local)} {h({l})} [{t}] {m}{n}"

[logging.appenders.file]
kind = "file"
path = "/tmp/husk.log"

[logging.appenders.file.encoder]
pattern = "{d(%Y-%m-%d %H:%M:%S)(local)} {h({l})} [{t}] {m}{n}"

[logging.root]
level = "debug"
appenders = ["file"]

[logging.loggers."husk"]
level = "debug"

so that [appenders.console] becomes [logging.appenders.console] and so on.

If you do not specify any logging, Husk will default to log to the console.

Location

You can put the configuration file at any place and start Husk with

$ husk ... --config <LOCATION> ...

or use the default location /etc/husk/config.toml. In this case you can skip --config.

Configure postfix

This is a description on how to add Husk to the postfix MTA. If you want to use Husk with a different MTA, please refer to its documentation on how to add a milter.

For postfix you have to tell the MTA where it can find the milter port. The configuration entries are smtpd_milters and non_smtpd_milters.

smtpd_milters = inet:localhost:3000
non_smtpd_milters = $smtpd_milters

inet:localhost:3000 corresponds to the connection configuration parameter in the Husk configuration.

The example above configures non_smtpd_milters by using the setting of smtpd_milters (via the $ operator).

Please keep in mind that in case you configured multiple milters, the sequence is important, as Husk will change the content of the mail.

Usage

Husk has two aspects:

  • it can run as a background process
  • it can be used as a cli-tool for administrating the background process.

The CLI syntax follows the scheme NOUN (more NOUNs), VERB and then parameters. Like

$ husk introducer add --cert-file FILE --domains DOMAIN

or

$ husk daemon start --config config.toml

Husk includes a help system, which can be used by passing --help.

$ husk --help

or

$ husk introducer add --help

and so on. It shows you the available subcommands and parameters.

The daemon

The daemon is the background process which processes mails and encrypts them if possible. It has to be started separately, the MTA expects it to be reachable and doesn't start it on it's own.

Start the daemon

$ husk daemon start &

or use

$ husk daemon start --config /path/to/the/configuration/file.toml &
Currently you have to use '&' to move the process into the background.

Husk can (and should) run as an unprivileged process (keep in mind to use a port number above 1024 as ports below require a privileged process).

Use systemd

TBD

Introducers

For Husk to use a certificate for encryption, it has to be authenticated - meaning, that the user id of the certificate (usually an email address) is indeed the user id of the key holder of said certificate.

This authentication can only be done by humans, but once it's done, its result can be shared.

This is what an introducer does - it authenticates certificates and publishes the result in form of a certification which becomes part of the certificate.

Husk allows to use introducers to benefit from their work. At the same time, introducers are limited to a list of domains for which certifications are accepted. This is a restriction Husk imposes. The list of domains is specified by the administrator, not the introducer.

Add an introducer

To add an introducer you need its certificate and specify which domains certifications done with this certificate should be accepted.

$ husk introducer add --cert-file FILE --domains example.com

You can specify a list of domains by

... ---domains domain1 domains2 domain3

FILE must contain a valid certificate, not expired and not revoked.

In case you already added the certificate to Husk, you can promote it by using its fingerprint.

$ husk introducer add --cert FINGERPRINT --domains example.com 

List introducers

$ husk introducer list 

Remove an introducer

$ husk introducer remove --cert FINGERPRINT

If you remove an introducer, the certificate will stay in the certificate store - only it's special powers will be removed. You can reactivate an introducer by using husk introducer add --cert FINGERPRINT ..., if you accidentially removed one.

Locals

Locals are certificates which are added to Husk by the administrator and do not require to be introduced.

If you want to test Husk or want to use it only with a few dedicated certificates, you can skip creating an introducer and use locals.

Add Locals

$ husk locals add --cert-file FILE

FILE must contain a valid certificate, not expired and not revoked.

Locals can be promoted to introducers by using husk introducer add --cert FINGERPRINT ....

List locals

$ husk locals list

Remove locals

$ husk locals remove --cert FINGERPRINT

If you remove a local, its certificate will stay in the certificate store, but will be dormant.