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 includes 0.0.0.0/0 or 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 with compatibility_level below 3.6, this evaluates before smtpd_relay_restrictions, which can produce an open relay if a permissive rule (such as check_helo_access returning PERMIT) short-circuits before reject_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

CauseWhat it looks likeFirst thing to check
mynetworks too broadRelay succeeds from any external IP without authpostconf -h mynetworks
Restrictions in wrong orderPERMIT rule fires before reject_unauth_destinationpostconf smtpd_recipient_restrictions
Empty smtpd_relay_restrictions after upgradeNo relay enforcement from that parameterpostconf -h compatibility_level smtpd_relay_restrictions
SASL bypassAuth backend accepts null or empty credentialsTest AUTH with empty password on port 587
Backup-MX without recipient validationAccepts mail for any address at relayed domains, then bouncespostconf -h relay_domains relay_recipient_maps
Deprecated restrictions still in configPostfix 3.9+ ignores removed directivespostconf -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, use reject_unauth_destination)
  • permit_naked_ip_address (removed in 3.9, use permit_mynetworks)
  • reject_maps_rbl (removed in 3.9, use reject_rbl_client)
  • permit_mx_backup (deprecated in 3.9, use explicit relay_domains)

Metrics and signals to monitor

SignalWhy it mattersWarning sign
Successful relay without sasl_methodConfirms unauthorized mail flowAny occurrence is PAGE
Relay denial rateIndicates active probing; sudden absence means restrictions may not be firingDrop to zero while traffic is present
SASL authentication failure rateBrute-force or credential stuffing on submission portsSpike from a single IP
Bounce rateRelay abuse generates bounces that damage sender reputationSpike correlating with relay activity
Outbound delivery volumeRelay abuse appears as unexpected outbound trafficVolume exceeding legitimate baseline
mynetworks configuration driftBroadened trust range reopens relay silentlyAny 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:

  1. Test authentication with an empty password from an external host on port 587.
  2. Ensure smtpd_sasl_security_options includes noanonymous.
  3. Set smtpd_tls_auth_only = yes so authentication is not offered over plaintext connections.
  4. 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:

  1. Configure relay_recipient_maps to validate recipients before accepting mail.
  2. 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.
  3. Remove permit_mx_backup from your restrictions (deprecated in Postfix 3.9) and use explicit relay_domains with relay_recipient_maps instead.

Prevention

  • Audit relay configuration after every Postfix upgrade. Compatibility defaults change across versions and can silently alter relay enforcement.
  • Set smtpd_relay_restrictions explicitly. 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/smtp deliveries with status=sent where the corresponding queue ID has no sasl_method= and the client IP is non-local.
  • Review mynetworks on every network change. Adding a new subnet, VPN range, or container network without updating mynetworks can open or close relay paths.
  • Keep recipient validation current on backup-MX servers. Stale relay_recipient_maps cause 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 reload or 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.