Translate all posts to German with personal blog style
Build & Deploy / deploy (push) Successful in 32s
Build & Deploy / deploy (push) Successful in 32s
This commit is contained in:
@@ -1,126 +1,98 @@
|
||||
+++
|
||||
date = '2025-08-01T10:03:15+02:00'
|
||||
draft = false
|
||||
title = 'Blocking Invalid Recipients Before They Reach Your Exchange Server'
|
||||
|
||||
title = 'Backscatter ade: Ungültige Empfänger vor dem Exchange abfangen'
|
||||
|
||||
[cover]
|
||||
image = "/imgs/email-route.jpg"
|
||||
alt = "Email App icon on blue background"
|
||||
alt = "E-Mail App Icon auf blauem Hintergrund"
|
||||
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.
|
||||
Neulich hatte ich ein richtig fieses Problem: **Backscatter**. Einer unserer Mail-Gateways landete auf der **backscatter.org**-Blacklist, weil wir Bounce-Nachrichten an gefälschte Absender geschickt haben. Ja, genau so läuft das: man will ja eigentlich nur Mails zustellen und plötzlich ist man selber der Spammer.
|
||||
|
||||
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.
|
||||
Nach einem Blick in die Logs war mir klar: Unser System war gegen Backscatter-Attacken so gut geschützt wie ein Fahrradschloss aus Pappe. Also musste was passieren.
|
||||
|
||||
## Was zur Hölle ist Backscatter?
|
||||
|
||||
Backscatter ist Müll, den dein Mail-Server **verschickt, nachdem** er eine Nachricht angenommen hat – meistens in Form eines **Non-Delivery Reports (NDR)** oder Bounces an eine **gefälschte Absenderadresse**.
|
||||
|
||||
## What Even Is Backscatter?
|
||||
Passiert so:
|
||||
|
||||
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**.
|
||||
- Ein Spammer schickt 'ne Mail mit ner **fake "Von"-Adresse** (oft von nem armen Unschuldigen).
|
||||
- Dein Server **nimmt die Mail an**, stellt aber später fest: "Hoppla, den Empfänger gibt's gar nicht."
|
||||
- Dein Server schickt nen **Bounce** an die gefälschte Absenderadresse – und trifft damit den Falschen.
|
||||
|
||||
It happens when:
|
||||
Und Zack, dein Server versendet Spam, ohne es zu wollen. Willkommen im Club.
|
||||
|
||||
- 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.
|
||||
## Das Problem bei uns
|
||||
|
||||
This makes your server appear to be sending spam, even though you're just bouncing bad mail.
|
||||
Unser Mail-Gateway leitet hauptsächlich Mails an mehrere interne Exchange-Cluster weiter. Klar, wir haben eine Liste mit gültigen Domains – Postfix nimmt nur Mail für diese Domains an.
|
||||
|
||||
**Das Problem?** Postfix wusste nicht, welche einzelnen Empfänger auf den Exchange-Servern gültig sind. Also hat es fröhlich Mails für **nicht existierende Benutzer** angenommen, um sie dann später zu bouncen. Klassischer Backscatter.
|
||||
|
||||
## Das Ziel
|
||||
|
||||
## The Problem in Our Setup
|
||||
Wir wollten Mails **während der SMTP-Session** ablehnen – idealerweise direkt nach dem `RCPT TO`-Befehl, wenn der Empfänger auf dem Exchange nicht existiert.
|
||||
|
||||
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.
|
||||
Dann kriegt der Sender sofort einen Korb und wir müssen erst gar keinen Bounce generieren. Win-Win.
|
||||
|
||||
**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
|
||||
## Mögliche Lösungen (und warum ich sie verworfen hab)
|
||||
|
||||
### **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.
|
||||
Dafür hätte ich ne **komplette Liste aller gültigen Empfänger** in Postfix pflegen müssen. Klar, geht. Aber dann müsste ich ein Skript schreiben, das die Liste regelmäßig aus Active Directory synchronisiert.
|
||||
|
||||
For us, this was too much custom scripting, too fragile, and too messy to maintain.
|
||||
Für uns war das zu viel Gefrickel, zu fehleranfällig und zu nervig zu warten.
|
||||
|
||||
### **2. virtual_mailbox_maps mit LDAP**
|
||||
LDAP-Lookups direkt gegen Active Directory, um Empfänger in Echtzeit zu prüfen. Klingt erstmal gut, aber:
|
||||
|
||||
- Mehr Komplexität und Abhängigkeiten.
|
||||
- Potenzielle Sicherheitsrisiken.
|
||||
- Hat nicht so richtig in unsere Umgebung gepasst.
|
||||
|
||||
### **2. virtual_mailbox_maps with LDAP**
|
||||
Another approach would be using **LDAP lookups** directly against Active Directory to verify recipients in real-time.
|
||||
Also auch gestrichen.
|
||||
|
||||
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.
|
||||
## Die Lösung: `reject_unverified_recipient`
|
||||
|
||||
So I ruled it out.
|
||||
Beim Durchlesen der **Postfix Address Verification Howto** bin ich über `reject_unverified_recipient` gestolpert – und dachte sofort: "Digga, genau das brauch ich!"
|
||||
|
||||
### **Wie es funktioniert**
|
||||
|
||||
Wenn ne eingehende SMTP-Session die `RCPT TO`-Phase erreicht:
|
||||
|
||||
## 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:
|
||||
1. Postfix checkt, ob `reject_unverified_recipient` für die Empfängerdomäne aktiv ist.
|
||||
2. Wenn ja, wird kurz **beim downstream Mail-System angefragt**, ob die Adresse existiert.
|
||||
3. Antwort vom downstream System:
|
||||
- **User existiert** → Postfix macht weiter.
|
||||
- **User existiert nicht** → Postfix **lehnt sofort ab** mit:
|
||||
```
|
||||
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.
|
||||
Weil die Ablehnung **während des SMTP-Dialogs** passiert, wird gar kein Bounce generiert. Backscatter ade!
|
||||
|
||||
## Umsetzung in ISPConfig
|
||||
|
||||
## Implementation in ISPConfig
|
||||
Bei uns laufen die Mail-Gateways mit **Postfix** und **ISPConfig** als Verwaltungsoberfläche. Also hab ich ne neue Konfigurationsoption in ISPConfig eingebaut, mit der man `reject_unverified_recipient** **pro Domain** steuern kann – plus einen **Validation Server** für den downstream-Server.
|
||||
|
||||
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.
|
||||
### Validation Server für die Empfängerprüfung
|
||||
|
||||
### Specifying a Validation Server for Recipient Verification
|
||||
Wichtiges Detail: Exchange-Server können standardmäßig keine Empfänger über SMTP-Port `25` validieren. Man muss die Funktion erst auf dem Exchange aktivieren und den Hub Transport Service nutzen – der läuft standardmäßig auf Port `2525`.
|
||||
|
||||
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`.
|
||||
Unbedingt den Zugriff auf diesen Port einschränken! Der erlaubt nämlich anonyme Logins für die Empfängervalidierung – das will man nicht in der freien Wildbahn haben.
|
||||
|
||||
Make sure to restrict access to this port, as it requires anonymous login specifically for recipient validation, you don't want that exposed broadly.
|
||||
> **Achtung:** Das ändert nichts an deinem normalen Mail-Flow. Nur die SMTP-Probes für die Empfängerprüfung gehen an diesen Validation Server.
|
||||
> Postfix macht das mit der `address_verify_transport_maps`-Option.
|
||||
|
||||
> **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.
|
||||
Für die Performance hab ich noch nen lokalen Cache auf dem Gateway eingerichtet (`address_verify_map`), damit nicht ständig dieselben Empfänger neu geprüft werden. Spart Nerven und Resourcen.
|
||||
|
||||
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.
|
||||
Jetzt können wir für alle Domains, die eine Empfängerprüfung brauchen, das Ding im Panel anschalten und Postfix ans richtige **Validation Transport** schicken.
|
||||
|
||||
Now, for domains that need recipient verification, we can enable it in the panel and point Postfix to the appropriate **validation transport**.
|
||||
## Das Ergebnis
|
||||
|
||||
Seit `reject_unverified_recipient` aktiv ist und auf die Exchange-Cluster zeigt, ist der Backscatter komplett weg. Wir nehmen keine Mails mehr für ungültige Empfänger an. Feierabend.
|
||||
|
||||
## 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.
|
||||
## Fazit
|
||||
|
||||
Wenn dein Postfix als Relay für Exchange (oder ein anderes downstream-Mail-System) läuft und du **Backscatter-Spam** loswerden willst: `reject_unverified_recipient` ist der Weg. Sauber, dynamisch, keine großen statischen Listen – und vor allem: die Drecksmail kommt erst gar nicht rein.
|
||||
|
||||
Reference in New Issue
Block a user