Artur Södler Software-Qualität

Projektbeispiel Mailserver


Schritt 1: Ist-Analyse

Haben Sie sich schon einmal über Spam-Mails geärgert?

Klar doch. Am besten also gleich alles, was verdächtig ist, automatisch wegsortieren. Dann wird das Leben leichter.

Denkfehler! Spätestens, wenn die E-Mail ihrer Frau im Spam-Eimer gelandet ist, die ihnen mitteilen wollte, sie sollen bitte die Kinder aus dem Kindergarten abholen. Nun ist guter Rat teuer: wir brauchen eine teurere, bessere Spam-Lösung. "Vertrauen" ist nun das Schlagwort, mit denen uns "Sicherheitsfachleute" ihre Lösungen aufdrängen wie Finanzdienstleister riskante Wertpapiere.

Wir müssen umdenken, die bisherigen Konzepte hinterfragen: Wenn wir schon eine E-Mail in den Mülleimer werfen, warum haben wir dann vorher den Empfang bestätigt? Wenn Ihr Mailserver die E-Mail abgelehnt hätte, dann wäre Ihre Frau postwendend informiert gewesen, hätte zum Telefonhörer gegriffen und die Sache mit dem virtuellen Nudelholz geregelt. Immerhin werden die Kinder dann pünktlich abgeholt.

Ärgerlich ist nur, dass alle handelsüblichen Mailserver erst einmal den Eingang einer E-Mail bestätigen. Nun sind Sie doch in der Pflicht, und müssen den Spam-Ordner regelmäßig durchsehen.

Was mache ich, wenn der Mail-Server ausfällt?

Auch diese Frage haben Sie sich sicher schon gestellt. Schlimmstenfalls kann der Mail-Speicher mit einer stinkenden kleinen Elektronik-Rauchwolke geleert werden. Ein Ersatz-PC und die nächtliche Datensicherung bringen uns wieder ins Rennen, aber die E-Mail Ihrer Frau ist ebenfalls weg.

Wir müssen umdenken, die bisherigen Konzepte hinterfragen: Warum bestätigt der Mail-Server den Eingang der Mail, wenn die E-Mail noch nicht auf der Bandsicherung im Tresor ist?

Schritt 2: Forschung und Kreativität

Wie kann ich E-Mails nicht annehmen?

Das SMTP-Protokoll zur Übertragung von E-Mails schreibt vor, dass der Einwurf jeder Nachricht mit einer dreistelligen Nummer bestätigt wird. Nummern zwischen 200-299 heißen "OK", 300-399 heißen "bisher gut, aber mach bitte weiter", 400-499 sind temporäre Fehler, und 500-599 sind endgültige Fehler.
Das Greylisting-Verfahren nutzt dies: Jeder Mail-Einwurf wird mit einem Fehler 4xx beantwortet. Spam-Roboter geben es in der Regel sofort auf, ernsthafte Mailserver senden erneut. Der zweite Einwurf wird akzeptiert.

Leider kommen auf diese Weise E-Mails verzögert an. Die Zeitspanne bis zur Wiederholung kann schon ein paar Minuten sein.

Hinterfragen wir: Wenn die E-Mail nun gleich beim ersten Mal angenommen wird? Wir antworten zwar trotzdem so, als ob es einen temporären Fehler gäbe, nur nutzen wir die Zwischenzeit zur Spamprüfung, zur Datensicherung und für was auch immer — und wenn wir am Ende entschieden haben, dass wir die E-Mail annehmen wollen, dann antworten wir mit "200 ok". Wenn nicht, mit "500 E-Mail abgelehnt".

Das klingt doch praktikabel: Was im Spam-Ordner landet, wird auch abgelehnt. Damit sind Sie endlich die Verantwortung los, den Spam-Ordner regelmäßig durchzusehen.

Schritt 3: Planung

Was also benötigen wir?

Wir brauchen zwei Datenbanken an zwei physisch getrennten Standorten (für Datensicherung), zwei Mailserver an zwei physisch getrennten Standorten (für Sicherung der Erreichbarkeit), und eine Menge Software drumherum.

Eine E-Mail wird beim Server A gespeichert und mit einem "temporären Fehler" abgelehnt. Wenn der Sender den Einwurf beim Server B wiederholt (A hatte ja einen "temporären Fehler"), wird Server B im Idealfall bereits die E-Mail kennen, und auch wissen, ob sie angenommen oder abgelehnt werden soll. Ist der Sender aber schneller, muss auch Server B diese E-Mail speichern und mit "temporärem Fehler" ablehnen.

