diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aeff37..04da8f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,13 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version three `dmarc_*` maps root creates at the start were missing from the list of paths where a symbolic link is removed first. +### Documentation + +- **The upstream's "Required" TLS checks no certificate**, and the guide and + Help now say so (audit M7): it guards against a listener, not against one + who answers in the upstream's place. + + ## [2.14.3] - 2026-10-17 A tag beside a label. No migration; schema 13. diff --git a/docs/guide.md b/docs/guide.md index 23694c7..c477657 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -1225,7 +1225,10 @@ for such a sender. **Panel** (`/inbound/domains`): the global role adds and deletes domains. On a domain's page, set the upstream host/port and TLS to that hop (opportunistic / -required / off), and choose recipients. An upstream has one TLS mode: Postfix +required / off), and choose recipients. *Required* is Postfix's `encrypt` +level: the hop is encrypted, but the upstream's certificate is not checked, +so it guards against someone who listens on the way, not against one who +answers in the upstream's place. An upstream has one TLS mode: Postfix keeps the TLS policy per next hop, not per domain, so the mode saved for one domain is the mode of every domain forwarded to the same host and port, and they are changed with it; a *domain* user who does not manage all of them is diff --git a/docs/security-audit-2026-10-17.md b/docs/security-audit-2026-10-17.md index 84a6a2d..76fd4ff 100644 --- a/docs/security-audit-2026-10-17.md +++ b/docs/security-audit-2026-10-17.md @@ -847,8 +847,8 @@ the argument. ### Stage 6 — the rest, and what to accept (~3 h) -- [ ] **M7.** guide: upstream `encrypt` checks no certificate. — **Sonnet**, - 0.25 h. (Offering `secure` is hours and a `domain`-user-facing choice; +- [x] **M7.** guide: upstream `encrypt` checks no certificate. — **Sonnet**, + 0.25 h. *Done 2026-10-17:* guide and Help. (Offering `secure` is hours and a `domain`-user-facing choice; propose it on the roadmap, not here.) - [ ] **A6, A7, A10, W7, M6, M8** and the README note — half an hour each, or the wording change named under each. — **Sonnet**, 2 h. diff --git a/internal/web/view/help.go b/internal/web/view/help.go index c049fe7..6a4f0be 100644 --- a/internal/web/view/help.go +++ b/internal/web/view/help.go @@ -231,7 +231,7 @@ var inboundTopics = []HelpTopic{ Rich("An optional backup-MX or forwarder, switched on in the server's ", Code(".env"), "; the Inbound menu exists only then. Postfix accepts mail on port 25 for the listed domains only and hands each message on to that domain's upstream; there are no mailboxes. For each domain publish the MX record its page shows, and keep a primary MX the domain already has if this is a backup. The MX tag is green when at least one MX of the domain points at this server, and a domain accepts no mail until an upstream is saved on its page. Adding and deleting domains is for the global role."), }}, {ID: HelpUpstream, Title: "Upstream", Body: []Text{ - Plain("The upstream is the server that actually holds the mailboxes. Give its host and port — used exactly as written, with no MX lookup — and choose the TLS for the hop to it: Opportunistic uses TLS when the upstream offers it and otherwise sends in the clear; Required sends only over TLS, and the mail waits in the queue while the upstream does not offer it or the TLS handshake fails - an upstream that answers STARTTLS with a permanent error bounces it; Off never uses TLS. While the upstream does not answer, Postfix keeps the mail and retries as for any other mail."), + Plain("The upstream is the server that actually holds the mailboxes. Give its host and port — used exactly as written, with no MX lookup — and choose the TLS for the hop to it: Opportunistic uses TLS when the upstream offers it and otherwise sends in the clear; Required sends only over TLS, and the mail waits in the queue while the upstream does not offer it or the TLS handshake fails - an upstream that answers STARTTLS with a permanent error bounces it. Neither checks the upstream's certificate: TLS here keeps the mail from whoever only listens on the way, not from one who answers in the upstream's place. Off never uses TLS. While the upstream does not answer, Postfix keeps the mail and retries as for any other mail."), }}, {ID: HelpRecipients, Title: "Valid recipients", Body: []Text{ Plain("Choose whom this domain accepts. Listed addresses only: the relay accepts exactly the addresses you list, one per line or comma-separated, and refuses any other while the sender is still connected, so it never has to send a bounce for them. Any recipient: everything at the domain is accepted and passed on, and an address the upstream then rejects comes back as a bounce from this server to a sender who is often forged — backscatter. Prefer a list, and keep it in step with the mailboxes upstream."),