Nach langer Zeit gibt es heute mal wieder einen kleinen Post aus der Sysadmin-Ecke.
Die Ausgangslage
Ein Benutzer liefert seine Emails mit Authentifizierung bei einem durch mich betriebenen Mailserver ein, der für die entsprechende Domain zuständig ist.
In den Headern dieser Mail wird nun die IP-Adresse auftauchen, von der aus die Email eingeliefert wurde. Dies kann die IP zu Hause sein, die von einem Bekannten oder die von einer Institution. Postet derjenige häufiger auf Mailinglisten kann man so schon ein Profil erstellen und bekommt auf jeden Fall heraus, dass er z.B. Emails von der Uni aus sendet, etc.
Dies möchte man nun verhindern - und das funktioniert mit postfix Bordmitteln sogar relativ einfach.
Mehr Information ist am Ende doch weniger
Zunächt müssen wir die entsprechenden Header erkennen können. Da bei allen nicht-authentifizierten Emails die IP-Adresse des einliefernden MTA im Header unverändert erhalten bleiben soll, schon um Spammer identifizieren zu können ohne extra in die Logs schauen zu müssen, brauchen wir einen Weg, die passenden Received:-Header zu erkennen. Dies erreichen wir, indem wir dem postfix sagen, dass er den Benutzernamen des Absenders auf dem Mailserver in den Header einfügen soll. Dies geschieht über die Anweisung smtpd_sasl_authenticated_header = yes in der Datei main.cf des postfix.
Unser header sieht nun ungefähr so aus:
Received: from [192.168.101.150] (guest123.guest.example.org [192.0.43.10]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: username) by mail.somedomain.tld (Postfix) with ESMTPSA id 32A59B1C032 for; Thu, 30 Jun 2011 12:36:07 +0200 (CEST)
Die hervorgehobene Zeile ist neu hinzugekommen und ermöglicht es uns im zweiten Schritt nach genau diesen Headern zu suchen.
pcre ftw!
postfix bietet dafür die Möglichkeit der header_checks. Damit kann man mittels (perl) regular expressions auf den Headern der Email arbeiten und Zeilen einfügen, Zeilen ändern und eigentlich vor allem Aktionen auslösen wie das Aufhalten einer Email, Abweisen, Weiterleiten, etc.
Wir benutzen diese Möglichkeiten, um auf der oben gezeigten Received:-Zeile ein paar Ersetzungen vorzunehmen.
Dazu stellen wir zunächst sicher, dass die main.cf des Postfix auch header checks aktiviert hat:
smtpd_sasl_authenticated_header = yes ... header_checks = pcre:/etc/postfix/header_checks mime_header_checks = pcre:/etc/postfix/header_checks
Nun koennen wir in der angegebenen Datei header_checks mit folgender Zeile das Umschreiben aktivieren:
/^Received:\ from (.*)\(.*\)(.*)\(Authenticated\ sender:\ .*\)(.*by mail\.somedomain\.tld.*)$/U REPLACE Received: from $1 (Remote IP hidden) $2(Sender was authenticated on somedomain.tld) $3
Hinweis: Die Zeile ist relativ lang, beim Kopieren aufpassen sie komplett zu erwischen. Wichtig ist die Option U an der Regex, diese schaltet sie auf ungreedy. Siehe man pcre_table.
Der Name des Mailservers taucht hier nochmal auf, damit ich die Original-IP bei extern eingelieferten Emails nicht verwerfe - das kann zum Identifizieren von Spammern helfen, auch wenn die Header oft gefälscht sind.
Im Ergebnis sieht der Header der Email nun aus wie folgt:
Received: from [192.168.101.150] (Remote IP hidden) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) (Sender was authenticated at somedomain.tld) by mail.somedomain.tld (Postfix) with ESMTPSA id A36241184685 for; Fri, 29 Jul 2011 20:23:31 +0200 (CEST)
Wenn man die private IP auch noch entfernen möchte, kann man sich jetzt natürlich einen weiteren Header-check überlegen, der auf '\[.*\].*Remote IP hidden' triggert und diese ersetzt. Das kann im Einzelfall notwendig werden, wenn kaputte Antispam-Maßnahmen anderer Empfänger solche Emails ablehnen.
Wenn man misstrauisch ist fügt man ausserdem noch eine Zeile hinzu, die jedes Vorkommen von '(Authenticated sender: ...)' mit etwas belanglosem ersetzt, falls man unter allen Umständen die internen Nutzernamen geheim halten will.