1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-16 14:27:01 +00:00

dkim: Implement internal dkim signing and verification

This patch implements internal DKIM signing and verification.
This commit is contained in:
Alberto Bertogli
2024-02-10 23:55:05 +00:00
parent f13fdf0ac8
commit 76a72367ae
90 changed files with 4902 additions and 112 deletions

View File

@@ -1,70 +1,90 @@
# DKIM integration
[chasquid] supports generating [DKIM] signatures via the [hooks](hooks.md)
mechanism.
[chasquid] supports verifying and generating [DKIM] signatures since version
1.14.
All incoming email is verified, and *authenticated* emails for domains which
have a private DKIM key set up will be signed.
In versions older than 1.13, support is possible via the [hooks] mechanism. In
particular, the [example hook] included support for some command-line
implementations. That continues to be an option, especially if customization
is needed.
## Signing
## Easy setup
The [example hook] includes integration with [driusan/dkim] and [dkimpy], and
assumes the following:
- Run `chasquid-util dkim-keygen DOMAIN` to generate a DKIM private key for
your domain. The file will be in `/etc/chasquid/domains/DOMAIN/dkim:*.pem`.
- Publish the DKIM DNS record which was shown by the
previous command (e.g. by following
[this guide](https://support.dnsimple.com/articles/dkim-record/)).
- Change the key file's permissions, to ensure it is readable by chasquid (and
nobody else).
- Restart chasquid.
- The [selector](https://tools.ietf.org/html/rfc6376#section-3.1) for a domain
can be found in the file `domains/$DOMAIN/dkim_selector`.
- The private key to use for signing can be found in the file
`certs/$DOMAIN/dkim_privkey.pem`.
Only authenticated email will be signed.
It is highly recommended that you use a DKIM checker (like
[Learn DMARC](https://www.learndmarc.com/)) to confirm that your setup is
fully functional.
### Setup with [driusan/dkim]
## Advanced setup
1. Install the [driusan/dkim] tools with something like the following (adjust
to your local environment):
You need to place the PEM-encoded private key in the domain config directory,
with a name like `dkim:SELECTOR.pem`, where `SELECTOR` is the selector string.
```
for i in dkimsign dkimverify dkimkeygen; do
go get github.com/driusan/dkim/cmd/$i
go install github.com/driusan/dkim/cmd/$i
done
sudo cp ~/go/bin/{dkimsign,dkimverify,dkimkeygen} /usr/local/bin
```
It needs to be either RSA or Ed25519.
1. Generate the domain key for your domain using `dkimkeygen`.
1. Publish the DNS record from `dns.txt`
([guide](https://support.dnsimple.com/articles/dkim-record/)).
1. Write the selector you chose to `domains/$DOMAIN/dkim_selector`.
1. Copy `private.pem` to `/etc/chasquid/certs/$DOMAIN/dkim_privkey.pem`.
1. Verify the setup using one of the publicly available tools, like
[mail-tester](https://www.mail-tester.com/spf-dkim-check).
### Key rotation
To rotate a key, you can remove the old key file, and generate a new one as
per the previous step.
It is important to remove the old key from the directory, because chasquid
will use *all* the keys in it.
You should use a different selector each time. If you don't specify a
selector when using `chasquid-util dkim-keygen`, the current date will be
used, which is a safe default to prevent accidental reuse.
### Setup with [dkimpy]
### Multiple keys
1. Install [dkimpy] with `apt install python3-dkim` or the equivalent for your
environment.
1. Generate the domain key for your domain using `dknewkey dkim`.
1. Publish the DNS record from `dkim.dns`
([guide](https://support.dnsimple.com/articles/dkim-record/)).
1. Write the selector you chose to `domains/$DOMAIN/dkim_selector`.
1. Copy `dkim.key` to `/etc/chasquid/certs/$DOMAIN/dkim_privkey.pem`.
1. Verify the setup using one of the publicly available tools, like
[mail-tester](https://www.mail-tester.com/spf-dkim-check).
Advanced users may want to sign outgoing mail with multiple keys (e.g. to
support multiple signing algorithms).
This is well supported: chasquid will sign email with all keys it find that
match `dkim:*.pem` in a domain directory.
## Verification
Verifying signatures is technically supported as well, and can be done in the
same hook. However, it's not recommended for SMTP servers to reject mail on
verification failures
[chasquid] will verify all DKIM signatures of incoming mail, and record the
results in an [`Authentication-Results:`] header, as per [RFC 8601].
Note that emails will *not* be rejected even if they fail verification, as
this is not recommended
([source 1](https://tools.ietf.org/html/rfc6376#section-6.3),
[source 2](https://tools.ietf.org/html/rfc7601#section-2.7.1)), so it is not
included in the example.
[source 2](https://tools.ietf.org/html/rfc7601#section-2.7.1)).
## Other implementations
[chasquid] also supports [DKIM] via the [hooks] mechanism. This can be useful
if more customization is needed.
Implementations that have been tried:
- [driusan/dkim]
- [dkimpy]
[chasquid]: https://blitiri.com.ar/p/chasquid
[DKIM]: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
[hooks]: hooks.md
[example hook]: https://blitiri.com.ar/git/r/chasquid/b/next/t/etc/chasquid/hooks/f=post-data.html
[driusan/dkim]: https://github.com/driusan/dkim
[dkimpy]: https://launchpad.net/dkimpy/
[RFC 8601]: https://datatracker.ietf.org/doc/html/rfc8601
[`Authentication-Results:`]: https://en.wikipedia.org/wiki/Email_authentication#Authentication-Results

View File

@@ -53,6 +53,18 @@ List of exported variables:
- **chasquid/smtpIn/commandCount** (map of command -> count)
count of SMTP commands received, by command. Note that for unknown commands
we use `unknown<COMMAND>`.
- **chasquid/smtpIn/dkimSignErrors** (counter)
count of DKIM sign errors
- **chasquid/smtpIn/dkimSigned** (counter)
count of successful DKIM signs
- **chasquid/smtpIn/dkimVerifyErrors** (counter)
count of DKIM verification errors
- **chasquid/smtpIn/dkimVerifyFound** (counter)
count of messages with at least one DKIM signature
- **chasquid/smtpIn/dkimVerifyNotFound** (counter)
count of messages with no DKIM signatures
- **chasquid/smtpIn/dkimVerifyValid** (counter)
count of messages with at least one valid DKIM signature
- **chasquid/smtpIn/hookResults** (result -> counter)
count of hook invocations, by result.
- **chasquid/smtpIn/loopsDetected** (counter)