Your mail queue is growing with bounces to envelope senders at domains you have never heard of. Within hours, your IP lands on a DNSBL and legitimate mail stops reaching its destination.
This is a backscatter storm. Postfix accepted mail for recipients it could not deliver to, then generated non-delivery reports (NDRs) to the forged envelope sender. Those NDRs hit innocent third parties whose addresses the spammer forged.
The fix: reject unknown recipients at SMTP time instead of accepting and bouncing later. The challenge is identifying which misconfiguration let the mail through, stopping the storm without losing legitimate mail, and repairing your sender reputation.
What this means
Backscatter happens when Postfix acts as a backup MX, relay, or gateway that accepts mail without validating recipients against a known-good list. The message is accepted during the SMTP transaction, queued, delivery fails, and Postfix generates a bounce to the forged envelope sender.
If the bounce destination is also invalid, Postfix generates a double-bounce. Double-bounces are discarded by default, but the processing load consumes cleanup, bounce, and queue manager resources. Meanwhile, the original bounces to forged addresses are actively damaging your sender reputation.
Key signals: a bounce rate spike followed by sustained elevated injection, maildrop queue activity from local bounce generation, and queue entries from MAILER-DAEMON or double-bounce senders.
flowchart LR
A["Spammer sends with\nforged return path"] --> B["Your Postfix accepts\nfor unknown recipient"]
B --> C["Delivery fails:\nuser unknown"]
C --> D["Bounce generated\nto forged sender"]
D --> E["Innocent third party\nreceives NDR spam"]
D --> F["Forged address invalid?\nDouble-bounce discarded"]
E --> G["Complaints and\nDNSBL listing"]The critical distinction: rejecting at SMTP time (5xx response during RCPT TO) produces no bounce. The connecting server is responsible for generating any NDR. Accepting then failing produces a bounce from your server, making you the source of backscatter.
Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
| Backup MX without relay_recipient_maps | Mail accepted for any address in relay domains, then bounced after delivery failure | postconf -h relay_recipient_maps |
| Wildcard catch-all alias | All mail to a domain accepted regardless of recipient validity, then bounced or forwarded to nonexistent addresses | Check virtual alias maps for @domain wildcard entries |
| Empty local_recipient_maps with luser_relay | Local recipients not validated before acceptance; all mail redirected via luser_relay | postconf -h local_recipient_maps luser_relay |
| relay_recipient_maps configured with @domain wildcard | Postfix accepts mail for any recipient in relay domains, becoming a backscatter source per Postfix documentation | Inspect relay recipient map contents for wildcard entries |
| Content filter accepting then rejecting | Filter passes SMTP but rejects during processing, generating late bounces | Check content_filter logs for post-acceptance rejections |
Quick checks
These commands are read-only and safe to run during an active incident. Your log path may be /var/log/maillog (RHEL family) instead of /var/log/mail.log (Debian family). Adjust accordingly.
# Count bounces logged in the current hour
grep "$(date '+%b %e %H')" /var/log/mail.log | grep -c 'status=bounced'
# Count MAILER-DAEMON messages currently queued
postqueue -p | grep -c 'MAILER-DAEMON'
# Show top senders in the queue (Postfix 3.1+ uses -j JSON output)
postqueue -j | jq -r '.sender' | sort | uniq -c | sort -rn | head -20
# Identify forged sender patterns in recent bounces
grep 'status=bounced' /var/log/mail.log | tail -20 | grep -o 'from=<[^>]*>' | sort | uniq -c
# Inspect bounce destination domains
grep 'status=bounced' /var/log/mail.log | grep -oE 'to=<[^>]*>' | cut -d@ -f2 | sort | uniq -c | sort -rn | head
# Check if relay_recipient_maps is configured
postconf -h relay_recipient_maps
# Check if local_recipient_maps is populated
postconf -h local_recipient_maps
# Check recipient rejection enforcement
postconf -h smtpd_reject_unlisted_recipient
# Check current deferred queue size
find /var/spool/postfix/deferred -type f | wc -l
# Check inode usage on queue filesystem (backscatter consumes inodes fast)
df -i /var/spool/postfix
How to diagnose it
Confirm backscatter is happening. Look for bounces (
status=bounced) with sender addresses at domains unrelated to your users or relay customers. If the log fills with MAILER-DAEMON mail to random external domains, you are generating backscatter.Identify which mail was accepted that should have been rejected. Search for recent bounced messages:
grep 'status=bounced' /var/log/mail.log | tail -50Look at the
to=<...>field. If the recipient does not exist in your directory, the message should have been rejected at SMTP time, not accepted and bounced.Trace the acceptance path. Check which Postfix restriction allowed the message through. Determine whether the recipient domain is in
relay_domains,mydestination, orvirtual_alias_domains:postconf -h relay_domains mydestination virtual_alias_domainsThen check whether the corresponding recipient validation map exists and is populated.
Test the recipient map directly. If relay_recipient_maps is configured, verify a lookup works:
# Test a known-invalid recipient - should return empty postmap -q nonexistent@yourdomain.com hash:/etc/postfix/relay_recipients # Test a known-valid recipient - should return a result postmap -q validuser@yourdomain.com hash:/etc/postfix/relay_recipientsIf both return empty, the map is not populated. If the map file does not exist, relay_recipient_maps is effectively a no-op.
Check for wildcard entries. Inspect map source files for
@domainentries that accept all recipients:grep '^@' /etc/postfix/relay_recipients 2>/dev/null grep '^@' /etc/postfix/virtual 2>/dev/nullCheck DNSBL status. Query common blocklists for your IP before the listing propagates further:
# Replace 1.2.3.4 with your IP in reverse notation host 4.3.2.1.bl.spamcop.net host 4.3.2.1.zen.spamhaus.org host 4.3.2.1.dnsbl.sorbs.net
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
| Bounce rate (status=bounced) | Directly measures NDR generation volume | Sustained rate above 1% of injection, or sudden 10x increase from baseline |
| MAILER-DAEMON queue entries | Active bounce messages sitting in queue | Any significant count indicates bounces not draining |
| Deferred queue growth rate | Bounces to invalid addresses defer on delivery, consuming queue capacity | Growth exceeding 1000 messages/hour with no plateau |
| Injection vs delivery velocity | Bounce generation inflates injection without real delivery value | Injection rate far exceeding delivery rate sustained over 5+ minutes |
| Recipient rejection rate | Shows whether recipient validation is active | Drop in rejections coinciding with bounce rate spike |
| Inode usage on queue filesystem | Each bounce and double-bounce creates small queue files | Above 80% used on the partition holding /var/spool/postfix |
| Relay attempt rejection rate | Indicates whether relay restrictions are catching forged traffic | Drop in “relay access denied” log entries with rising bounces |
| Maildrop queue depth | Bounces are generated locally via pickup daemon | Persistent files in maildrop older than 10 minutes |
Fixes
Reject unknown recipients at SMTP time
This is the definitive fix. Every recipient must be validated during the SMTP transaction, before the message is queued.
For relay domains, configure relay_recipient_maps with an explicit list of valid recipients:
# The source file must already exist and contain entries.
# Format: validuser@domain OK
postmap /etc/postfix/relay_recipients
postconf -e 'relay_recipient_maps = hash:/etc/postfix/relay_recipients'
postfix reload
For domains where you cannot maintain a static recipient list (for example, a backup MX for a primary server you do not control), use address verification:
# Review existing restrictions first - postconf -e replaces the entire list.
postconf -h smtpd_recipient_restrictions
postconf -e 'smtpd_recipient_restrictions = reject_unauth_destination, reject_unverified_recipient'
postfix reload
The reject_unverified_recipient check (Postfix 2.1+) probes the destination MTA in real time and caches the result. Be aware of the tradeoff: the official ADDRESS_VERIFICATION_README warns that this can increase load on downstream servers during dictionary attacks or backscatter floods. The persistent verification cache (address_verify_map) mitigates this by caching results across restarts, but is not enabled by default on all distributions.
Do not change unverified_recipient_reject_code from its default of 450 to 250. The Postfix documentation explicitly warns this turns your server into a backscatter source under load.
Remove wildcard catch-all aliases
If your virtual alias map or relay recipient map contains @domain wildcard entries, every address in that domain is accepted. During a spam flood targeting random addresses at your domain, this generates bounces for every forged sender.
Replace wildcard entries with explicit recipient lists. If you must keep a catch-all for operational reasons, understand that your server will generate backscatter during any spam campaign targeting that domain.
Fix local_recipient_maps configuration
The local_recipient_maps parameter specifies which local recipients are valid. By default (Postfix 2.0+), Postfix populates this from the Unix password file and alias database. If it is set to empty, all local recipients are accepted.
The critical gotcha: if you use luser_relay to redirect unknown local recipients, you must set local_recipient_maps to empty (disabling recipient validation). The LOCAL_RECIPIENT_README explicitly warns against doing this on systems receiving mail directly from the internet.
Check your configuration:
postconf -h local_recipient_maps luser_relay
If luser_relay is set and local_recipient_maps is empty on an internet-facing server, you have found the problem.
Stop an active storm
To stop bounce generation immediately, tighten recipient restrictions and reload. New connections will reject invalid recipients at SMTP time. Existing queued bounces still need cleanup.
To remove queued bounce messages without affecting legitimate mail:
# DANGER: This deletes messages from the queue. Verify the pattern matches
# only bounce messages before running.
# mailq output appends * (active) or ! (held) to queue IDs.
# The gsub strips those before passing to postsuper.
# Test the pattern first:
mailq | awk '/MAILER-DAEMON|double-bounce/ {gsub(/[*!]/,"",$1); print $1}' | head -20
# If the output looks correct, delete those queue entries:
mailq | awk '/MAILER-DAEMON|double-bounce/ {gsub(/[*!]/,"",$1); print $1}' | postsuper -d -
Review the output carefully before piping to postsuper. Do not run postsuper -d ALL unless you are prepared to lose every queued message, including legitimate mail.
Address blocklisting
After fixing the root cause, request delisting from any DNSBL that listed your IP. Some blocklists (particularly those targeting backscatter sources) require admin-initiated removal and will re-list you if the underlying problem persists. Fixing recipient validation before requesting delisting is mandatory; delisting without a fix guarantees re-listing.
Prevention
- Monitor bounce rate explicitly. Bounces count as “sent” in simple delivery metrics. You need a dedicated counter for status=bounced entries, not just delivery success/failure. Alert on sustained rates above 1% or any sudden 10x spike from baseline.
- Keep relay_recipient_maps current. Stale maps that are missing valid recipients cause false rejections. Maps that include too many entries or wildcards cause backscatter. Sync from your authoritative directory on a schedule.
- Audit recipient validation after every configuration change. Any change to smtpd_recipient_restrictions, relay_domains, virtual_alias_domains, or transport_maps can silently disable recipient validation. Run
postfix checkand test with an invalid recipient after changes. - Use postscreen to reduce inbound spam volume. Postscreen blocks obvious zombies before they reach smtpd, reducing the volume of spam that reaches your recipient validation logic.
- Check DNSBL listings proactively. Query major blocklists for your IP on a schedule, not just when recipients complain. Backscatter listings can appear within hours of a storm starting.
How Netdata helps
Netdata’s Postfix collector surfaces the signals that indicate a backscatter storm before it reaches the blocklisting stage:
- Per-second queue depth tracking across active, deferred, maildrop, and incoming queues. A spike in maildrop combined with deferred growth while MAILER-DAEMON messages accumulate is the earliest indicator of bounce generation.
- Mail flow velocity correlation. Injection rate outpacing delivery rate, combined with rising bounce counts, distinguishes a backscatter storm from a normal delivery backlog or slow-destination queue buildup.
- Inode utilization monitoring on the queue filesystem. Each bounce and double-bounce creates small queue files that consume inodes independently of disk space.
- Process count tracking for smtpd, bounce, cleanup, and pickup daemons. Sustained elevation in bounce daemon activity with high smtpd utilization indicates active NDR generation under load.
- Anomaly detection on bounce rate and queue growth velocity. Netdata learns the baseline for each signal and flags deviations without manually tuned thresholds.
Related guides
- Postfix active queue saturation: hitting qmgr_message_active_limit
- postfix check warnings: configuration drift and permission problems
- Postfix Connection refused: blocked port 25 and rejected outbound delivery
- Postfix Connection timed out: delivery deferrals to unreachable destinations
- Postfix content_filter backpressure: incoming queue growth when Amavis or Rspamd slows
- Postfix deferred queue growing: why mail piles up and how to drain it
- Postfix destination concurrency limit: tuning per-destination delivery
- Postfix DNS resolver failure: when a broken resolver defers mail to everyone
- Postfix flushing and clearing the deferred queue: postqueue and postsuper
- Postfix greylisting delays: 450 4.7.1 deferrals and slow first delivery
- Postfix Host or domain name not found: DNS name service errors deferring mail
- How Postfix actually works in production: a mental model for operators






