mirror of
https://github.com/tildeclub/tilde.club.git
synced 2026-10-25 00:55:38 +00:00
181 lines
8.8 KiB
Markdown
181 lines
8.8 KiB
Markdown
# Mail
|
|||
|
|
|
||
|
|
Mail is part of the current tilde.club host, not a localhost-only experiment.
|
||
|
|
The collected Postfix config accepts mail for tilde.club and several related
|
||
|
|
domains, uses `.mail/`, and has no configured `relayhost`. Dovecot 2.4 serves
|
||
|
|
Maildir mail from `~/.mail`, authenticates through PAM, and exposes a Postfix
|
||
|
|
authentication socket. The first-login wizard can create `.forward`.
|
||
|
|
|
||
|
|
OpenDKIM and Rspamd are connected through milters on localhost ports 8891 and
|
||
|
|
11332. A pyspf-milter service is also running; its presence alone does not show
|
||
|
|
how it is connected. The guide does not reconstruct unpublished filter rules.
|
||
|
|
|
||
|
|
## Decide what service you are offering
|
||
|
|
|
||
|
|
There are three useful starting points:
|
||
|
|
|
||
|
|
- Local-only mail between shell accounts.
|
||
|
|
- Internet mail with direct inbound and outbound delivery.
|
||
|
|
- Inbound mail with outbound delivery through an authenticated relay.
|
||
|
|
|
||
|
|
The production reference matches the second configuration at the Postfix
|
||
|
|
`relayhost` setting. Provider-side routing was not inspected. For a new direct
|
||
|
|
mail host, verify that TCP 25 is permitted, the address has working reverse DNS,
|
||
|
|
and the provider allows mail service. Do not discover a port-25 block after
|
||
|
|
opening accounts.
|
||
|
|
|
||
|
|
Use a separate mail domain in examples if that is your intended policy. Here,
|
||
|
|
mail addresses are `member@tilde.example.net` and the SMTP host is also
|
||
|
|
`tilde.example.net`.
|
||
|
|
|
||
|
|
## DNS before launch
|
||
|
|
|
||
|
|
Publish and verify:
|
||
|
|
|
||
|
|
- A/AAAA records for the SMTP host; publish IPv6 only if SMTP and reverse DNS work there.
|
||
|
|
- An MX for the mail domain pointing to that hostname, not to an IP literal.
|
||
|
|
- A PTR for each sending address, matching the sending hostname with forward resolution.
|
||
|
|
- SPF authorizing the actual sending service, including any outbound relay.
|
||
|
|
- A DKIM public key for the signing selector you configure.
|
||
|
|
- DMARC with a monitored report address and a policy you can operate. Start with
|
||
|
|
observation and verify alignment before enforcing rejection.
|
||
|
|
|
||
|
|
Do not copy tilde.club's IP addresses, signing keys, DNS selectors, or domain
|
||
|
|
aliases. Forwarded mail has additional SPF/DMARC consequences; test it against
|
||
|
|
actual recipients rather than assuming `.forward` solves deliverability.
|
||
|
|
|
||
|
|
## Install the base services
|
||
|
|
|
||
|
|
```bash
|
||
|
|
dnf install postfix dovecot dovecot-pigeonhole swaks
|
||
|
|
```
|
||
|
|
|
||
|
|
Back up existing configs first. The examples are for a new host. Merge
|
||
|
|
[main.cf.fragment](../examples/postfix/main.cf.fragment) into Postfix's config,
|
||
|
|
replacing conflicting settings rather than appending duplicate guesses. Keep
|
||
|
|
the distribution's default local-recipient checks, alias handling, and master
|
||
|
|
services. Point `root` and `postmaster` aliases to a mailbox an operator reads,
|
||
|
|
then run `newaliases`.
|
||
|
|
|
||
|
|
The example uses Dovecot LMTP for local mailbox delivery so the Sieve plugin can
|
||
|
|
run. This is a deliberate new-host choice: the collected production config has
|
||
|
|
an empty `mailbox_transport` and a local delivery transport. A configured Sieve
|
||
|
|
plugin alone does not prove that every live delivery goes through it.
|
||
|
|
|
||
|
|
For a local-only host, keep Postfix listening on loopback, do not publish an MX
|
||
|
|
or open SMTP externally, and explicitly reject nonlocal delivery with
|
||
|
|
`default_transport = error: external mail is not offered`. Do not apply that
|
||
|
|
setting to a host that promises Internet mail.
|
||
|
|
|
||
|
|
## Dovecot 2.4
|
||
|
|
|
||
|
|
Use [tilde.conf](../examples/dovecot/tilde.conf) as a standalone starting config
|
||
|
|
for system accounts with private primary groups. Replace the domain and TLS
|
||
|
|
paths. Do not include another conflicting authentication config alongside it.
|
||
|
|
Retain the distro's `/etc/pam.d/dovecot` authentication/account policy; it is a
|
||
|
|
separate PAM service from SSH and should not inherit SSH-specific TOTP prompts.
|
||
|
|
|
||
|
|
This uses Dovecot 2.4 syntax. In particular, it uses `mail_driver`, `mail_path`,
|
||
|
|
protocol/plugin blocks, and current TLS settings. Do not paste a Dovecot 2.3
|
||
|
|
`mail_location` tutorial into it.
|
||
|
|
|
||
|
|
The example enables IMAP and LMTP, requires TLS, uses a minimum of TLS 1.2, and
|
||
|
|
places LMTP and authentication sockets inside Postfix's private spool. The
|
||
|
|
current host also enables POP3 and ManageSieve; enable those on a new host only
|
||
|
|
if they are part of the service you intend to support.
|
||
|
|
|
||
|
|
The recorded host has `ssl_min_protocol = TLSv1`. That is a live compatibility
|
||
|
|
setting, not the minimum used by this example. Check client compatibility before
|
||
|
|
changing a running system.
|
||
|
|
|
||
|
|
Ensure each mailbox and Sieve directory is owned by its member and is not
|
||
|
|
readable by other members or the shared web group. Test SELinux access on a new
|
||
|
|
enforcing host. Inspect `doveadm user member` for the actual resolved UID, group,
|
||
|
|
home, and mail paths.
|
||
|
|
|
||
|
|
```bash
|
||
|
|
doveconf -n
|
||
|
|
postfix check
|
||
|
|
systemctl enable --now dovecot postfix
|
||
|
|
```
|
||
|
|
|
||
|
|
Check the journal and actual socket ownership. A parser check cannot prove
|
||
|
|
that PAM login or delivery works. Do not add `doveconf -P` when sharing output:
|
||
|
|
it reveals values that the default display hides.
|
||
|
|
|
||
|
|
## Submission
|
||
|
|
|
||
|
|
Merge the named services from
|
||
|
|
[master.cf.fragment](../examples/postfix/master.cf.fragment). Do not replace the
|
||
|
|
rest of `master.cf`. The example offers authenticated STARTTLS on 587 and
|
||
|
|
implicit TLS on 465, with authentication enabled on those services and TLS
|
||
|
|
required before accepting credentials. Delivery on 25 remains available without
|
||
|
|
mandatory TLS so remote mail servers can reach you.
|
||
|
|
|
||
|
|
Keep relay restrictions explicit. Test that an outside, unauthenticated client
|
||
|
|
cannot relay to a third-party domain. Also test that an authenticated member
|
||
|
|
can submit a message and that the expected envelope/header sender policy is
|
||
|
|
enforced. If you want one-account/one-sender enforcement, maintain
|
||
|
|
`smtpd_sender_login_maps` for the addresses and aliases you actually allow and
|
||
|
|
then apply the matching sender restrictions to submission. Do not enable a
|
||
|
|
sender-ownership rule against an empty map.
|
||
|
|
|
||
|
|
A shared host's localhost clients are not all trusted operators. Local shell
|
||
|
|
users can invoke mail tools directly, so address-spoofing controls, outbound
|
||
|
|
volume policy, abuse response, and logging need to cover local submission too.
|
||
|
|
Use authenticated submission or an identity-aware local submission policy where
|
||
|
|
account attribution is required.
|
||
|
|
|
||
|
|
## Filtering and signing
|
||
|
|
|
||
|
|
The base examples establish mail transport, not a finished spam policy. Before
|
||
|
|
opening Internet mail, configure maintained filtering and signing software.
|
||
|
|
The production host's two milter endpoints are recorded above, but its private
|
||
|
|
rules and signing material are not included here.
|
||
|
|
|
||
|
|
If using OpenDKIM, install the maintained package and generate a new key under
|
||
|
|
`/etc/opendkim/keys/tilde.example.net`. Configure a signing table for your domain,
|
||
|
|
a key table pointing to that key, and a localhost-only milter socket. Publish
|
||
|
|
the generated public TXT record. Keep the private key restricted to the signing
|
||
|
|
service. In Rspamd, configure the proxy/milter and controller according to its
|
||
|
|
installed version, keep the controller private, and choose which service owns
|
||
|
|
DKIM signing. Avoid accidentally signing twice with conflicting policies.
|
||
|
|
|
||
|
|
Add the tested milter endpoints to `smtpd_milters` and `non_smtpd_milters` only
|
||
|
|
after verifying them. Choose and document what happens if filtering is down:
|
||
|
|
accepting unfiltered mail and temporarily rejecting it are different policies.
|
||
|
|
Add spam-folder handling only after confirming messages travel through the
|
||
|
|
Sieve-enabled delivery path. Do not enable Sieve external-program extensions
|
||
|
|
just because they appear in a production dump.
|
||
|
|
|
||
|
|
See [OpenDKIM](https://www.opendkim.org/) and
|
||
|
|
[Rspamd's MTA integration guide](https://docs.rspamd.com/tutorials/integration/).
|
||
|
|
Both need their own update, key rotation, and failure checks.
|
||
|
|
|
||
|
|
## Verification
|
||
|
|
|
||
|
|
Use disposable mailboxes and clients you control:
|
||
|
|
|
||
|
|
1. Deliver locally between two accounts and verify the mailbox path and ownership.
|
||
|
|
2. Receive from an outside sender and send to an outside recipient.
|
||
|
|
3. Verify the received SPF, DKIM, and DMARC results and inspect the queue/logs.
|
||
|
|
4. Check IMAP login with a valid account, a wrong password, and an ineligible account.
|
||
|
|
5. Check submission over TLS and reject an unauthenticated external relay attempt.
|
||
|
|
6. Test aliases, `.forward`, invalid recipients, a full quota, Sieve, and service restart.
|
||
|
|
7. Renew the certificate in a test run and confirm each mail service uses the new one.
|
||
|
|
|
||
|
|
For TLS inspection without exposing a password in command history:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
openssl s_client -connect tilde.example.net:993 -servername tilde.example.net
|
||
|
|
openssl s_client -starttls smtp -connect tilde.example.net:587 -servername tilde.example.net
|
||
|
|
postqueue -p
|
||
|
|
journalctl -u postfix -u dovecot --since today
|
||
|
|
```
|
||
|
|
|
||
|
|
Do not submit a password until the client verifies the certificate and expected
|
||
|
|
hostname. Do not paste authentication transcripts into public logs.
|
||
|
|
|
||
|
|
Back up mailbox data, Sieve files, aliases, transport/filter configs, and signing
|
||
|
|
keys using [the recovery plan](backups.md). A key or MFA reset for SSH does not
|
||
|
|
by itself revoke an existing webmail session, mail password, or application token.
|