Harden Postfix¶
Hardening runbook. Configures Postfix so it is not an open relay, does not leak account information, and rejects obvious abuse before it reaches mailboxes. This covers the security-relevant configuration; full Postfix setup is in its own documentation. For checking an existing server’s relay state quickly, see relay and authentication review.
When to run¶
When setting up a Postfix server that accepts or relays mail. When a relay review shows the server accepts mail it should not, or after any change to the SMTP restrictions.
The files¶
Two files hold the configuration. /etc/postfix/main.cf is the bulk of it; /etc/postfix/master.cf defines which services run. Most changes take effect on postfix reload; a few need a restart. Back up main.cf before editing:
sudo cp /etc/postfix/main.cf{,.old}
Inspect the current non-default settings at any point with:
postconf -n
Close the relay¶
An open relay forwards mail from anyone to anyone, and gets the server blocklisted within hours. The control is smtpd_recipient_restrictions in main.cf. The combination that closes the relay: permit authenticated users and local networks, reject everything bound for a domain this server does not host.
smtpd_recipient_restrictions =
reject_invalid_hostname,
reject_unknown_recipient_domain,
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
reject_rbl_client sbl.spamhaus.org,
permit
reject_unauth_destination is the line that closes the relay. Its absence is the open-relay condition.
Risk¶
Restriction rules are order-sensitive. A permit placed too early short-circuits the rejects that follow it, leaving the relay open despite the rules looking correct. Keep reject_unauth_destination ahead of any blanket permit. Confirm mynetworks contains only loopback (and any genuinely trusted internal range), not a broad subnet that turns into a relay path.
Disable address harvesting¶
The VRFY command lets an attacker test whether an account exists, aiding brute force and harvesting names. Turn it off:
disable_vrfy_command = yes
Greylisting (optional)¶
Greylisting temporarily rejects mail from unknown senders on first contact. Legitimate servers retry and get through; many spam scripts do not. Install postgrey and add it as a policy service:
smtpd_recipient_restrictions = ..., check_policy_service inet:127.0.0.1:10030
Enable the postgrey service, then reload Postfix. It delays first-contact mail by minutes, which is the trade-off.
Mailboxes are not Postfix’s job¶
Postfix routes mail; it does not store mailboxes. Deliver to a POP/IMAP server (Dovecot’s dovecot-lda) for storage, filtering, and quotas. Keeping that boundary clean avoids a class of misconfiguration.
Verify¶
Check the configuration parses, then reload:
sudo postfix check && sudo postfix reload
Confirm the relay is closed by attempting to relay from an external host to an outside domain (full method in relay and authentication review):
postconf smtpd_recipient_restrictions # confirm reject_unauth_destination present
postconf mynetworks # confirm loopback only
The relay test should return 554 or 550 relay access denied. Confirm VRFY is refused: VRFY postmaster over an SMTP session should return a 502 or 252, not a real answer.
Done¶
reject_unauth_destination present and ahead of any permit. mynetworks limited to trusted addresses. VRFY disabled. postfix check clean. External relay attempt refused.
Rollback¶
The pre-edit main.cf.old is the fallback: restore it and reload. For a single bad restriction line, edit it out and reload rather than reverting the whole file, so other hardening stays in place.
Follow-up¶
Relay hardening is separate from sender authentication. Pair with SPF, DKIM, and DMARC.
Add TLS for mail transport so sessions are encrypted, and SASL authentication so
permit_sasl_authenticatedhas something to permit.Watch the queue and logs after changes; see relay and authentication review.