Postfix postscreen and Pre-Queue Spam Defense
Introduction¶
postscreen sits in front of Postfix's smtpd and evaluates each connecting
client before a full SMTP conversation starts. Most spam comes from
compromised machines running crude SMTP engines; postscreen catches them with
cheap tests, so your real smtpd processes only handle plausible mail.
How it works¶
postscreen runs on port 25; smtpd moves to a pass port. A connecting IP is:
- On the temporary allowlist (passed a check recently) → handed straight to
smtpd. - On the denylist → rejected.
- Otherwise → run the tests, then allow or reject.
master.cf¶
smtp inet n - y - 1 postscreen
smtpd pass - - y - - smtpd
dnsblog unix - - y - 0 dnsblog
tlsproxy unix - - y - 0 tlsproxy
main.cf¶
postscreen_access_list = permit_mynetworks, cidr:/etc/postfix/postscreen_access.cidr
# DNSBLs with weights; act on the sum
postscreen_dnsbl_sites =
zen.spamhaus.org*3
bl.spameatingmonkey.net*2
b.barracudacentral.org*2
bl.spamcop.net*1
dnsbl.sorbs.net*1
list.dnswl.org=127.0.[0..255].0*-2 # WHITELIST — negative weight
list.dnswl.org=127.0.[0..255].1*-3
list.dnswl.org=127.0.[0..255].2*-4
postscreen_dnsbl_threshold = 3
postscreen_dnsbl_action = enforce # drop (or: ignore while testing, warn)
# Greet delay + protocol tests (pre-handshake — no false positives from real MTAs)
postscreen_greet_action = enforce
postscreen_greet_wait = ${stress?{2}:{6}}s
# Deep tests — these hold the connection; run AFTER greet passes
postscreen_pipelining_enable = yes
postscreen_pipelining_action = enforce
postscreen_non_smtp_command_enable = yes
postscreen_non_smtp_command_action = enforce
postscreen_bare_newline_enable = yes
postscreen_bare_newline_action = enforce
# Cache the results
postscreen_cache_map = btree:$data_directory/postscreen_cache
postscreen_bare_newline_ttl = 30d
postscreen_dnsbl_ttl = 1h
The tests¶
- DNSBL — query several blocklists, sum the weights, reject if ≥ threshold. Weighting means one aggressive list can't blackhole legit mail alone; DNSWL (whitelist) subtracts. Spamhaus ZEN needs a registered account / paid feed for anything beyond low volume now — check current terms.
- Greet delay (
greet_wait) — postscreen speaks its 220 banner slowly. Botnet engines that don't wait and start blasting commands (or hang up) fail. Real MTAs wait. - Pipelining — sending commands before the server's response, pre-greeting. RFC-violating; botnets do it.
- Non-SMTP command — sending HTTP/other garbage.
- Bare newline —
\nwithout\r. Real MTAs send\r\n.
The greet/deep tests are pre-SMTP — a real mail server never fails them, so there's essentially no false-positive risk from enforcing them (unlike content filtering).
Interaction with greylisting¶
postscreen's deferrals are a form of greylisting for unknown senders — the
first connection gets a temp-fail while tests run, the retry (which real MTAs do)
gets through and is now allowlisted. This delays first mail from new senders by
minutes. Usually acceptable; tune *_ttl so it's a one-time cost per sender.
Verification and troubleshooting¶
postconf -M | grep -E 'postscreen|smtpd|dnsblog|tlsproxy'
grep postscreen /var/log/mail.log | tail -50
# per-connection outcome:
# "PASS NEW [1.2.3.4]" "DNSBL rank 5 for [1.2.3.4]" "PREGREET 12 after 0.1 from [1.2.3.4]"
postconf postscreen_dnsbl_threshold postscreen_dnsbl_action
- Legit senders rejected ("DNSBL rank N") — a blocklist is too aggressive or
the sender is genuinely listed (they need to delist). Lower that list's weight,
raise
postscreen_dnsbl_threshold, or setpostscreen_dnsbl_action = ignorewhile you tune (it logs but doesn't act). Add trusted partners topostscreen_access_list. PREGREETrejecting a real MTA — very rare; some misconfigured senders or monitoring probes. Whitelist them, or reducegreet_wait.- First mail from every new correspondent delayed ~5 min — the test/greylist effect. Expected; ensure the cache TTLs are long so it's one-time.
- Spamhaus queries returning
127.255.255.x/ errors — you're over the free query limit (using a public resolver at volume) — you need a data feed subscription or a rsync'd local copy. Remove the list or subscribe. - postscreen cache errors / not persisting —
postscreen_cache_mappath permissions, orbtreevslmdbavailability.postconf -mfor supported map types. - TLS clients failing — postscreen hands TLS off to
tlsproxy; if that's not inmaster.cfor misconfigured, STARTTLS breaks. Ensure thetlsproxyentry exists. - Everything still getting through — actions set to
ignore/warnnotenforce, orpermit_mynetworksis too broad so nothing is tested.
Related tools and reading¶
- On-site: Blacklist Checker, SMTP test, DNS lookup.
- Related posts: Postfix as a relay, with milters, SPF, DKIM and DMARC end to end.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Web & Mail Servers
Running BIND 9 as an Authoritative Server
BIND as an authoritative server: zone files, secured AXFR with TSIG, SOA serial rules, and DNSSEC inline-signing. Here's a working master/slave setup.
October 24, 2026Varnish Cache in Front of a Site
Varnish is a caching HTTP accelerator configured in VCL. Here's the request lifecycle, why you strip cookies, how bans work, and grace mode for serving stale during backend trouble.
October 24, 2026Let's Encrypt with Certbot, Including Renewal That Doesn't Break
Getting the first cert is easy; keeping renewal working for years is the part people get wrong. Webroot vs DNS-01, deploy hooks, and the failure modes.
October 24, 2026