Wir brauchen also ein Datenmodell, bei dem keiner der beiden Server die alleinige Herrschaft über einen Nummernkreis oder über die Identität zweier E-Mails hat. Die beiden Server müssen gleichberechtigt sein, um eigenständig funktionieren zu können, und die Identität zweier E-Mails muss an ihrem Inhalt erkannt werden können.

Der SMTP-Server ist eine eigenständige Software, weil er auch dann korrekt arbeiten soll, wenn Backup, Spam-Prüfung und POP3/IMAP-Server streiken. Er muss rund um die Uhr bereitstehen und hat nach der Datenbank den höchsten Qualitätsanspruch.

Backup, Spam-Prüfung und POP3/IMAP-Server können vorübergehend inaktiv sein. Besonders die zahlreichen Formatfehler der Spam-E-Mails stellen eine Herausforderung dar, der nicht jeder Programmierer gewachsen ist. Da ist es gut, wenn die Spam-Prüfung im Debugger laufen kann, während E-Mails immer noch angenommen werden.

E-Mails werden in Kernbestandteile zerlegt, die ihre Eindeutigkeit leicht erkennen lassen, und Randbestandteile, die sie vervollständigen oder den Einwurf dokumentieren. Die Datenbank kennt Tabellen mit Datensätzen, die jeweils ein Freitextfeld beliebiger Länge haben können:

• body  der E-Mail-Inhalt
• capture  alle SMTP-Daten eines Einwurfs
• config  Konfiguration des Mailservers und der Postfächer
• header  ein E-Mail-Header ohne alle "received:"-Zeilen
• mail  eine eindeutige E-Mail
• mailbox  ein Empfänger-Postfach
• msgid  die (optionale) Message-ID der E-Mail
• pop3  ein POP3- oder SMTP-Mail-Account
• rdns  Reverse-DNS-Lookup und andere Informationen zur Sender-IP-Adresse
• receive  eine E-Mail in einem Postfach
• received  die "received:"-Zeilen des Headers
• text  diverse Texte wie Benutzernamen, Passwörter, Zeitsteuerungen, Handynummern
• throw-in  alle Daten eines Einwurfs und Protokoll der Antwort

Die Datenbank beherrscht als Mindestanforderung auf allen Tabellen nur Transaktionen im Sinne von:

• find-or-insert  finde diesen Inhalt (und gib die alte Datensatznummer zurück)
 — oder — 
füge diesen Inhalt ein (und gib die neue Datensatznummer zurück)
• find  finde diesen Inhalt (und gib den Datensatz zurück)
 — oder — 
finde nicht und teile dies mit
• set, increment  finde diesen Inhalt, ändere ihn (und gib die Datensatznummer zurück)
 — oder — 
finde nicht und teile dies mit

Außerdem hat sie einen Zeitstempel-Mechanismus, um geänderte Datensätze aufzufinden.

Schritt 4: Dokumentation

Die Dokumentation findet in Verzeichnissen statt, die später bei der Entwicklung auch die Quellcodes enthalten werden. Die Dokumentation ist in der Quellcode-Versionsverwaltung gespeichert. Bei der Dokumentation des Projekts tauchen Detail-Fragen auf, zum Beispiel:

• Welche Datenbank ist geeignet?
• Wie können race conditions verhindert werden, wenn zwei Datenbanken unterschiedliche Zustände eines Postfachs kennen?
• Welche Teile können auf welchen Plattformen laufen?
• Wie können Prozesse debuggt werden, wenn der Programmablauf von Datenströmen dritter Parteien abhängig ist?
• Wie können Prozesse überwacht werden?
• Welche Sicherheitsmaßnahmen müssen ergriffen werden, um unberechtigten Zugriff auf die Datenbank (den Server, die Postfächer) zu verhindern?
• Wie können die Postfächer von den Anwendern konfiguriert werden?
• Wie können Spam-Mails absortiert und durchsucht werden?

Im Verlauf der Dokumentation ändert sich das Projekt nochmals grundlegend:

