diff --git a/CHANGELOG.md b/CHANGELOG.md index cc4b501..ae59502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version ## [Unreleased] +### Fixed + +- **ETRN is discarded from the EHLO reply silently**: since `2.14.4` Postfix + logged "discarding EHLO keywords: ETRN" for every connection on every port + (seen on the test server after the rollout); `silent-discard` keeps the + discard and drops the line. + ## [2.14.4] - 2026-10-17 The follow-ups of the security audit of 2026-10-17 diff --git a/build/postfix-config.sh b/build/postfix-config.sh index 27c95d0..a48a4e3 100644 --- a/build/postfix-config.sh +++ b/build/postfix-config.sh @@ -327,14 +327,17 @@ postconf -e \ # client flush the queue toward an inbound domain's upstream # (fast_flush_domains = $relay_domains), and nothing here needs it (security # audit 2026-10-17, S6; Postfix 3.10.13, src/smtpd/smtpd.c, etrn_cmd() asks -# smtpd_check_etrn(), whose "reject" answers reject_code, 554). +# smtpd_check_etrn(), whose "reject" answers reject_code, 554). The discard is +# silent: without the pseudo keyword smtpd logs "discarding EHLO keywords: +# ETRN" for every connection (src/smtpd/smtpd.c:2016, EHLO_MASK_SILENT; +# src/global/ehlo_mask.c:88; seen on the test server after 2.14.4). postconf -e \ "smtpd_tls_protocols=>=TLSv1.2" \ "smtpd_tls_mandatory_protocols=>=TLSv1.2" \ "smtp_tls_mandatory_protocols=>=TLSv1.2" \ "disable_vrfy_command=yes" \ "smtpd_etrn_restrictions=reject" \ - "smtpd_discard_ehlo_keywords=etrn" \ + "smtpd_discard_ehlo_keywords=silent-discard,etrn" \ 'smtpd_banner=$myhostname ESMTP' # SASL: Cyrus with the local sasldb2 the panel maintains. The realm is left diff --git a/docs/architecture.md b/docs/architecture.md index 0979c29..f3cf08b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -104,7 +104,7 @@ smtp/inet` removes Debian's stock smtpd). Outbound delivery still uses the submission chain would otherwise let a signing outage defer relayed mail and would file inbound mail into the outbound send log under the sender's domain. `ETRN` is refused on every listener and not offered in the EHLO - reply (`smtpd_etrn_restrictions=reject`, `smtpd_discard_ehlo_keywords=etrn`): + reply (`smtpd_etrn_restrictions=reject`, `smtpd_discard_ehlo_keywords=silent-discard,etrn`): Postfix's default lets any client flush the queue toward an inbound domain's upstream. With the inbound relay on the chain is the optional antispam milter, then the panel's **inbound journal milter** (unix socket diff --git a/test/e2e/process_check.go b/test/e2e/process_check.go index e25db64..1734e48 100644 --- a/test/e2e/process_check.go +++ b/test/e2e/process_check.go @@ -168,7 +168,7 @@ func checkPostfixHardening(s *stack) error { return fmt.Errorf("postconf: %v\n%s", err, out) } got := strings.Split(strings.TrimSpace(out), "\n") - want := []string{">=TLSv1.2", ">=TLSv1.2", "yes", "$myhostname ESMTP", "reject", "etrn"} + want := []string{">=TLSv1.2", ">=TLSv1.2", "yes", "$myhostname ESMTP", "reject", "silent-discard,etrn"} if strings.Join(got, "|") != strings.Join(want, "|") { return fmt.Errorf("postconf -h of the hardened settings = %q, want %q", got, want) }