← All rules
SOCLE-CLD-GEN-048// Hardening (misc)mediumeffective runtime

Hide Postfix SMTP Banner Software Name

Strip the software identity from the SMTP greeting by setting smtpd_banner = $myhostname ESMTP. The distribution default ($myhostname ESMTP $mail_name (Ubuntu)) announces the MTA product, and often the packaging, to every anonymous client that opens a connection to port 25: that is free reconnaissance, letting an attacker match your MTA against a list of known vulnerabilities before sending a single command.

Checked against the resolved running state (e.g. sshd -T, sysctl, systemctl show), catches drop-ins and Includes a file read would miss. Caveat: runtime ≠ persistence; a value correct now may not survive a reboot.

A pass proves✓ running now? on disk? survives rebootthe qualified verdict →
Debian 12CIS 1.1.0Debian 13CIS 1.0.0FedoraRHEL 10 / Rocky 10 / AlmaLinux 10RHEL 8 / Rocky 8 / AlmaLinux 8CIS 4.0.0RHEL 9 / Rocky 9 / AlmaLinux 9CIS 2.0.0Ubuntu 24.04CIS 1.0.0Ubuntu 26.04

What Pavois checks

Pavois reads the effective banner with postconf -h smtpd_banner and fails if it still contains mail_name. postconf -h prints the value Postfix resolved, after main.cf and the built-in defaults, with the $mail_name variable left unexpanded: its mere presence in the template is what leaks the product name at connection time. When postconf is absent (Postfix not installed) the control returns ok.

describe command('if ! command -v /usr/sbin/postconf >/dev/null 2>&1; then echo ok; elif /usr/sbin/postconf -h smtpd_banner 2>/dev/null | grep -qi mail_name; then echo ko; else echo ok; fi') do
  its('stdout.strip') { should eq 'ok' }
end

How to verify it is applied

Read the resolved template, then the greeting a real client sees:

postconf -h smtpd_banner              # expected: $myhostname ESMTP
printf 'QUIT\r\n' | nc localhost 25

The greeting must read 220 host.example.org ESMTP, with no product name, version or distribution tag after ESMTP.

Inspect & investigate

journalctl -u postfix (or /var/log/mail.log, /var/log/maillog on RHEL) records the reload that applies the new banner, and every subsequent connect from line. Banner-grabbing scans show up there as a burst of connections that disconnect right after the greeting, without ever issuing MAIL FROM.

Remediation

Pavois runs the postfix-banner step: postconf -e 'smtpd_banner = $myhostname ESMTP', with a de-duplicating sed plus append as the fallback when postconf is missing, followed by a Postfix reload. A not_if guard skips the step once main.cf declares a banner free of mail_name, keeping confkit harden apply idempotent. $myhostname is deliberately kept: RFC 5321 expects the greeting to carry the server's fully qualified name, and several anti-spam checks reject a greeting that does not.

Pavois applies this with its own harden engine, the plan below, not a shell script:

commandmkdir -p /etc/postfix; touch /etc/postfix/main.cf; if command -v postconf >/dev/null 2>&1; then postconf -e 'smtpd_banner = $myhostname ESMTP'; else sed -ri '/^smtpd_banner/d' /etc/postfix/main.cf; echo 'smtpd_banner = $myhostname ESMTP' >> /etc/postfix/main.cf; fi; systemctl reload postfix 2>/dev/null || true
namepostfix-banner
not_ifgrep -qs '^smtpd_banner' /etc/postfix/main.cf && ! grep '^smtpd_banner' /etc/postfix/main.cf | grep -qi mail_name
resourceexec
pavois harden plan local

where the target is local, a user@host SSH alias, or a container , Docs

Impact & precautions

Defence in depth, not a fix: hiding the banner patches nothing, it only raises the cost of targeting. Operational risk is minimal, but check anything that parses the greeting: some monitoring probes, mail-relay tests and legacy anti-spam rules match on the product name and will need updating. The banner keeps its hostname and the ESMTP keyword, so protocol conformance and reverse-DNS checks are unaffected.

0