A Postfix server that accepts mail from unauthenticated, non-local clients and forwards it to arbitrary external domains is an open relay. Treat any confirmed occurrence as a PAGE-level security incident: automated scanners find open relays within hours, and a single relayed spam batch can trigger blocklist listings that take days to clear.
The most common causes are configuration changes that widen trust: mynetworks set too broadly, restrictions evaluated in the wrong order, a SASL backend that accepts empty credentials, or a backup-MX setup without recipient validation.
How relay permission works
Postfix decides whether to relay a message through a layered evaluation of client identity, authentication state, and recipient destination. The decision happens at RCPT TO time, before the message enters the queue. Three configuration surfaces control the outcome:
mynetworks: IP ranges trusted to relay without authentication. If this includes0.0.0.0/0or an overly broad CIDR, every client is trusted.smtpd_relay_restrictions: evaluated for every RCPT TO to determine if relaying is allowed. Postfix 2.10+ uses this as the primary relay control surface.smtpd_recipient_restrictions: evaluated for spam and access control. On systems withcompatibility_levelbelow 3.6, this evaluates beforesmtpd_relay_restrictions, which can produce an open relay if a permissive rule (such ascheck_helo_accessreturning PERMIT) short-circuits beforereject_unauth_destination.
A confirmed open relay shows in logs as a delivery line with status=sent via the postfix/smtp daemon, where the corresponding connection line lacks sasl_method=, and the client IP is outside your trusted networks.
Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
mynetworks too broad | Relay succeeds from any external IP without auth | postconf -h mynetworks |
| Restrictions in wrong order | PERMIT rule fires before reject_unauth_destination | postconf smtpd_recipient_restrictions |
Empty smtpd_relay_restrictions after upgrade | No relay enforcement from that parameter | postconf -h compatibility_level smtpd_relay_restrictions |
| SASL bypass | Auth backend accepts null or empty credentials | Test AUTH with empty password on port 587 |
| Backup-MX without recipient validation | Accepts mail for any address at relayed domains, then bounces | postconf -h relay_domains relay_recipient_maps |
| Deprecated restrictions still in config | Postfix 3.9+ ignores removed directives | postconf -n for check_relay_domains, permit_mx_backup, permit_naked_ip_address, reject_maps_rbl |
Quick checks
# Check effective relay control configuration
postconf -h smtpd_relay_restrictions smtpd_recipient_restrictions mynetworks mynetworks_style
# Check compatibility level (affects defaults and evaluation order)
postconf -h compatibility_level
# Smoking gun: unauthenticated SMTP delivery from a non-local client.
# sasl_method appears on smtpd connection lines, not on smtp delivery lines.
# Correlate by queue ID. Path may be /var/log/maillog on RHEL-based systems.
grep 'postfix/smtp\[' /var/log/mail.log | grep 'status=sent' \
| grep -oE '[A-F0-9]{9,}' | sort -u | head -50 | while read qid; do
grep "$qid" /var/log/mail.log | grep -q 'sasl_method=' \
|| grep "$qid" /var/log/mail.log | grep 'client=' \
| grep -vE '127\.0\.0\.1|::1|192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.'
done
# Relay denials by source IP (should be nonzero if probed)
grep 'relay access denied' /var/log/mail.log \
| grep -oP 'from \S+\[\K[0-9.]+' | sort | uniq -c | sort -rn | head
# Check relay_domains and recipient validation
postconf -h relay_domains relay_recipient_maps
# Check for deprecated restrictions still in active config
postconf -n | grep -E 'check_relay_domains|permit_mx_backup|permit_naked_ip_address|reject_maps_rbl'
How to diagnose it
flowchart TD
A["External client connects, port 25, no auth"] --> B["RCPT TO: external recipient"]
B --> C{"smtpd_relay_restrictions"}
C --> D{"permit_mynetworks match?"}
D -->|"Yes: mynetworks too broad"| E["250 OK: relay accepted"]
D -->|No| F{"permit_sasl_authenticated?"}
F -->|"Yes: SASL bypass"| E
F -->|No auth| G{"reject_unauth_destination present?"}
G -->|"No or after a PERMIT rule"| E
G -->|Yes, evaluated first| H["554 5.7.1 Relay access denied"]Step 1: Confirm the relay is actually happening
Run the smoking-gun scan from the quick checks above. Any line returned means an unauthenticated, non-local client successfully sent mail through your server to an external destination. This is a confirmed open relay.
If the scan returns nothing, verify relay probes are being denied:
grep 'relay access denied' /var/log/mail.log | tail -20
Zero denials with active SMTP traffic may indicate that restrictions are not firing at all or that logging is misconfigured.
Step 2: Audit mynetworks
postconf -h mynetworks mynetworks_style
If the output contains 0.0.0.0/0 or a CIDR broader than your actual network (for example, a /8 when you only need a /24), that is the open relay. The single most common cause is mynetworks = 0.0.0.0/0 left in place after testing.
Also note that at compatibility_level >= 2, the default mynetworks_style may have changed from subnet to host, meaning only the server’s own IP is trusted without an explicit mynetworks setting. If your config relied on the old subnet default and you upgraded without setting mynetworks explicitly, behavior may have shifted.
Step 3: Audit restriction order and enforcement
postconf -h smtpd_relay_restrictions smtpd_recipient_restrictions
postconf -h compatibility_level
postconf -h smtpd_relay_before_recipient_restrictions
The recommended production setting for smtpd_relay_restrictions is:
permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
The default on Postfix 2.10+ uses defer_unauth_destination instead of reject_unauth_destination. Both block unauthorized relay, but defer returns a 4xx temporary failure (client retries), while reject returns a 5xx permanent failure. For relay control, reject_unauth_destination is the recommended choice because it permanently stops unauthorized attempts.
If smtpd_relay_restrictions is empty, check compatibility_level. At compatibility_level below 1, Postfix uses a backwards-compatible empty default, meaning no relay enforcement from that parameter. Relay control then falls entirely to smtpd_recipient_restrictions. If that parameter also lacks proper enforcement, the server is open.
On Postfix 3.6+, smtpd_relay_before_recipient_restrictions controls evaluation order. At compatibility_level >= 3.6, relay restrictions evaluate first. Below that, recipient restrictions evaluate first, which is where the classic misordering open relay lives: a PERMIT-producing rule in smtpd_recipient_restrictions fires before reject_unauth_destination, granting relay to matching clients.
Step 4: Test from an external host
From a machine outside your mynetworks, connect to port 25 and attempt to relay to an external domain:
# Run from an EXTERNAL host only. Replace your-mta with your hostname.
telnet your-mta.example.com 25
EHLO test.example.net
MAIL FROM:<external@test.example.net>
RCPT TO:<test@example.net>
If the server responds 250 OK to the RCPT TO for an external domain, it is an open relay. A properly configured server returns 554 5.7.1 Relay access denied or a similar 5xx rejection.
Step 5: Check for deprecated and removed restrictions
Postfix 3.9 removed several directives that older configurations may still reference. If these are present, Postfix ignores them silently or logs a warning, and the relay behavior they enforced is no longer applied:
check_relay_domains(removed in 3.9, usereject_unauth_destination)permit_naked_ip_address(removed in 3.9, usepermit_mynetworks)reject_maps_rbl(removed in 3.9, usereject_rbl_client)permit_mx_backup(deprecated in 3.9, use explicitrelay_domains)
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
Successful relay without sasl_method | Confirms unauthorized mail flow | Any occurrence is PAGE |
| Relay denial rate | Indicates active probing; sudden absence means restrictions may not be firing | Drop to zero while traffic is present |
| SASL authentication failure rate | Brute-force or credential stuffing on submission ports | Spike from a single IP |
| Bounce rate | Relay abuse generates bounces that damage sender reputation | Spike correlating with relay activity |
| Outbound delivery volume | Relay abuse appears as unexpected outbound traffic | Volume exceeding legitimate baseline |
mynetworks configuration drift | Broadened trust range reopens relay silently | Any change without review |
Fixes
Narrow mynetworks
Restrict mynetworks to only the IP ranges that should relay without authentication:
# Destructive: changes relay policy. Review CIDR ranges before applying.
postconf -e 'mynetworks = 127.0.0.0/8, 192.168.1.0/24'
postfix reload
Never use 0.0.0.0/0 in mynetworks. If you need relay from dynamic or remote clients, require SASL authentication on port 587 instead.
Fix restriction order
Set smtpd_relay_restrictions explicitly with reject_unauth_destination as the final rule:
# Destructive: changes relay policy.
postconf -e 'smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination'
postfix reload
In smtpd_recipient_restrictions, ensure no PERMIT-producing rule (such as check_helo_access, check_client_access, or check_sender_access) appears before reject_unauth_destination unless you have a specific, reviewed reason. The safe pattern is to place reject_unauth_destination early in the list and put permissive checks after it.
Set compatibility_level and explicit restrictions after upgrade
If smtpd_relay_restrictions is empty due to a low compatibility_level:
# Destructive: changes defaults across multiple parameters.
# Read the Postfix COMPATIBILITY_README before raising compatibility_level.
postconf -e 'compatibility_level = 3.6'
postconf -e 'smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination'
postfix reload
Raising compatibility_level changes other defaults beyond relay control. Review the full set of changes in the Postfix COMPATIBILITY_README before applying.
Close a SASL bypass
If the SASL backend accepts empty or null credentials:
- Test authentication with an empty password from an external host on port 587.
- Ensure
smtpd_sasl_security_optionsincludesnoanonymous. - Set
smtpd_tls_auth_only = yesso authentication is not offered over plaintext connections. - Review the SASL backend configuration (Dovecot, Cyrus) for mechanism and password policy enforcement.
Fix a backup-MX hole
If your server acts as backup MX for domains in relay_domains:
- Configure
relay_recipient_mapsto validate recipients before accepting mail. - Without recipient validation, Postfix accepts mail for any address at the relayed domain, then generates bounces for invalid recipients. This creates backscatter and can be treated as relay abuse by blocklists.
- Remove
permit_mx_backupfrom your restrictions (deprecated in Postfix 3.9) and use explicitrelay_domainswithrelay_recipient_mapsinstead.
Prevention
- Audit relay configuration after every Postfix upgrade. Compatibility defaults change across versions and can silently alter relay enforcement.
- Set
smtpd_relay_restrictionsexplicitly. Never rely on defaults or backwards-compatible empty values. - Test from an external host regularly. A 30-second telnet test from outside your network catches misconfigurations before spammers do.
- Alert on the smoking-gun pattern. Monitor for
postfix/smtpdeliveries withstatus=sentwhere the corresponding queue ID has nosasl_method=and the client IP is non-local. - Review
mynetworkson every network change. Adding a new subnet, VPN range, or container network without updatingmynetworkscan open or close relay paths. - Keep recipient validation current on backup-MX servers. Stale
relay_recipient_mapscause backscatter and potential relay abuse.
How Netdata helps
- Queue depth trends distinguish legitimate outbound volume from a spam relay flood by showing whether deferred and active queues are growing abnormally alongside a traffic spike. See the deferred queue guide and active queue saturation guide.
- Per-second collection lets you correlate a sudden outbound delivery spike with the exact timestamp of a
postfix reloador configuration change. - Anomaly detection flags unusual spikes in outbound network activity and queue depth that may indicate relay abuse, even when individual log lines appear normal in isolation.
Related guides
- Postfix active queue saturation: hitting qmgr_message_active_limit
- Postfix backscatter storm: bounces to forged senders and blocklisting
- Postfix IP blocklisted: deliverability collapse and sender reputation
- Postfix bounce rate spike: 5xx failures, bad address lists, and reputation risk
- 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 daemon memory growth: leaking RSS and OOM risk
- Postfix deferred queue growing: why mail piles up and how to drain it
- Postfix destination concurrency limit: tuning per-destination delivery
- Postfix queue partition disk full: /var/spool/postfix out of space






