fixed site
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
+++
|
||||
date = '2025-08-01T10:03:15+02:00'
|
||||
draft = false
|
||||
title = 'Blocking Invalid Recipients Before They Reach Your Exchange Server'
|
||||
|
||||
|
||||
[cover]
|
||||
image = "/imgs/email-route.jpg"
|
||||
alt = "Email App icon on blue background"
|
||||
caption = ""
|
||||
+++
|
||||
|
||||
Recently, I had to deal with a serious problem: **backscatter**.
|
||||
One of our mail gateways ended up listed on the **backscatter.org** blacklist for sending bounce messages to forged senders.
|
||||
|
||||
After checking the logs, I quickly realized that our system wasn't actually protected against backscatter attacks, so I had to do something about it.
|
||||
|
||||
|
||||
|
||||
## What Even Is Backscatter?
|
||||
|
||||
Backscatter is unwanted email that your mail server sends **after** receiving a message, usually in the form of a **non-delivery report (NDR)** or **bounce** to a **forged sender address**.
|
||||
|
||||
It happens when:
|
||||
|
||||
- A spammer sends email with a **fake "From" address** (often an innocent third party).
|
||||
- Your mail server **accepts** the message first, but later discovers it’s undeliverable.
|
||||
- Your server sends a **bounce** to the forged address, hitting an innocent person instead of the spammer.
|
||||
|
||||
This makes your server appear to be sending spam, even though you're just bouncing bad mail.
|
||||
|
||||
|
||||
|
||||
## The Problem in Our Setup
|
||||
|
||||
Our mail gateway mostly relays mail to multiple internal Exchange Server clusters.
|
||||
We have a list of valid domains configured, so Postfix will only accept mail for those domains.
|
||||
|
||||
**The problem?**
|
||||
Postfix didn't know which individual recipients were valid on the downstream Exchange servers.
|
||||
That meant it would happily accept messages for **nonexistent users**, only to later bounce them, classic backscatter behavior.
|
||||
|
||||
|
||||
|
||||
## The Goal
|
||||
|
||||
We needed to reject mail **during the SMTP session**, ideally right after the `RCPT TO` command, if the recipient didn't exist on the Exchange servers.
|
||||
|
||||
That way, the sending server would get the rejection immediately, and we would never have to generate a bounce message.
|
||||
|
||||
|
||||
|
||||
## Possible Solutions I Considered
|
||||
|
||||
### **1. relay_recipient_maps**
|
||||
This would require maintaining a **full list of valid recipients** in a Postfix lookup table.
|
||||
It works well, but means writing and maintaining a script to **sync the list from Active Directory** on a regular basis.
|
||||
|
||||
For us, this was too much custom scripting, too fragile, and too messy to maintain.
|
||||
|
||||
|
||||
|
||||
### **2. virtual_mailbox_maps with LDAP**
|
||||
Another approach would be using **LDAP lookups** directly against Active Directory to verify recipients in real-time.
|
||||
|
||||
This can work in some setups, but:
|
||||
- It adds complexity and dependencies.
|
||||
- It can introduce security concerns.
|
||||
- It didn’t fit well with our environment.
|
||||
|
||||
So I ruled it out.
|
||||
|
||||
|
||||
|
||||
## The Solution: `reject_unverified_recipient`
|
||||
|
||||
While reading through the **Postfix Address Verification Howto**, I came across the `reject_unverified_recipient` option - bling! - exactly what I needed.
|
||||
|
||||
|
||||
|
||||
### **How It Works**
|
||||
|
||||
When an incoming SMTP session reaches the `RCPT TO` stage:
|
||||
|
||||
1. Postfix checks if `reject_unverified_recipient` is enabled for the recipient domain.
|
||||
2. If yes, it temporarily **probes the downstream mail system** to see if the recipient address exists.
|
||||
3. If the downstream system says:
|
||||
- **User exists** → Postfix continues processing.
|
||||
- **User does not exist** → Postfix **rejects immediately** with:
|
||||
```
|
||||
550 5.1.1 <user@example.de>: Recipient address rejected: User unknown
|
||||
```
|
||||
|
||||
Because the rejection happens **during SMTP**, no bounce is generated, and backscatter is avoided entirely.
|
||||
|
||||
|
||||
## Implementation in ISPConfig
|
||||
|
||||
In our case, the mail gateways run **Postfix** with **ISPConfig** as the management interface.
|
||||
I implemented a new configuration option in ISPConfig for **per-domain control** of `reject_unverified_recipient`, along with a **validation server** to specify for the downstream validation server.
|
||||
|
||||
### Specifying a Validation Server for Recipient Verification
|
||||
|
||||
One important detail is that Exchange servers cannot validate recipients over the default SMTP transport on port `25`. To enable recipient validation, you need to activate it on the Exchange server and use the Hub Transport service, which by default runs on port `2525`.
|
||||
|
||||
Make sure to restrict access to this port, as it requires anonymous login specifically for recipient validation, you don't want that exposed broadly.
|
||||
|
||||
> **Note:** This setup does not affect your regular mail flow. Only the SMTP probes used for verifying recipients are sent to this validation server.
|
||||
> Postfix enables this behavior with the `address_verify_transport_maps` option.
|
||||
|
||||
To optimize performance and reduce unnecessary verification probes for addresses that have already been checked, I configured a local cache on the mail gateway using the `address_verify_map` option. This way, repeated probes for the same recipient are avoided.
|
||||
|
||||
Now, for domains that need recipient verification, we can enable it in the panel and point Postfix to the appropriate **validation transport**.
|
||||
|
||||
|
||||
## The Result
|
||||
|
||||
After enabling `reject_unverified_recipient` and pointing it at the Exchange clusters, the backscatter stopped completely.
|
||||
We were no longer accepting messages for invalid recipients.
|
||||
|
||||
## Conclusion
|
||||
|
||||
If your Postfix server is acting as a relay for Exchange (or any downstream mail system) and you're struggling with **backscatter spam**, enabling `reject_unverified_recipient` can be a clean and effective fix.
|
||||
|
||||
It avoids maintaining large static recipient maps, works dynamically, and ensures that invalid mail is rejected **before** it ever gets into your system.
|
||||
|
||||
Reference in New Issue
Block a user