Postfix UCE HOWTO | ![]() |
Written by: Istvan Sebestyen <istvan at swissdent dot hu>
Last Modified: Fri Jul 22 13:53:04 CEST 2005
Spenden sind willkommen, wenn Sie dieses Howto hilfreich finden
In Postfix gibt es drei verschiedene Stufen:
Postfix verarbeitet die Beschränkungsphasen in folgender Reihenfolge:
smtpd_client_restrictions
smtpd_helo_restrictions
smtpd_sender_restrictions
smtpd_recipient_restrictions
smtpd_data_restrictions
Ich würde diese kurz erklären:
Ihr habt sicher gemerkt, dass in vielen Postfix Konfigurationen alle Beschränkungen unter smtpd_recipient_restrictions sind. Nun, dies hat auch einen Grund. Postfix führt standardmässig erst nach dem "RCPT TO:" Befehl die UCE-Filter durch, da die Variable smtpd_delay_reject auf "yes" gesetzt ist (wenn man diese nicht zuvor geändert hat). Ich empfehle nicht diese zu ändern, da einige SMTP Clients dies nicht unbedingt mögen werden (ich will jetzt nicht unbedingt auf die SMTP Clients von Microsoft zielen ;-)
Dies ist auch der Grund, warum smtpd_delay_reject=yes Standard ist. Es gibt nämlich (wirklich) einige MS SMTP Clients, welche nach dem HELO/EHLO umsonst ein REJECT bekommen würden, weil diese es nicht verstehen und dennoch die ganzen Daten senden würden. Wenn jemand z.B. ein 3MB grosses File herumschickt mit solch einem MS Client, dann würde der Client vergeblich vom Server nach dem HELO/EHLO schon ein REJECT bekommen, weil der dann schliesslich doch die Daten sendet. Darum ist in Postfix smtpd_delay_reject auf "yes" gesetzt.
Es ist wichtig, dass wir die Beschränkungen in richtiger Reihenfolge angeben, weil diese dann von Postfix so verarbeitet werden. So entscheidet er, ob er die Nachricht weitergeben soll oder stoppt.
Nachdem wir jetzt die Beschränkungsphasen angeschaut haben, werfen wir
einen Blick auf die Beschränkungen:
Die folgende Konfiguration werden wir zu einem kleinen Test verwenden:
smtpd_helo_required = yes
smtpd_client_restrictions =
smtpd_helo_restrictions =
smtpd_sender_restrictions =
smtpd_recipient_restrictions =
permit_mynetworks,
reject_unauth_destination,
reject_invalid_hostname,
reject_non_fqdn_sender,
reject_unknown_sender_domain,
reject_non_fqdn_recipient,
reject_unknown_recipient_domain,
reject_rbl_client relays.ordb.org,
reject_rbl_client cbl.abuseat.org,
Wie funktionieren denn genau die Beschränkungen unter Postfix? Mit was arbeitet er und woher weiss er welche Beschränkung wann dran ist? Schauen wir uns doch mal ein kleines Beispiel mit der oben stehenden Konfiguration an.
Der SMTP Client sendet sagen wir mal solch einen Envelope: MAIL FROM:<user@gibtsnicht.de>
Und gehen wir davon aus, dass die Domain gibtsnicht.de auch wirklich nicht existiert. Postfix wird die Beschränkungen in der oben stehenden Reihenfolge anschauen.
Das Beispiel:
| Beschränkung | Antwort |
|---|---|
| permit_mynetworks | DUNNO |
| reject_unauth_destination | DUNNO |
| reject_invalid_hostname | DUNNO |
| reject_non_fqdn_sender | DUNNO |
| reject_unknown_sender_domain | REJECT |
| reject_non_fqdn_recipient | |
| [..] | |
Der Client verbindet sich, gibt ein EHLO an den Server. Es gibt mehrere Beschränkungen, die der Server sich anschauen muss, dies macht er in der korrekten Reihenfolge:
Der TCP/IP Client ist nicht in $mynetworks drin, somit geht Postfix zur nächsten Beschränkung.
Der Hostname im EHLO wird geprüft von reject_invalid_hostname, ob dieser eine richtige Syntax hat. Da die richtig ist, gibts ein DUNNO als Antwort.
Es trifft auf reject_unauth_pipelining nicht zu, daher wird es weitergegeben.
Da user@gibtsnicht.de in FQDN Form ist, trifft reject_non_fqdn_sender nicht zu.
Die nächste Beschränkung, reject_unknown_sender_domain sieht sich MAIL FROM an und löst den Domain Namen der angegebenen Email Adresse auf. Da es keine solche Domain gibt, antwortet Postfix hier mit REJECT. Die Antwort des SMTP Servers:
450 <user@gibtsnicht.de>: Sender address rejected: Domain not found
Nach dem kommen reject_unknown_recipient_domain und noch weitere Beschränkungen, aber diese sind nicht interessant, weil die Verbindung schon zurückgewiesen wurde. Alle weiteren Beschränkungen werden nicht angeschaut.
Noch etwas wichtiges: Bei den verschiedenen Beschränkungsphasen
gibts im Normalfall immer eine Beschränkung, bei der man als
Parameter maptype:mapname angeben muss. Wenn wir verschieden Regeln
auflisten, dann können diese folgende Ergebnisse haben: OK, DUNNO,
REJECT oder sowas wie "554 Geh weg." (3 stelliger Code und Antwort).
Wenn nun eine Regel stimmt und das Target DUNNO ist, dann
bedeutet das soviel, dass Postfix nicht entscheiden kann was passiert,
deshalb beendet er die Analyse und springt zur nächsten
Beschränkung.
Schauen wir ein Beispiel an. Sagen wir, dass bei den Beschränkungen
folgende Beschränkung zu finden ist:
check_sender_access pcre:/etc/postfix/sender_checkDer Inhalt dieses Files:
/domain\.de$/ DUNNO /^mail\.domain\.de$/ DUNNO /^spammer\.de$/ REJECT
Wenn eine Email kommt von mail.domain.de, dann matcht diese sowohl mit der ersten, als auch mit der Zweiten Regel. Die zweite Regel, wird aber von Postfix nicht angeschaut, weil bei der ersten schon ein DUNNO zurückgegeben wurde und somit hat Postfix aufgehört das File zu parsen und springt zur nächsten Beschränkung. Es ist immer sinnvoll bei Regular Expressions mit einem "^" und einem "$" den Ausdruck zu begrenzen, nicht dass ungewollte Fehler auftreten. In diesem Fall könnte ja foodomain.de und bardomain.de auch mit /domain\.de$/ übereinstimmen. Das oben angegebene Beispiel dient hiermit nur als Vorstellung für dieses Problem und sollte nicht verwendet werden (jedenfalls nicht ohne "^" und "$").
Sehen wir mal das ganze im SMTP Protokoll an. Die Parameter:
SMTP Client:
Address: 111.111.111.111
Hostname: gibtsnicht.de
Prefix: >>
SMTP Server:
Address: 222.222.222.222
Hostname: domain.tld
Prefix: <<
Nun die Verbindung selber:
<< 220 mail.domain.tld ESMTP
>> EHLO localhost -----
<< 250-domain.tld |
<< 250-PIPELINING | -> smtpd_delay_reject=yes
<< 250-SIZE 10240000 |
<< 250-ETRN | Hier werden die definierten
<< 250 8BITMIME | Beschränkungen noch nicht
>> MAIL FROM:<user@gibtsnicht.de> | angeschaut.
<< 250 Ok |
>> RCPT TO:<user@domain.tld> ----- -> Hier wird alles gecheckt.
|
permit_mynetworks -> DUNNO
|
[...]
|
reject_non_fqdn_sender -> DUNNO
reject_unknown_sender_domain -> REJECT
|
-----
<< 450 <user@gibtsnicht.de>: Sender address rejected: Domain not found
>> DATA
<< 554 Error: no valid recipients
>> QUIT
<< 221 Bye
Wenn Ihr dieses Beispiel nicht versteht, schaut mal im RFC 821 nach (RFC=Request for Comments). Dort wird erläutert wie eine SMTP Verbindung ausschauen sollte.
Was man noch wissen sollte... Wenn die Email durch alle Beschränkungen durch ist, gibts noch ein permit am Schluss. Dies ist Standard. Das heisst, dass es bei den Beschränkungen überall ein DUNNO als Antwort bekommt, am Schluss hängt Postfix noch ein permit, somit bekommt die Email ein OK und die Email kann zugestellt werden. Wenn man nicht will, dass die Email nach den Beschränkungen ein OK bekommt, kann man in der Konfigurationsdatei noch ein reject an den Schluss anhängen. Dies ist natürlich ein bisschen gefährlich und man sollte wissen, was man tut.
Bisher haben wir nur die HELO/EHLO, MAIL FROM und RCPT TO Befehle von der SMTP Verbindung angeschaut. Diesen folgt jetzt DATA.
Die header_checks, mime_header_checks und body_checks kommen nach dem DATA Befehl der SMTP Verbindung, wenn Postfix den "." am Schluss bekommen hat. header_checks, mime_header_checks und body_checks gehören nicht zu smtpd_*_restrictions sondern sind selber Beschränkungsphasen. Man verwendet dazu meistens zwei Maptype's: pcre und regexp.
header_checks braucht noch Parameter, die so aussehen: maptype:mapname. Ein Beispiel:
header_checks pcre:/etc/postfix/maps/header_checks.pcre
Im header_checks.pcre file könnte eine Zeile so aussehen:
/^<HEADER>:.*inhalt/ VORGEHEN
In der Praxis:
/^From:.*abuser@domain\.tld$/ REJECT
Welche Header es gibt, kann man in der Source einer Email nachschauen, dort findet man sicher genügend Header. Es gibt einige Methoden für das VORGEHEN, die sind definiert:
REJECT: Dies ist das gewöhnliche Vorgehen, das am meisten verwendet
wird. Die Email wird zurückgewiesen. Man kann nach REJECT noch
einen Text angeben, das in den Logs zu sehen ist, was auch der
Absender bekommt.
Bsp: /^Subject:.*gratis/ REJECT Ich zahl' lieber.
Alle Emails die im Subject "gratis" enthalten werden gefiltert
und zurückgewiesen mit "Ich zahl' lieber".
IGNORE: Dieses Vorgehen nimmt den Header aus der Email raus, weist
diese aber nicht zurück.
Bsp: /^X-Mailer:/ IGNORE
Wir nehmen alle Header mit "X-Mailer" raus, weil wir evt. nicht
wissen wollen mit welchem MUA (=Mail User Agent) die Email
geschickt wurde.
WARN: Dieses Vorgehen ist sehr nützlich, wenn wir neue header_checks
ausprobieren wollen. Es gibt lediglich nur einen Eintrag ins
Logfile, die Mails werden weiterhin zugestellt.
Bsp: /^Subject:.*geld/ WARN
Wir schauen an, ob diese Filterregel nützlich ist, dafür
müssen wir die Logfiles öffnen.
HOLD: Hält die Emails in der Queue, bis der Admin sagt, was mit
denen passiert. Dies könnte nützlich sein, wenn wir die
Nachrichten nicht zurückweisen wollen, aber auch nicht, dass
der Benutzer diese sofort bekommt.
Bsp: /^Subject:.*Kündigung/ HOLD
Jede Nachricht deren Subject "Kündigung" enthält wird auf
HOLD gesetzt und bleibt in der Queue, bis der Admin entscheidet
ob diese zugestellt oder gelöscht wird.
DISCARD: Dieses Vorgehen simuliert die Zustellung einer Nachricht,
obwohl diese in Wirklichkeit gelöscht wird. Dies ist sinnvoll,
wenn man nicht will, dass der betroffene Absender oder Server
weiss, was mit der Nachricht wirklich passiert.
Bsp: /^Subject:.*Rechnung/ DISCARD
Löscht die Nachrichten, die im Subject "Rechnung" enthalten.
FILTER: Erlaubt, dass man einen anderen Server oder Filter angibt wie
im Fall von transport Map. Dies ist nützlich wenn wir nur
Nachrichten mit bestimmten Header filtern wollen.
Bsp: /^Subject:.*Virus/ FILTER smtp:10025
Übergibt die Nachrichten, welche im Subject "Virus" enthalten
dem SMTP (Server) auf Port 10025. In den meisten Fällen ist
amavis auf diesem Port zu finden.
Der Parameter zu header_checks:
header_checks = pcre:/etc/postfix/maps/header_check.pcre
Schauen wir mal den Inhalt dieses Files an:
/^Subject:.*100\% Free/ REJECT Woah! Free? /^From:.*spammer@domain\.de/ REJECT Geh weg, Spammer. /^X-Mailer:.*Microsoft/ REJECT Get a _real_ MUA.
Wichtig: Die oben stehenden Beispiele sind nicht unbedingt nützlich für den Einsatz, die stehen lediglich als Beispiele. Verwendet die nur, wenn Ihr versteht, was Ihr macht. Sonst verwendet doch bitte WARN anstatt REJECT.
Postfix hat in den Versionen 2.x eine neue Beschränkungsphase, nämlich mime_header_checks. Dies macht eigentlich genau das gleiche wie header_checks, nur für die Attachments. Die Parameter für mime_header_checks:
mime_header_checks pcre:/etc/postfix/maps/mime_header_check.pcre
Der Inhalt dieses Files:
/name=\"?(.*)\.(exe|bat)\"?$/ REJECT Unwanted attachment/Unerwuenschter Anhang $1.$2 /name=[^>](screensaver|movie)\.zip/ REJECT Sobig Virus gefunden.
Und body_checks funktioniert auch etwa in dieser Art, nur muss man am Anfang nichts angeben. Die Parameter zu body_checks:
body_checks = pcre:/etc/postfix/maps/body_check.pcre
Der Inhalt dieses Files:
/See the attached file for details/ REJECT Sobig Virus gefunden. /Get your free/ REJECT Free? No, thanks.
Auch die header_checks, mime_header_checks und body_checks gehen in Reihenfolge vor. Ein Beispiel:
Nehmen wir an wir haben im header_checks.pcre File folgende Zeilen:
/^Subject:.*Hallo/ REJECT Bye-bye. /^From:.*chef@domain\.de/ OK
Und sehen wir uns mal an, was passiert, wenn unser Chef uns eine Nachricht mit dem Subject "Hallo" schreibt:
<< 220 mail.domain.de ESMTP
>> EHLO host.domain.de
<< 250-mail.domain.de
<< 250-PIPELINING
<< 250-SIZE 10240000
<< 250-ETRN
<< 250 8BITMIME
>> MAIL FROM:<chef@domain.de>
<< 250 Ok
>> RCPT TO:<user@domain.de>
<< 250 Ok
>> DATA
<< 354 End data with <CR><LF>.<CR><LF>
>> To:user@domain.de
>> Subject:Hallo
>>
>> Tach auch
>> . -----
| Nur nach dem Schluss"." prüft
| Postfix die Header und Body.
|
| -> header_checks
| -> mime_header_checks
| -> body_checks
|
-----
<< 550 Error: Bye-bye.
>> QUIT
<< 221 Bye
Also, wie wir sehen ist die Nachricht nicht angekommen, sondern wurde verworfen. Wir haben vergeblich in unserem header_check.pcre File, dass chef@domain.de Emails verschicken kann, weil davor die Nachricht ein REJECT erhält, die Error-Meldung ist: Bye-bye. Wie wir auch angegeben haben.
Tipp: OK vor REJECT oder am besten zuerst WARN.
Es gibt sehr viele Freemail Provider, die gratis eine
Email-Dienstleistung anbieten. Viele Spammer profitieren leider von
diesem "Angebot" (einige dieser Provider: hotmail, yahoo, gmx, bigfoot,
etc...). Die meisten Spammer benützen eine ungültige Freemail
Adresse, damit Sie Ihre Werbung verschicken können. Kann man
eigentlich gegen diese Art von Spams etwas unternehmen? Natürlich!
Der Trick ist der folgende:
Da die meisten Spammer wahrscheinlich ein Script für das
Verschicken von mehreren Tausend Emails brauchen, benützen sie
wahrscheinlich nicht die Freemail Server, um von denen aus die Mails zu
verschicken, sondern entweder einen Open-Relay SMTP Server, oder einen,
von dem aus sie die Berechtigung haben Emails zu verschicken (meistens
sind es aber Open-Relay SMTP Server).
Wenn man z.B. von Hotmail aus eine Email schickt, dann verbindet sich
einer der Hotmail Server mit unserem Postfix SMTP Server und schickt die
Email ab. Wir können daher nachvollziehen (in unseren Logfiles)
welche Domain oder welcher Hostname die Verbindung zu unserem SMTP
Server aufgebaut hat. Es ist im Fall von Hotmail ein Server in der
hotmail.com Domain (hostname.hotmail.com). Die meisten Spammer
würden also einen Absender mit einem Account von hotmail.com
vortäuschen, aber in den Logfiles könnten wir nachschauen und
feststellen, dass die SMTP Verbindung nicht von einem hotmail.com Server
stammt. Wir können deshalb diese gefälschten Nacrhichten
filtern, indem wir eine eigene restriction class dafür definieren:
smtpd_restriction_classes =
freemail_hotmail
freemail_msn
freemail_yahoo
Dann müssen wir noch angeben, was diese Klassen machen müssen:
freemail_hotmail =
check_client_access pcre:/etc/postfix/maps/freemail_hotmail
freemail_msn =
check_client_access pcre:/etc/postfix/maps/freemail_msn
freemail_yahoo =
check_client_access pcre:/etc/postfix/maps/freemail_yahoo
Wir müssen noch ein File machen, in dem wir die Domain Namen von diesen Freemail Sites angeben. Das File können wir unter /etc/postfix/maps/freemail_check anlegen. Der Inhalt dieses Files:
hotmail.com freemail_hotmail msn.com freemail_msn yahoo.com freemail_yahoo
Und noch in der Beschränkungsphase smtpd_recipient_restrictions dies auch angeben:
smtpd_recipient_restrictions =
[..]
check_sender_access hash:/etc/postfix/maps/freemail_check,
[..]
Nun haben wir alles angepasst, werfen wir doch einen Blick auf den Inhalt der freemail_(provider) Files, wie es aussehen sollte:
/(^|\.)provider\.tld$/ DUNNO /./ REJECT You claim to be from provider.tld but your mail didn't come from a provider.tld server.
Wenn also der Absender eine Email-Adresse von provider.tld benutzt,
schaut Postfix nach, ob der Client auch von einem provider.tld Server
kommt. Wenn ja, hört er auf das File zu parsen (wegen dem DUNNO)
und schaut sich die nächsten Beschränkungen an. Wenn der
Client nicht von provider.tld stammt und der erste Regular Expression
nicht übereinstimmt, dann geht Postfix zum nächsten. Weil die
zweite Linie auf alles matcht, verwirft Postfix die Nachricht mit dem
oben liegenden Text.
Schauen wir doch am besten ein Beispiel an. Nehmen wir an, dass sich
jemand bei uns mit einer yahoo.com Email-Adresse ausgibt. Das File
freemail_yahoo sieht also so aus:
/(^|\.)yahoo\.com$/ DUNNO /./ REJECT You claim to be from yahoo.com but your mail didn't come from a yahoo.com server.
Die Parameter für die SMTP Verbindung:
SMTP Client:
Adresse: 111.111.111.111
Hostname: host.domain.de
Prefix: >>
SMTP Server:
Adresse: 222.222.222.222
Hostname: mail.domain.de
Prefix: <<
Die Verbindung würde so ausschauen:
<< 220 mail.domain.de ESMTP >> EHLO host.domain.de << 250-domain.de << 250-PIPELINING << 250-SIZE 10240000 << 250-ETRN << 250 8BITMIME >> MAIL FROM:<123456@yahoo.com> << 250 Ok >> RCPT TO:<user@domain.de> << 554 <host.domain.de[111.111.111.111]>: Client host rejected: You claim to be from yahoo.com but your mail didn't come from a yahoo.com server. >> DATA << 554 Error: no valid recipients >> QUIT << 221 Bye
Bevor man andere Freemail Server definiert, sollte man sich
vergewissern, ob die wirklich auch über deren eigene Domain die
Emails verschicken, meistens ist das der Fall, aber man soll ja
schliesslich nichts dem Zufall überlassen. Aber spätestens dann, wenn diese Freemail Server POP3/IMAP Dienstleistung (gratis) anbieten, sollte man diese Option lieber weglassen (es sei denn, dass auch ein SMTP Dienst angeboten wird, weil dann die Emails doch vom Freemail Server kommen).
http://www.securitysage.com/guides/postfix_uce.html
http://www.mengwong.com/misc/postfix-uce-guide.txt
http://jimsun.linxnet.com/misc/postfix-anti-UCE.txt
http://www.arschkrebs.de/postfix/
http://www.postfix.org/uce.html
http://www.postfix.org/docs.html
Copyright (c) 2003 Istvan Sebestyen <istvan at swissdent dot hu> All rights reserved.
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the Author.