• Auf die Datenbank kann über das Internet zugegriffen werden.
Dadurch können Prozesse zeitweise auch am Arbeitsplatz des Entwicklers laufen.
• Die Datenbank-Verbindungen erhalten eine proprietäre Verschlüsselung.
• Der Zeitstempel-Mechanismus der Datenbank bleibt nach außen verborgen.
Dafür synchronisiert die Datenbank aktiv ihre Inhalte in ein Backup.
• Aus dem Backup des "gegenüber"-Hosts wird die eigene Datenbank ergänzt. Mails, die in beiden Datenbanken identisch gefunden werden, werden als "gesichert" markiert.
• Felder der Tabellen sind entflochten, sodass nur voneinander unabhängige Status-Spalten vorkommen.
• Merkmalsausprägungen werden so sortiert, dass beim Synchronisieren die Faustregel "nimm den höheren Wert von beiden" gilt.
• Statt einer Oberfläche zur Konfiguration entscheidet man sich für die Konfiguration über E-Mails.
• Der Prozess zur Mail-Prüfung bekommt Kommandozeilen-Parameter, um den Status einzelner Mails zu manipulieren.
• Zusätzlich gibt es ein Datenbank-Utility, mit dem der Status der letzten E-Mails aufgelistet werden kann und E-Mails exportiert werden können.
• Eine SMS-Benachrichtigungsfunktion wirft am Ende das Prinzip gleichwertiger Server doch noch um. Um zu verhindern, dass zwei SMS gleichzeitig ausgelöst werden, bekommt Server B eine Wartezeit von einer Minute, bevor er seine SMS auslöst. Bis dahin sollte er von Server A erfahren haben, dass die SMS bereits ausgelöst wurde.
• Das failover für den POP3-Client bei Ausfall eines Mailservers wird nicht automatisiert: Die Mail-IDs des zweiten Mailservers unterscheiden sich, der Mail-Client könnte ungelöschte E-Mails nach einem failover doppelt sehen.

Schritt 5: Realisierung und Test

Alle Programme sind so geschrieben, dass sie unverändert unter Linux und Windows laufen, als 32-Bit- wie als 64-Bit-Programme. Als Kommandozeilen-Programm können sich alle unter Windows als Dienst registrieren, ebenso wie als Daemon unter Linux.

Für die Portabilität wird das Programm nicht mit Makros in verschiedene Fassungen gebracht, wie dies bei Microsoft üblich ist (#define TCHAR: char oder wchar_t), sondern es werden bestehende Bibliotheken eingesetzt und weiterentwickelt, die identische Programme an die Betriebssysteme anpassen. Windows-Unicode-Funktionen mit ihrer UTF-16-Kodierung werden an den UTF-8-Standard der Applikation angepasst.

Für den SMTP-Server haben wir zu Beginn exzessiv Protokolle eingesetzt, um bei evtl. Abstürzen möglichst viel Informationen über die Ursachen zu haben. Diese haben geholfen, eine denial-of-service-Verteidigungsstrategie nachzubessern, und einen Verbindungsabbruch wegen einer fehlformatierten E-Mail zu verhindern.

Für eine Übergangszeit haben wir SMTP-Daten über eine TCP-Weiterleitung mitgeschrieben und zum alten Mailserver geleitet. Die mitgeschnittenen Daten dienten dann als Testdaten.

Schritt 6: Zufriedenheit des Kunden

Diesmal sind wir selbst die eigenen Kunden. Nichtsdestotrotz sind wir mit dem Ergebnis zufrieden:

• Spam-Mails werden abgelehnt. Deshalb müssen wir sie nicht mehr durchsehen. Spätestens nach 1 Stunde (ohne Wiederholung nach 24 Stunden) wird über die bis dahin aufgelaufenen Spam-Mails gesammelt informiert.
• Andere Mailserver hatten bereits eine SMS-Benachrichtigung, leider aber ungefiltert, auch für Spam-Mails, auch mitten in der Nacht. Nun können wir nach Hotline-Kunden und nach Tageszeit unterscheiden.
• Eine Version von Outlook versteht das Format einer anderen Version von Outlook nicht. Durch Anpassung des POP3/IMAP-Servers können wir die verantwortliche Kopfzeile herauslöschen, und müssen nicht mehr um erneuten Versand in anderem Format bitten.
• Unser früherer Dienstleister für die Spam-Filterung filterte Mails unserer Kunden weg. Um E-Mails der Kunden sicher zu empfangen, waren wir gezwungen, die Spam-Prüfung abzuschalten. Wir filtern nun selbst, finden zwar nicht mehr alles, dafür wird keine einzige erwünschte E-Mail mehr für Spam gehalten.
• E-Mails zusätzlich auf das Smartphone leiten? Kein Problem, wir können den Mailserver anpassen.
• Zeitweise waren 300 Spam-Mails am Tag der Schnitt, in einigen Fällen zählten wir fast 2.000 Spam-Mails pro Tag. Na und?
• Die Miete der Server kostet monatlich 10,- €, eine zusätzliche Datensicherung ist nicht nötig. Die beiden Server werden zusätzlich für andere — ebenfalls redundante — Dienste genutzt.

Wenn Sie den Mailserver testen wollen, senden Sie uns einfach eine E-Mail.

 
Artur Södler Software Qualität