JOHANNES KEPLER UNIVERSITAT¨ LINZ JKU

Technisch-Naturwissenschaftliche Fakult¨at

Untersuchung von verschl¨usselterE-Mail- Kommunikation nach Spam und Viren

MASTERARBEIT

zur Erlangung des akademischen Grades Diplom-Ingenieur

im Masterstudium Netzwerke und Sicherheit

Eingereicht von: Michael Grundmann Bakk.techn., 0656189

Angefertigt am: Institut f¨urInformationsverarbeitung und Mikroprozessortechnik

Beurteilung: O.Univ.-Prof. Dr. J¨org R. M¨uhlbacher Assoz.Prof. Mag. iur. Dipl.-Ing. Dr. Michael Sonntag

Mitwirkung: Dipl.-Ing. Dr. Rudolf H¨ormanseder

Linz, September 2012 Kurzfassung

Ohne eine Überprüfung von E-Mail-Nachrichten nach unerwünschten (Spam) oder gefährlichen Inhalten (Viren, Phishing) ist das Betreiben oder Benutzen eines Mail-Dienstes nicht mehr vorstellbar. Da immer mehr und sensiblere Daten übertragen werden, wird auch die Verschlüs- selung des Mail-Transports immer wichtiger. Diese Verschlüsselung ist sicherheitstechnisch eine sinnvolle Entwicklung, die aber der benötigten Überprüfung der Mails entgegenstehen kann, wenn die Mail-Analyse beim »Betreten« oder »Verlassen« des eigenen Netzwerkes erfolgen soll. Diese Arbeit zeigt eine Möglichkeit, eine solche Inhaltsanalyse auch bei Verwendung von Verschlüsselung vorzunehmen. Dabei wird trotz TLS-Verschlüsselung, die zwischen den Mailservern zur Absicherung des SMTP-Transportweges aufgebaut wird, die Inhaltsanalyse mit Hilfe einer vertrauenswürdigen Zertifizierungsstelle ermöglicht. Hierbei werden bestehende SMTP-Proxy-Lösungen auf solche Funktionalität hin untersucht und als Konsequenz der Untersuchung wird eine Eigenentwicklung vorgestellt. Dazu werden die Eigenheiten von SMTP vorgestellt, soweit diese bei der Implementierung eines Proxy und der Verwendung von TLS relevant sind. Bei der Realisierung wurde darauf Wert gelegt, dass der Proxy die Sicherheit erhöht, aber dabei in keinem Fall ein nicht vorhandenes Sicherheitsniveau vortäuscht. Auch soll die Funktionalität und das Verhalten, besonders in Fehlerfällen, genau der Kommunikation ohne Proxy entsprechen. Diese Schwerpunkte ergeben sich aus der Anforderung des Projekts zur Integration des SMTPS-Proxy in die Firewall der Firma Underground_81.

1http://www.underground8.com Abstract

Operating or using an electronic mail service is hardly imaginable anymore without checking the electronic mail messages for unwanted (spam) or dangerous (virus, phising) content. Due to the need to transmit more and sensitive data, encryption of the mail transport is becoming increasingly widespread. While this is a reasonable development, it might contradict the necessary checking of the mail messages, if this should happen when they “enter” or “leave” the own network. This thesis shows a way to enable such a checking, even when using TLS encryption. A trusted Certificate Authority (CA) allows for an analysis of the content despite the encryption used by mail servers to secure the SMTP transport. It includes an investigation into existing SMTP proxy solutions and whether they are able to support this functionality which leads to a self-developed solution. Features of the SMTP protocol which are relevant to the implementation of a proxy and the usage of TLS encryption will be presented. The implementation takes care that the proxy increases the security but in no case pretends a non-existing security level. The functionality and behavior, especially in error-cases, should match that of a communication without the proxy. These key aspects arise from the requirements of the project to integrate the SMTPS proxy into the firewall of the company Underground_8. Danksagung

An dieser Stelle möchte ich meinen Dank dem Institut für Informationsverarbeitung und Mikroprozessortechnik aussprechen. Im Besonderen danke ich dem Institutsvorstand O.Univ.- Prof. Dr. Jörg R. Mühlbacher und Assoz.Prof. Mag. iur. Dipl.-Ing. Dr. Michael Sonntag für die Betreuung dieser Diplomarbeit. Ebenfalls möchte ich mich bei Dipl.-Ing. Dr. Rudolf Hörmanseder für die fachliche Unterstützung der Masterarbeit bedanken.

Ohne die Unterstützung durch meine Kolleginnen und Kollegen bei der Firma Underground_8 wäre diese Arbeit nicht möglich gewesen. Im Speziellen gilt hier mein Dank Dipl.-Ing. Roman Aspetsberger, der mir sowohl technisch als auch inhaltlich eine große Hilfe war.

iii Inhaltsverzeichnis

1 Einleitung 1 1.1 Ausgangslage ...... 1 1.2 Gliederung der Arbeit ...... 1

2 Das Simple Mail Transfer Protocol 3 2.1 Aufbau des Simple Mail Transfer Protocol ...... 3 2.1.1 Ablauf einer SMTP-Session ...... 4 2.1.2 Ende einer SMTP-Session ...... 5 2.1.3 Behandlung des end of mail-Indikators ...... 6 2.1.4 SMTP-Kommandos ...... 6 2.1.5 SMTP Return Codes ...... 10 2.1.6 Bespiele für den Ablauf von SMTP-Sitzungen ...... 12 2.1.7 Verlässlichkeit ...... 13 2.1.8 Mail-Routing ...... 14 2.1.9 Timeouts ...... 16 2.2 SMTP-Proxy ...... 17 2.3 Proxy-Unterstützung für (E-)SMTP-Funktionalität ...... 18 2.4 SMTP-Proxy vs. Relay ...... 18 2.4.1 Regelung des Zugriffs ...... 18 2.4.2 Verantwortlichkeit für Mail-Nachrichten ...... 19 2.4.3 Verwaltung einer Warteschlange ...... 19 2.5 STARTTLS-Erweiterung ...... 19

3 Vorhandene SMTP-Proxy-Lösungen 22 3.1 ProxSMTP/ClamSMTP ...... 22 3.2 Anti-Spam-SMTP-Proxy-Server (ASSP) ...... 22 3.3 Hermes ...... 23 3.4 BarricadeMX ...... 23 3.5 qpsmtpd ...... 24 3.6 Evaluation ...... 25

4 TLS-Proxy-Engine von Underground_8 27 4.1 Aufbau des TLS-Proxy ...... 27 4.1.1 Multithreading ...... 27 4.1.2 Anbindung der Content-Filter ...... 30 4.1.3 Verbindungsablauf ...... 30

iv Inhaltsverzeichnis v

4.1.4 Zertifikate ...... 33 4.1.5 Erweiterbarkeit für weitere Protokolle ...... 34 4.1.6 Der TPROXY-Patch ...... 35 4.2 Erweiterung des TLS-Proxy ...... 35 4.2.1 RFC-konforme Fehlermeldungen ...... 35 4.2.2 Gemeinsam genutzte Zertifizierungsstelle ...... 36 4.2.3 Relay ...... 36 4.2.4 Erzwingen von TLS ...... 36 4.2.5 Hinterlegen von Zertifikaten ...... 37

5 Entwurf 38 5.1 Aufgabenstellung ...... 38 5.2 Einsatzszenarien ...... 39 5.2.1 Interne Clients verwenden beliebige externe Mailserver ...... 39 5.2.2 Interne Mailserver empfangen Mails von externen Servern ...... 40 5.2.3 TLS-Sessions trotz fehlender TLS-Unterstützung am Server ...... 40 5.2.4 Zentraler SMTP-Relay-Server ...... 40 5.3 Design ...... 41 5.3.1 Struktur ...... 41 5.3.2 Zertifizierungsstelle ...... 41 5.3.3 Anbindung der Content-Filter ...... 41 5.3.4 TLS-Funktionalität ...... 43 5.3.5 Relay ...... 44 5.3.6 Black-/Whitelists ...... 44 5.3.7 Fehlerbehandlung ...... 44 5.3.8 Behandlung von Timeouts ...... 45

6 Implementierung 46 6.1 Entwicklungsumgebung ...... 46 6.2 Verwendete Bibliotheken ...... 46 6.3 Einbindung der SMTP-Funktionalität ...... 47 6.4 Verbindungsablauf im TLS-Proxy ...... 48 6.4.1 Verwaltung von Sockets und TLS-Session ...... 48 6.4.2 Threads ...... 49 6.4.3 Proxy-Objekte ...... 50 6.4.4 Connection Tracking ...... 51 6.5 Ausgelagerte Zertifizierungsstelle ...... 53 6.5.1 Kernfunktionalität der Zertifizierungsstelle ...... 54 6.5.2 Initialisierung ...... 55 6.5.3 Signalbehandlung ...... 56 6.5.4 Threadverwaltung in der Zertifizierungsstelle ...... 57 6.6 Blocking vs. Non-Blocking I/O ...... 58 6.6.1 Multiplexing-I/O mit select ...... 59 6.6.2 OpenSSL und Non-Blocking-Sockets ...... 59 6.6.3 Verwendung im TLS-Proxy ...... 60 6.7 Protokollhandler für SMTP ...... 61 6.7.1 Struktur des SMTP-Handlers ...... 61 Inhaltsverzeichnis vi

6.7.2 SMTP-Data und SMTP-Dialog ...... 62 6.7.3 Multiplex-I/O ...... 62 6.7.4 Limits ...... 63 6.7.5 Behandlung von Verbindungsabbrüchen ...... 63 6.7.6 Behandlung von STARTTLS ...... 64 6.7.7 Relay ...... 67 6.7.8 Weiterleitung ohne Untersuchung ...... 68 6.7.9 Behandlung sonstiger Kommandos ...... 69 6.8 Hinterlegung von Zertifikaten ...... 70 6.8.1 Verwaltung der hinterlegten Zertifikate ...... 70 6.8.2 Aufbau einer Zertifikatsdatei ...... 71 6.8.3 Verwendung ...... 72

7 Konfigurationsoptionen 75 7.1 Allgemeine Optionen ...... 75 7.2 SSL/TLS-Optionen ...... 78 7.3 SMTP Optionen ...... 81 7.4 Optionen für die Zertifizierungsstelle ...... 83

8 Tests 85 8.1 Testwerkzeuge ...... 85 8.1.1 swaks ...... 85 8.1.2 OpenSSL s_client ...... 85 8.2 Testumgebung ...... 86 8.3 Non-TLS-Tests ...... 87 8.3.1 Grundlegender Test des Mail-Versands ...... 87 8.3.2 Filtern von SMTP-Kommandos und Antworten ...... 88 8.4 TLS-Tests ...... 89 8.4.1 Grundlegender TLS-Test ...... 89 8.4.2 STARTTLS mit On-The-Fly-Zertifikat ...... 90 8.4.3 Server kündigt keine STARTTLS-Unterstützung an ...... 90 8.4.4 Server präsentiert ungültiges oder abgelaufenes Zertifikat ...... 91 8.4.5 CA ist nicht erreichbar ...... 91 8.4.6 STARTTLS mit hinterlegtem Zertifikat ...... 91 8.4.7 Relay zu mailrelay.test.underground8.com ...... 92 8.5 Pass-Through ...... 93 8.5.1 Konfigurationsparameter ...... 93 8.5.2 Erwartete Funktionalität ...... 93 8.5.3 IP in Whitelist ...... 94 8.5.4 Hostname in Whitelist ...... 94 8.5.5 Client-Zertifikate ...... 94 8.6 Forced-TLS-Tests ...... 94 8.6.1 Konfigurationsparameter ...... 95 8.6.2 Serverseitiges Erzwingen von TLS ...... 95 8.6.3 Clientseitiges Erzwingen von TLS ...... 96

9 Handbuch zur Systemintegration 98 Inhaltsverzeichnis vii

9.1 Installation ...... 98 9.1.1 Softwareabhängigkeiten ...... 98 9.1.2 Installation auf einem Linux-System ...... 98 9.1.3 Statisches Linken der OpenSSL-Bibliotheken ...... 100 9.1.4 Grundkonfiguration ...... 101 9.2 Konfiguration der Szenarien ...... 104 9.2.1 Anpassen der Grundkonfiguration ...... 104 9.2.2 Interne Clients verwenden beliebige externe Mailserver ...... 105 9.2.3 Interne Mailserver empfangen Mails von externen Servern ...... 106 9.2.4 Interne Clients verbinden sich zum internen Server über den Proxy . . . 107 9.2.5 Zentraler SMTP-Relay-Server ...... 108

10 Zusammenfassung und Ausblick 110 10.1 Zusammenfassung ...... 110 10.2 Ausblick ...... 111

Glossar 112

Tabellenverzeichnis 115

Abbildungsverzeichnis 116

Quellcodeverzeichnis 118

Literaturverzeichnis 122

Internetquellen 126

Erklärung

Lebenslauf Kapitel 1

Einleitung

1.1 Ausgangslage

Die automatisierte Untersuchung von E-Mail-Kommunikation nach Spam und Viren ist zu einer Notwendigkeit geworden. Dies wird auch im McAfee Threats Report aus dem zweiten Quartal 2011 deutlich [56, Seite 15]. Darin wird zum Beispiel das Spam-Aufkommen mit 1–5 Billionen Nachrichten pro Tag beziffert. Das ist vor allem relevant, da der Aufwand, der zum manuellen Aussortieren von Spam betrieben werden muss, die Produktivität negativ beeinflusst. Auch wird E-Mail immer mehr zur Verbreitung von Viren genutzt. Die Anforderungen an die Vertraulichkeit und Integrität der E-Mail-Übertragung stehen jedoch im Widerspruch zu dieser Automatisierung, insbesondere da diese meist durch Ver- schlüsselung abgedeckt werden. Verschlüsselte Verbindungen können aber normalerweise nicht am Übertragungsweg (z. B. an einer Firewall oder einem Proxy) untersucht werden und müssen deshalb meist ohne Untersuchung durchgelassen oder zur Gänze blockiert werden. Roman Aspetsberger stellt in seiner Masterarbeit „Trusted Person in the Middle: TLS- Proxy“ [Asp09] einen Lösungsansatz vor, der von der Firma Underground_8 als TLS-Proxy- Lösung zur Untersuchung von HTTPS-Verbindungen in die U8-Firewall integriert wird. Ziel dieser Arbeit ist es, diese Lösung weiterzuentwickeln und um die Unterstützung für das Simple Mail Transfer Protocol (SMTP) zu erweitern.

1.2 Gliederung der Arbeit

Der erste Teil dieser Arbeit umfasst die theoretischen Grundlagen für einen SMTPS-Proxy (Kapitel 2). Dazu gehören eine Betrachtung des Mail-Protokolls SMTP im Kontext mit SMTP-Proxys. Auch ist ein Vergleich von SMTP-Proxy und SMTP-Relay enthalten. Eine Untersuchung der STARTTLS-Erweiterung1 für SMTP und die Evaluierung vorhandener SMTP-Proxy-Lösungen im Hinblick auf die Möglichkeit der Verwendung von Transport Layer

1Ermöglicht das Aushandeln von TLS-Verschlüsselung auf Klartextverbindungen (STARTTLS)

1 1. Einleitung 2

Security (TLS) schließt das Kapitel 3 ab. In Kapitel 4 wird die Struktur der bereits vorhandenen TLSProxy-Engine der Firma Underground_8 beschrieben. Insbesondere wird auf die Erweiterbarkeit für weitere Protokolle neben dem Hypertext Transfer Protocol (HTTP) eingegangen. Weiters werden die gewünschten Erweiterungen für den TLS-Proxy vorgestellt. Gefordert waren die Unterstützung des SMTP- Protokolls, das Auslagern der Zertifizierungsstelle für eine gemeinsame Nutzung durch alle TLS-Proxys, die Möglichkeit, Nachrichten über ein Mail-Relay anstatt direkt an den Zielserver zuzustellen, sowie das Erzwingen von TLS-Sessions auf Client- oder Server-Seite. In Kapitel 5 wird die Aufgabenstellung detailliert beschrieben, die Struktur der SMTP- Unterstützung im Proxy erläutert, und es werden wichtige Designentscheidungen begründet. Auch wird untersucht, wie die Content-Filter (Viren-, Spamfilter) an den Proxy angebunden werden sollen und wie eine zentrale Zertifizierungsstelle realisiert werden kann. Kapitel 6 stellt die Implementierung des SMTPS-Proxy2 genauer vor. Die verwendeten Ent- wicklungswerkzeuge sowie die Zielplattform werden präsentiert und wichtige Codeausschnitte erläutert. Kapitel 8 enthält den speziell für den Proxy entwickelten Testplan, der das erwartete Ver- halten des SMTPS-Proxy unter Berücksichtigung der Konfigurationsmöglichkeiten beschreibt. Die zum Testen verwendeten Werkzeuge sowie die Testergebnisse werden ebenfalls präsentiert. Kapitel 9 enthält ein Handbuch zur Installation, Konfiguration und Benutzung des SMTPS- Proxy und zur Integration in konkrete Einsatzszenarien.

2Die verschlüsselte Variante des Simple Mail Transfer Protocols (SMTPS) Kapitel 2

Das Simple Mail Transfer Protocol

2.1 Aufbau des Simple Mail Transfer Protocol

Dieses Kapitel beschreibt das Simple Mail Transfer Protocol (siehe RFC 821 [Pos82], bzw. RFC 5321 [Kle08]), seine Kommandos und Konzepte, soweit sie für einen SMTP- bzw. SMTPS-Proxy relevant sind oder das Verständnis unterstützen. SMTP ist für den Transport von elektronischen Mail-Nachrichten, sogenannten Mail Objects, zuständig. Der Sender benutzt SMTP, um seine Nachricht an einen SMTP-Server zu übergeben. Dieser Server kann entweder direkt der Host des Empfängers, ein passender SMTP-Server oder sogar der Host des Senders sein. Um eine Mail-Nachricht zustellen zu können, gibt der SMTP-Client (im Normalfall der Sender der Nachricht) dem SMTP-Server folgende Informationen: Die Herkunft der Nachricht (Reverse-Path) und das/die Ziel(e) der Nachricht sowie die Nachricht selbst. Der SMTP-Server kann sowohl Sender als auch Empfänger ablehnen oder akzeptieren. Der Server kann einen Empfänger auch dann akzeptieren, wenn er die Nachricht weiterleiten muss. Diese Übernahme einer Nachricht und die Weiterleitung wird SMTP-Relay genannt. Auf diese Weise kann eine Mail-Nachricht während ihrer Weiterleitung mehrere SMTP-Server passieren. Die zu transportierenden Mail Objects setzen sich aus den Komponenten Envelope und Content zusammen.

• Der Envelope besteht aus einer Reihe von SMTP-Kommandos, die zumindest die Quelle und das Ziel bzw. die Ziele spezifizieren. • Der Content besteht wiederum aus zwei Teilen: dem Header und dem Body. Der genaue Aufbau ist in RFC 822 [Cro82] bzw. RFC 5322 [Res08] festgelegt.

SMTP ist ein textbasiertes Protokoll, in dem Client und Server Kommandos und Sta- tusinformationen jeweils als eine Zeile darstellen. Diese Kommandos bestehen aus einem Kommandowort mit vier Zeichen und optional aus Kommandoparametern welche mit einem Leerzeichen (SP für space) vom Kommandowort getrennt werden. Die maximale Länge einer

3 2. Das Simple Mail Transfer Protocol 4

Envelope HELO MAIL FROM: RCPT TO: DATA Content From: Header To: Date: Subject:

Mail Text Body

QUIT

Abbildung 2.1: Aufbau von Mail-Objects, die mit SMTP transportiert werden

Kommandozeile (inklusive Kommandowort und abschließendem CRLF) beträgt 512 octets. Kommandos und Parameter sind, mit Ausnahme des Mailbox local-part1, nicht case-sensitive. Die Antworten bestehen aus einem dreistelligen numerischen Code für die maschinelle Verar- beitung und einem Text, der die Antwort genauer beschreibt. Der Client wertet die Antwort alleine auf Basis des numerischen Codes aus. Der Text kann als Status- bzw. Fehlermeldung an die Benutzer weitergereicht werden. SMTP-Kommandos und Antworten werden zeilenweise gesendet und mit einem Carriage- Return (CR) + Line-Feed (LF) abgeschlossen. Durch das Alter von SMTP ist anzumerken, dass die Zeichen des 7-Bit-US-ASCII-Zeichensatzes [Cer69] verwendet werden. Das bedeutet, dass auch bei einem 8-Bit-Übertragungskanal die 7 Bit in Least Significant Bit = niederwertigstes Bit (LSB) bis Most Significant Bit = höchstwertiges Bit (MSB) -1 übertragen werden und das MSB auf 0 gesetzt werden muss.

2.1.1 Ablauf einer SMTP-Session

Zu Beginn einer SMTP-Session, also nach dem Aufbau der TCP-Verbindung2, in der die SMTP-Session abgewickelt wird, sendet der Server eine Willkommensnachricht. Dieser Reply auf den TCP-Verbindungsaufbau mit Code 220 kann Informationen zur und zum Versionsstand bekanntgeben3. Der Server kann an dieser Stelle die SMTP-Verbindung ablehnen, indem er anstatt eines 220-Codes den Wert 554 sendet. Beenden darf er die SMTP-Verbindung aber erst auf Kommando des Clients (siehe Abschnitt 2.1.2). Auch der Client stellt sich vor, indem er das Kommando HELO oder EHLO (falls er das

1Eine Mailbox wird in der Form local-part@domain angegeben. 2Transmission Control Protocol (TCP) 3Diese Informationen können aber auch für mögliche Angreifer von Vorteil sein und sind deshalb mit Vorsicht zu verwenden. 2. Das Simple Mail Transfer Protocol 5

Extended Simple Mail-Transfer-Protocol (ESMTP) unterstützt) sendet. Als Parameter übergibt er seine Identifikation (typischerweise die Domäne). Wenn der Server ein EHLO empfängt, kann er in der Antwort mit Code 250 dem Client mitteilen, welche SMTP-Erweiterungen er unterstützt. An dieser Stelle sind beide Teilnehmer der Session bereit, eine Mail-Transaktion zu beginnen. Diese besteht aus folgenden Schritten: • Als Start der Transaktion sendet der Client ein MAIL-Kommando und identifiziert damit den Absender. • Der Server kann den Absender nun mit dem Antwort-Code 250 bestätigen oder mit Code 4xx bzw. 5xx ablehnen. Eine genaue Auflistung der Antwort-Codes findet sich in Abschnitt 2.1.4 bzw. 2.1.5. Wurde der Absender bestätigt, kann der Client mit einem oder mehreren RCPT-Kommandos Empfänger angeben. Der Server hat auch hier die Möglichkeit, einzelne Empfänger zu bestätigen oder abzulehnen. • Mit dem Kommando DATA leitet der Client nun die Übertragung des Mail-Content ein. Nachdem der Server das Data-Kommando mit Code 354 bestätigt hat, überträgt der Client den Content, welcher durch den end of mail-Indikator abgeschlossen wird. Dieser Indikator wird durch eine Zeile bestehend nur aus einem Punkt dargestellt (siehe auch Abschnitt 2.1.3). • Sobald der Server den Content mit dem Code 250 bestätigt hat, ist er für die weitere Zustellung der Nachricht verantwortlich. Nach der Transaktion kann der Client entweder mit einem neuerlichen Mail-Kommando eine neue Transaktion beginnen oder mit dem Kommando QUIT die Session beenden.

2.1.2 Ende einer SMTP-Session

Normalerweise endet eine SMTP-Session, wenn der Client das QUIT-Kommando sendet und der Server darauf mit einem Code 221 antwortet. Der Server schließt daraufhin die TCP- Verbindung. Der Server darf von sich aus die Verbindung nur in folgenden Ausnahmefällen beenden: • Wenn der Server feststellt, dass er den SMTP-Service beenden muss, muss er noch versuchen, dem Client vor Verbindungsabschluss eine Code-421-Antwort zu senden. • Der Server darf die Verbindung auch beenden, falls beim Warten auf ein Client- Kommando oder auf Daten vom Client ein Timeout (siehe Abschnitt 2.1.9) aufgetreten ist. In RFC5321 [Kle08] wird explizit erwähnt, dass ein SMTP-Server die Verbindungen nicht abbrechen darf, selbst wenn er ein unbekanntes Kommando vom Client empfängt. Die kor- rekte Reaktion auf ein unbekanntes Kommando ist eine 500-Antwort, wonach auf weitere Anweisungen des Clients gewartet werden muss. 2. Das Simple Mail Transfer Protocol 6

Wenn ein Client einen TCP-Verbindungsabbruch erkennt, ohne eine entsprechende Be- nachrichtigung (421) des Servers empfangen zu haben, soll er trotzdem die aktive Transaktion als abgebrochen betrachten.

2.1.3 Behandlung des end of mail-Indikators innerhalb des Mail-Textes

Die Sequenz „.“ dient als Kennzeichnung des Endes der Mail-Daten und darf deshalb nicht innerhalb des (vom Benutzer eingegebenen) Mail-Textes vorkommen. Die Kenntnis solcher „verbotener“ Sequenzen kann aber von AnwenderInnen nicht vorausgesetzt werden. Der SMTP-Client hat jedoch die Möglichkeit, das Ende des Mail-Textes auf andere Weise zu erkennen. Wenn er nun am Anfang einer Zeile einen Punkt erkennt, dupliziert er ihn4. Dadurch kann die Sequenz nicht mehr im Text auftreten. Der Server hat dabei die Aufgabe, jede Zeile darauf zu überprüfen, ob sie mit 2 Punkten beginnt. Ist dies der Fall, streicht er einen davon. Beginnt die Zeile nur mit einem Punkt wird die Sequenz als End Of Mail (EOM) Indikator betrachtet.

2.1.4 SMTP-Kommandos

Dieses Kapitel beschreibt jene Kommandos, die ein SMTP-Server laut RFC5321 [Kle08] mindestens unterstützen muss. Diese Kommandos können vom Client nur dann verwendet werden, wenn nicht gerade Mail-Content übertragen wird. Die Syntax der beschriebenen SMTP-Kommandos und Return-Codes basiert auf der in [CO08] spezifizierten Augmented Backus Naur Form (ABNF), die wiederum auf der Backus Naur Form (BNF) aufbaut. Die ABNF wird in verschiedenen RFCs verwendet, um Syntax oder Kommunikationsprotokolle zu beschreiben. Die in diesem Kapitel gezeigte Syntax wurde aus [Kle08] entnommen.

2.1.4.1 HELO

HELO wird von SMTP-Clients benützt, um sich beim SMTP-Server zu identifizieren. Als Parameter wird der Fully Qualified Domain Name = der vollständige Name einer Domain (FQDN) übergeben. Falls der Client keinen oder keinen sinnvollen5 Domainnamen angeben kann, soll er zumindest seine Internet Protocol (IP)-Adresse übergeben. Der Client erwartet darauf eine einzeilige Antwort, im positiven Fall mit Code 250. Nach Empfang dieser Antwort sind beide Teilnehmer in einem Initialzustand und bereit, eine Transaktion zu beginnen.

Syntax: helo = “HELO“ SP Domain CRLF

4Das ist eine Form des Character Stuffing oder Zeichenstopfens, wie es z. B. in [Tan98, Seite 203 ff.] beschrieben wird. 5z. B. wenn der Domainname dynamisch zugewiesen wurde und kein Reverse-Eintrag existiert. 2. Das Simple Mail Transfer Protocol 7

1 HELO mail.example.com Listing 2.1: SMTP-Client identifiziert sich mit dem HELO-Kommando

2.1.4.2 EHLO

Das Kommando EHLO (Extended-Hello) erfüllt die gleiche Aufgabe wie HELO, signalisiert dem Server aber zusätzlich, dass der Client grundsätzlich ESMTP-Funktionalität unterstützt. Der Server kann diese in einem Multiline-Reply mit Code 250 ankündigen. Laut RFC5321[Kle08] muss er alle unterstützten Kommandos mit Hilfe von Schlüsselwörtern ankündigen, die nicht in der Liste der minimal vorausgesetzten Schlüsselwörter (Abschnitt 2.1.4) enthalten sind.

Syntax: ehlo = “EHLO“ SP ( Domain / address-literal ) CRLF

1 EHLO mail.example.com Listing 2.2: SMTP-Client identifiziert sich mit dem EHLO-Kommando

2.1.4.3 MAIL

Um eine Mail-Transaktion zu beginnen, sendet der Client ein MAIL-Kommando und gibt die Adresse der Mailbox des Absenders (Reverse-Path) als Parameter an. Diese Information kann der Server benutzen, um Fehlerberichte zuzustellen oder um zu entscheiden, ob der Absender berechtigt ist, Nachrichten zu senden. Zusätzlich existieren aber auch Benachrichtigungstypen, die einen leeren (<>) Reverse-Path verlangen. Dies sind Nachrichten, die sich auf eine vorher- gehende Nachricht beziehen, wie Message Delivery Notification (MDN)[HV04] oder Delivery Status Notification (DSN)[Moo03]. Dadurch wird verhindert, dass wegen Unzustellbarkeit solcher Benachrichtigungen weitere Benachrichtigungen erzeugt werden.

Syntax: mail = “MAIL FROM:“ Reverse-path [SP Mail-parameters] CRLF

1 MAIL FROM: Listing 2.3: Spezifikation des Absenders mit dem MAIL-Kommando

2.1.4.4 RCPT

Das RCPT-Kommando (Recipient) kann vom Client mehrmals abgesetzt werden und spezifiziert jedes Mal einen individuellen Empfänger. Jeder dieser Empfänger wird vom Server entweder bestätigt (Code 250) oder abgelehnt (Code 4xx bzw. 5xx). Wie der Reverse-Path beim MAIL- Kommando spezifiziert auch der Forward-Path eine Mailbox, im Fall des RCPT-Kommandos die Mailbox des Empfängers. 2. Das Simple Mail Transfer Protocol 8

Syntax: rcpt = “RCPT TO:“ ( ““ / ““ / Forward-path ) [SP Rcpt-parameters] CRLF

1 RCPT TO: Listing 2.4: Spezifikation der Absender mit dem RCPT-Kommando

2.1.4.5 DATA

Die positive Antwort auf das Kommando DATA des Clients hat den Code 354 und signalisiert diesem, dass er mit dem Senden des Mail-Content beginnen kann. Alle darauf folgenden Zeilen werden vom Server solange als Teil dieses Content interpretiert, bis er den End-Of-Mail- Indikator (.) empfangen hat. Das erste CRLF im Indikator ist eigentlich das Zeilenende der vorherigen Contentzeile und weiters das letzte Zeichen, das der SMTP-Server weiterleitet (Relay) oder zustellt. Nach Erhalt des Indikators muss der Server den Reverse-Path, alle (akzeptierten) Forward-Paths und den Content verarbeiten und entscheiden, ob er die Mail-Nachricht annimmt (Code 250). Mit dem Senden des Return-Codes 250 übernimmt der Server die volle Verantwortung für die Nachricht. Tritt in der weiteren Verarbeitung ein Fehler auf, so muss der Server dies an den Absender (Reverse-Path) der Nachricht melden.

Syntax: data = “DATA“ CRLF

1 DATA Listing 2.5: Einleitung der Mail-Daten-Übertragung mit dem DATA-Kommando

2.1.4.6 RSET

Der SMTP-Client kann an jeder Stelle der Transaktion (jedoch nicht während der Übertragung des Mail-Content) ein RSET-Kommando (Reset) senden, um sie abzubrechen. Der Server muss darauf mit einem 250 Reply antworten und genauso wie der Client die gespeicherten Daten zur aktuellen Transaktion verwerfen. Falls gerade keine Transaktion im Gange ist, hat das Kommando keinen Effekt, muss aber trotzdem vom Server bestätigt werden. Das RSET Kommando ist aber kein Signal an den Server, die SMTP-Verbindung zu beenden (siehe Abschnitt 2.1.2).

Syntax: rset = “RSET“ CRLF

1 RSET Listing 2.6: Abbruch der Transaktion mit dem RSET-Kommando 2. Das Simple Mail Transfer Protocol 9

2.1.4.7 NOOP

Das NOOP-Kommando hat keinen Effekt auf die Transaktion, außer dass der Server es mit einer 250 Antwort bestätigen muss. Der Client kann es im SMTP-Dialog jederzeit mit oder ohne Parameter senden. Falls ein Parameter gesendet wird, muss ihn der Server ignorieren.

Syntax: noop = “NOOP“ [ SP String ] CRLF

1 NOOP Listing 2.7: Absenden eines Kommandos, das sich nicht auf die Transaktion auswirkt: NOOP

2.1.4.8 QUIT

Als Reaktion auf das Kommando QUIT antwortet der SMTP Server mit „221 OK“ und beendet dann die TCP-Verbindung. Weiters wird auch jede gerade aktive Transaktion abgebrochen. Der Server darf ansonsten die Verbindung nicht von sich aus unterbrechen (Ausnahmen siehe Abschnitt 2.1.2). Genauso soll der Client die Verbindung nicht abbrechen, bevor er QUIT gesendet und die Antwort empfangen hat. Falls die TCP-Verbindung trotzdem abbricht, müssen beide Teilnehmer die Transaktion so behandeln, als ob sie abgebrochen wäre.

Syntax: quit = “QUIT“ CRLF

1 QUIT Listing 2.8: Beenden der SMTP-Sitzung mit dem QUIT-Kommando

2.1.4.9 VRFY

Mit dem VRFY-Kommando (Verify) kann der Client beim Server nachfragen, ob der übergebene Parameter einen User oder eine Mailbox spezifiziert. In der Antwort kann der Server einerseits die Existenz der Mailbox oder des Users bestätigen und andererseits zusätzliche Informationen zum angefragten User zurückgeben. Aus Sicherheitsgründen6 können SMTP-Server die VRFY- Funktionalität abschalten und „252 Cannot VRFY User“ zurückgeben, anstatt die Verifikation durchzuführen. Auf keinen Fall dürfen sie aber eine 250-Antwort zurückgeben, wenn der Parameter nicht verifiziert wurde.

Syntax: vrfy = “VRFY“ SP String CRLF

1 VRFY john Listing 2.9: Überprüfung mit dem VRFY-Kommando, ob ein User oder eine Mailbox auf dem Server existieren

6z. B. um Spammern das Sammeln von Adressen nicht zu erleichtern. 2. Das Simple Mail Transfer Protocol 10

2.1.5 SMTP Return Codes

SMTP-Antworten bestehen aus einem dreistelligen Code gefolgt von einem beschreibenden Text. Der Code entspricht dem maschinenlesbaren Teil, während der Text für Menschen bestimmt ist. Im Code sind genug Informationen enthalten, damit der Client den Text nicht verarbeiten muss. Er kann ihn entweder verwerfen, mitprotokollieren oder an den User weiterleiten (z. B. in Fehlerfällen).

Syntax: textstring = 1*(%d09 / %d32-126) ; Horizontal Tabulator (HT), SP, Printable US-ASCII Reply-line = *( Reply-code “-“ [ textstring ] CRLF ) Reply-code [ SP textstring ] CRLF Reply-code = %x32-35 %x30-35 %x30-39

Zwar basiert die Syntax der Return-Codes bei SMTP auf jenen von FTP, jedoch wird die Klasse 1yz nicht verwendet.

2.1.5.1 Multiline Replies

Vor allem bei Antworten auf das Kommando EHLO kann es vorkommen, dass der Text mehr als eine Zeile umfasst. In diesem Fall muss jede Zeile mit dem Reply-Code beginnen, der Text jeder Zeile außer der letzten wird nun mit einem „-“-Zeichen statt einem SP vom Reply-Code getrennt. Das Trennzeichen der letzten Zeile ist wiederum ein Leerzeichen. Die Antwort auf das Kommando EHLO hat damit folgende Syntax:

Syntax: ehlo-ok-rsp = ( “250“ SP Domain [ SP ehlo-greet ] CRLF ) / ( “250-“ Domain [ SP ehlo-greet ] CRLF *( “250-“ ehlo-line CRLF ) “250“ SP ehlo-line CRLF )

1 250-mail.example.net 2 250-STARTTLS 3 250 SIZE 0 Listing 2.10: Mögliche Antwort auf das EHLO-Kommando

2.1.5.2 Klasse 2yz

Return Codes mit der Ziffer 2 an erster Stelle stehen für eine positive Rückmeldung. Weiters wird dadurch angezeigt, dass die Operation abgeschlossen wurde und ein neues Kommando gesendet werden kann.

1 220 mail.example.net Service ready Listing 2.11: Begrüßung des Servers nach dem TCP-Verbindungsaufbau 2. Das Simple Mail Transfer Protocol 11

2.1.5.3 Klasse 3yz

Das Kommando wurde zwar erfolgreich angenommen, zu dessen Abschluss fehlen dem Server aber noch weitere Informationen. Diese muss der Client im nächsten Kommando nachreichen. 1 354 Start mail input; end with . Listing 2.12: Antwort auf das DATA-Kommando

2.1.5.4 Klasse 4yz

Codes dieser Klasse zeigen an, dass das Kommando weder akzeptiert noch die davon an- geforderte Aktion durchgeführt wurde. Allerdings ist dieser Fehlerzustand temporär und ein erneutes Senden dieses Kommandos könnte erfolgreich sein. Ein Client soll deshalb die Kommandosequenz zu einem späteren Zeitpunkt nochmals probieren. 1 452 Temporary problem, insufficient system storage Listing 2.13: Antwort des Servers, wenn nicht genug Speicherplatz zur Verfügung steht

2.1.5.5 Klasse 5yz

Im Gegensatz zur Klasse 4yz sind Fehler hier permanent (z. B. ein Server unterstützt ein Kommando nicht). Dementsprechend darf ein Client die gleiche Sequenz auch nicht erneut probieren. 1 502 Command not implemented Listing 2.14: Antwort des Servers, wenn ihm ein Kommando zwar bekannt ist, aber nicht unterstützt wird.

Die zweite Stelle der Codes unterteilt die Antworten weiter in folgende Kategorien:

2.1.5.6 Kategorie x0z

Zu dieser Kategorie gehören sowohl Fehler in der Syntax als auch syntaktisch korrekte Kommandos, die nicht unterstützt werden. 1 500 Syntax error: line too long Listing 2.15: Antwort des Servers, wenn ein zu langes Kommando empfangen wurde

2.1.5.7 Kategorie x1z

Diese Kategorie enthält Antworten auf Anfragen nach Informationen, Status oder Hilfe. 1 214 Visit http://www.example.net for help Listing 2.16: Antwort des Servers auf das HELP-Kommando 2. Das Simple Mail Transfer Protocol 12

2.1.5.8 Kategorie x2z

Die Antworten aus dieser Kategorie betreffen den Übertragungskanal.

1 221 mail.example.net Service closing transmission channel Listing 2.17: Antwort des Servers auf das QUIT-Kommando

2.1.5.9 Kategorie x5z

Diese Kategorie betrifft das Mail-System selbst.

1 252 Cannot VRFY, send some mail and i try my best Listing 2.18: Antwort des Servers auf das VRFY-Kommando

Die Kategorien x3z und x4z sind unspezifiziert. Die dritte Stelle der Codes erlaubt eine weitere, feinere Unterteilung.

2.1.6 Bespiele für den Ablauf von SMTP-Sitzungen

1 220 mail.example.net Service ready 2 EHLO mail.example.com 3 250-mail.example.net 4 250-STARTTLS 5 250 SIZE 0 6 HELP 7 214 Visit http://www.example.net for help 8 VRFY john 9 252 Cannot VRFY, send some mail and i try my best 10 MAIL FROM: 11 250 OK 12 RCPT TO: 13 550 No such user here 14 RCPT TO: 15 250 OK 16 DATA 17 354 Start mail input; end with . 18 Date: 1.10.2011 10:21:00 +0100 19 Subject: Hello 20 From: Jack 21 To: Joe 22 23 Hello Joe 24 Whats up? 25 . 26 250 OK 27 QUIT 2. Das Simple Mail Transfer Protocol 13

28 221 mail.example.net Service closing transmission channel

Listing 2.19: Beispiel für den Ablauf einer SMTP-Sitzung

1 220 mail.example.net Service ready 2 EHLO mail.example.com 3 250-mail.example.net 4 250 SIZE 0 5 STARTTLS 6 502 Command not implemented 7 MAIL FROM: 8 250 OK 9 RCPT TO: 10 250 OK 11 DATA 12 354 Start mail input; end with . 13 Date: 1.10.2011 10:21:00 +0100 14 Subject: Hello 15 From: Jack 16 To: Joe 17 18 Hello Joe 19 Whats up? 20 . 21 452 Temporary problem, insufficient system storage 22 RSET 23 250 OK 24 QUIT 25 221 mail.example.net Service closing transmission channel

Listing 2.20: Beispielablauf einer abgebrochenen SMTP-Sitzung

2.1.7 Verlässlichkeit

Nimmt ein Server eine Mail-Nachricht an, indem er eine 250-Antwort als Reaktion auf das Ende des Mail-Content sendet, so übernimmt er die Verantwortung für die Zustellung. Ist diese Zustellung nicht beim ersten Versuch erfolgreich, sind weitere Zustellversuche vorgesehen (Genaueres in [Kle08, Abschnitt 4.5.4.1]). Kann die Nachricht trotz allem nicht zugestellt werden, so ist der SMTP-Server verpflichtet, den Absender darüber zu informieren. Diese Benachrichtigung wird mit einer Mail-Nachricht durchgeführt, deren Reverse-Path nicht gesetzt ist (“<>“). Als Zieladresse verwendet der Server den Reverse-Path der originalen Nachricht. Das Format einer solchen DSN ist in [Moo03] bzw. [MV03] beschrieben. Können solche Notifications nicht zugestellt werden, sind dafür keine weiteren Benachrichtigungen zu generieren. 2. Das Simple Mail Transfer Protocol 14

2.1.8 Mail-Routing

Damit eine Mail-Nachricht an ihrem Ziel ankommt, gibt es verschiedene Möglichkeiten, die Route dorthin festzulegen. Die noch in [Pos82] erwähnte Methode, bei welcher der Absender mit Hilfe von Source-Routing den Weg festlegt, ist mittlerweile unnötig geworden und wird in aktuelleren RFCs zu SMTP nicht mehr empfohlen. Dies ist vor allem seit der Einführung und Verfügbarkeit von MX-Einträgen7 im Domain Name System (DNS)[Moc87] obsolet. Soll ein SMTP-Server eine Mail-Nachricht an eine bestimmte Domain zustellen, darf er sich laut [Par86] nicht direkt mit der Ziel-Domain verbinden, sondern muss erst eine DNS- Query nach dem MX-Eintrag dieser Domain ausführen, um den zuständigen SMTP-Server zu ermitteln. Im einfachsten Fall gibt es nur einen MX-Eintrag und der SMTP-Server wird versuchen, die Nachricht dorthin zuzustellen. Gibt es keinen Eintrag kann der SMTP-Server einen direkten Zustellversuch an den A-Eintrag8 der Ziel-Domain vornehmen. Es ist aber auch möglich, im DNS mehrere MX-Einträge zu hinterlegen und diese nach Priorität9 zu reihen. Listing 2.21 zeigt dazu ein Beispiel. Die Adressen sind explizit für Dokumentation oder Beispiele reserviert (siehe RFC5737[ACV10]).

1 mx01.example.com IN A 203.0.113.1 2 mx02.example.com IN A 203.0.113.2 3 example.com IN MX 5 mx01.example.com 4 example.com IN MX 10 mx02.example.com

Listing 2.21: Beispiel für MX- und A-Einträge im DNS für mehrere DNS-Server

Ein SMTP-Server, der als MX für eine Domain eingetragen ist, muss nun entweder direkt an die Empfänger zustellen können oder Routen zu den zuständigen SMTP-Servern konfiguriert haben.

2.1.8.1 Mail-Relay

Ist ein SMTP-Server nicht das endgültige Ziel einer Mail-Nachricht, so tritt er als Mail-Relay auf. Nachdem er die Nachricht angenommen hat, verbindet er sich als SMTP-Client zum nächsten Server10 und sendet die Nachricht weiter. Ein SMTP-Server muss nicht für jedes Mail als Relay agieren, er kann diese Funktionalität auf lokale Absender oder auf authentifizierte11 Benutzer beschränken. Zumindest aber für die Domain, für die er als MX eingetragen ist, muss er Mails annehmen (und in Folge zustellen).

7Mail eXchange Ressource Record im DNS (MX) 8Address Ressource Record im DNS (A) 9Wobei der Eintrag mit dem niedrigsten Preference-Wert die höchste Priorität hat. 10Den er z. B. per MX-Eintrag im DNS ermittelt hat 11Genaueres zu SMTP-AUTH-Funktionalität in [SM07] 2. Das Simple Mail Transfer Protocol 15

2.1.8.2 Trace Records

Jeder SMTP-Server, der eine Nachricht auf ihrem Weg verarbeitet, muss einen Received-Header an deren Beginn anfügen. Er darf dabei Received-Header, die von anderen Servern eingefügt wurden, nicht löschen oder verändern. Der Header selbst besteht aus folgenden Teilen: • Einem „From“-Eintrag, der sowohl den Hostnamen des sendenden Hosts (aus dem HELO/EHLO-Kommando) und dessen IP-Adresse (aus der TCP-Verbindung selbst) ent- halten muss • Einem „By“-Eintrag, der den Namen des empfangenden Hosts enthält • Einem Timestamp, der die Zeit des Empfangs enthält Optional sind folgende Einträge möglich: • Ein „For“-Eintrag mit der im RCPT-Kommando angegebenen Empfängeradresse • Ein „Via“-Eintrag, der das Transportprotokoll (normalerweise TCP) enthält • Ein „With“-Eintrag mit dem Empfangsprotokoll (z. B. ESMTP) • Ein „ID“-Eintrag mit der Message-ID Die genaue Syntax kann in [Kle08] nachgelesen werden. Bei der endgültigen Zustellung einer Nachricht (oder wenn sie das SMTP-System verlässt) fügt der SMTP-Server einen „Return-Path“-Header ein, der den Absender aus dem Kommando MAIL enthält. Wurde von einem vorherigen SMTP-Server fälschlicherweise schon ein „Return- Path“-Header eingefügt, so darf er gelöscht und aus dem Kommando MAIL neu erstellt werden.

1 From: User1 2 Date: Thu, 16 Aug 2012 23:17:42 +0200 3 To: [email protected] 4 Return-Path: 5 Received: (qmail 31490 invoked by uid 210); 16 Aug 2012 21:17:51 -0000 6 Received: from 203.0.113.1 by mx01.example.com (envelope-from , uid 201) with ; 16 Aug 2012 21:17:51 -0000 7 Received: from unknown (HELO mail.example.net) (198.51.100.2) by 0 with SMTP; 16 Aug 2012 21:17:44 -0000 8 Received: (qmail 31227 invoked by uid 0); 16 Aug 2012 21:17:43 -0000 9 Received: from 198.51.100.3 by webmail.example.net with HTTP; Thu, 16 Aug 2012 23:17:42 +0200 (CEST) 10 Message-ID: <[email protected]>

Listing 2.22: Beispiel für einen Mail-Header

Listing 2.22 zeigt einen möglichen Mail-Header. Unter anderem ist in diesem Header ersichtlich, dass die Mail vom Host webmail.example.net ausgeht, und dieser Host sie mittels HTTP empfangen hat. Danach wurde die Mail noch von den Hosts mail.example.net und mx01.example.com weitergeleitet. 2. Das Simple Mail Transfer Protocol 16

2.1.9 Timeouts

Laut [Kle08] muss ein SMTP-Client einen Timeout-Mechanismus aufweisen, sodass er für jeden Befehl bzw. für jeden Datenblock (beim Übertragen des Mail-Content) einen Timer implementiert. Ein globales Timeout, zum Beispiel für die Abhandlung der gesamten Transak- tion, ist nicht zulässig. Die genauen Werte der Timeouts sind nicht vorgegeben, jedoch sollen die Vorschläge aus Tabelle 2.1 eingehalten werden. Aktion Timeout Client Timeouts Vom erfolgreichen Aufbau der TCP-Verbindung bis zur 220- 300 Sekunden Willkommensnachricht Abarbeitung des Kommandos MAIL 300 Sekunden Abarbeitung des Kommandos RCPT 300 Sekunden Vom Absenden des Kommandos DATA bis zum Empfang der Antwort 354 120 Sekunden Erfolgreiches Abschließen eines TCP-Send-Befehls beim Übertragen des 180 Sekunden Mail-Content Vom Senden des End-Of-Mail-Indikators bis zum Empfang der abschlie- 600 Sekunden ßenden Antwort 250 Server Timeouts Wartezeit bis zum nächsten Kommando des Clients 300 Sekunden

Tabelle 2.1: Vorschläge für Mindestwerte von SMTP-Timeouts aus [Kle08].

Nicht alle SMTP-Client- bzw. Server-Implementierungen halten sich an die RFC-Empfehlungen. Tabelle 2.2 zeigt exemplarisch gemessene Werte zu Server-Timeouts einiger Mail-Server. Gemessen wurden die Timeouts mit dem Befehl aus Listing 2.23. 1 time telnet Listing 2.23: Grobe Messung der SMTP-Server-Timeouts

Nach Absetzen des Befehls folgten keine weiteren Eingaben, weshalb der Server die TCP-Verbindung nach seinem Timeout abbrechen muss. Dieser Test kann jedoch nur eine Annäherung sein, da er die gesamte Laufzeit vom Aufbau bis zum Abbruch der Verbindung misst und nicht wie im RFC vorgegeben die Wartezeit bis zum nächsten Kommando des Clients. Manche Server schließen die TCP-Verbindung nicht nach dem Erreichen des Timeouts, sondern erst nach dem Empfang eines weiteren Paketes des Clients und verhindern so die Messung mit dieser einfachen Methode. In diesem Test war dies: „mail-relay.telekom.at ( 4.62)“. Es kann deshalb nicht unbedingt davon ausgegangen werden, dass Server obgleich sie die Verbindung lange geöffnet halten, auch bis zuletzt Kommandos annehmen. Darum wurde bei allen Servern getestet, ob sie nach dem auf 25 Sekunden festgelegten relevanten Minimum noch ein Kommando annehmen. Das war bei allen Servern der Fall. 2. Das Simple Mail Transfer Protocol 17

SMTP-Server SMTP-Software Timeout in Sekunden Minimum laut RFC 300 mx1.gmx.net n/a 60 mx-ha01-web.de n/a 30 email.aon.at n/a 60 lmail1.ris.at XMail 1.25 93 mx0.inode.at n/a 31 mail3.edvz.uni-linz.ac.at n/a 66 mail.krru.at netqmail 1.06 40 gmail-smtp-in.l.google.com n/a 600 mail.messaging.microsoft.com n/a 60 mail.cloud9.net Postfix 25 hera.kernel.org 8.14.4/8.14.3 3600 mail-relay.telekom.at Exim 4.63 n/a Relevantes Minimum 25

Tabelle 2.2: Gemessene SMTP-Server-Timeout-Werte.

Unterschiede gab es auch in der Art des Verbindungsabbruchs. Viele Server sendeten gar keine Meldung beim Beenden der Verbindung. Andere wiederum sendeten entweder die Meldung „421: hdomaini Service not available, closing transmission channel“ oder „451: Requested action aborted: error in processing“, bevor sie die Verbindung schlossen. Auch das Schließen fand auf verschiedene Arten statt. Manche TCP-Verbindungen wurden sauber mit FIN-ACK beendet, mache wurden jedoch mit TCP-Reset abgebrochen.

2.2 SMTP-Proxy

A proxy is a software agent that acts on behalf of the server for the client and on behalf of the client for the server. Following authentication of the client or server to the proxy, the proxy works for both sides transparently.[Poh01]

Anders als Mail-Relay-Server verzichten SMTP-Proxys auf eine Zwischenspeicherung der Nachrichten. Sie leiten die Anfragen des Clients sowie die Antworten des Servers zur jeweiligen Gegenstelle weiter. Dazu muss ein SMTP-Proxy aber sowohl Anfragen als auch Antworten zumindest teilweise interpretieren können. Jene Kommandos, die ein SMTP-Server laut [Kle08] mindestens unterstützen muss12, benötigen keine weitere Behandlung des Proxy, wenn er nur die SMTP-Kommandos und Antworten weiterleitet. Soll der Proxy jedoch dazu verwendet werden, den Inhalt der transportierten Mail-Nachrichten zu untersuchen, muss er zumindest das Kommando DATA richtig interpretieren und erst dann an der Server weiterleiten, wenn der

12Dies sind: HELO, EHLO, MAIL, RCPT, DATA, RSET, NOOP, QUIT und VRFY. 2. Das Simple Mail Transfer Protocol 18

Inhalt untersucht wurde.

2.3 Proxy-Unterstützung für (E-)SMTP-Funktionalität

ESMTP bietet die Möglichkeit, SMTP um neue Befehle und Funktionen zu erweitern. Wird ein SMTP-Proxy verwendet, stellt sich die Frage, inwieweit er diese Erweiterungen kennen, unterstützen oder behandeln muss. Die einfachste Möglichkeit wäre, das EHLO-Kommando des Clients nicht an den Server weiterzuleiten, sondern stattdessen ein HELO-Kommando zu senden. Dadurch wird dem Server angezeigt, dass der Client kein ESMTP unterstützt und es nicht nötig ist, die unterstützten SMTP-Erweiterungen anzukündigen. Auch der Client darf dann nicht versuchen, Erweiterungen zu verwenden. Da dadurch ESMTP effektiv deaktiviert wird, ist es besser, das Kommando EHLO durchzu- lassen und stattdessen jene SMTP-Erweiterungen aus der Antwort des Server herauszufiltern, die der Proxy nicht unterstützt. Es können jedoch immer weitere Erweiterungen entwickelt werden, die der Proxy noch nicht kennt und die eventuell problematisch sind. Als Alternative könnte hier eine Art Whitelist von Erweiterungen angedacht werden. Welcher Weg hier gewählt wird, hängt natürlich auch davon ab, wie oft neue Erweiterungen erscheinen.

2.4 SMTP-Proxy vs. Relay

Aufgrund der Architektur des Protokolls, kann jeder SMTP-Server als Relay eine dem Proxy ähnliche Funktionalität bieten, es gibt jedoch signifikante Unterschiede.

2.4.1 Regelung des Zugriffs

Ein SMTP-Relay-Server muss bei jeder SMTP-Verbindung selbst entscheiden, ob der jeweilige Client in dieser Situation zur Benutzung berechtigt ist, da der Server sonst als offenes Relay Spam-Versender unterstützt. Ein einfacher Ansatz ist hier, nur Hosts aus bestimmten, meist lokalen IP-Bereichen zuzulassen. Dies ist auch ausreichend, wenn das Relay nur für ebendiese Hosts zuständig sein soll. Um auch Clients ohne feste IP-Adresse unterstützen zu können, wird in [SM07] eine Möglichkeit beschrieben, einen SMTP-Client mit Hilfe von SMTP-AUTH zu authentifizieren. Ein SMTP-Proxy kann die Entscheidung, einen Client zuzulassen oder abzulehnen, an den Zielserver abgeben, da jeder Befehl des Clients, inklusive SMTP-AUTH, weitergeleitet wird. Für den Server sieht es nun aber so aus, als ob die SMTP-Verbindung direkt vom Proxy ausgehen würde. Ein Client, dessen Adresse für den Server prinzipiell zulässig ist, wird in diesem Fall abgelehnt, wenn die Adresse des Proxy für den Server nicht zulässig ist. Dieses Problem kann aber mit Transparent Proxy (TPROXY) (siehe Abschnitt 4.1.6) gelöst werden. 2. Das Simple Mail Transfer Protocol 19

2.4.2 Verantwortlichkeit für Mail-Nachrichten

Wie in Abschnitt 2.1.7 beschrieben übernimmt ein SMTP-Server mit dem Annehmen der Mail-Nachricht die Verantwortung für ihre Zustellung. Ein Relay kann jedoch nicht wissen, ob der Zielserver diese annehmen wird, und muss, falls die Zustellung fehlschlägt, den Absender in einer separaten Nachricht darüber informieren. Dadurch ist ein Relay besonders anfällig für Spammer, die versuchen, eine große Anzahl an Adressen zu verifizieren. Dies kann zu einer DoS-Attacke13 werden, da das Relay sehr viele Non-Delivery-Notification-Reports senden muss. Ein SMTP-Proxy kann in diesem Fall die Ressourcen für das Senden der DSN sparen, da er den Zielserver über die Annahme (oder Nichtannahme) der Nachricht entscheiden lässt.

2.4.3 Verwaltung einer Warteschlange

Jeder Host, der als Mail-Relay arbeitet, muss zur Abarbeitung der Nachrichten eine Warte- schlange verwalten. Dies ist nötig, wenn ein Zielserver ausgelastet oder aus einem anderen Grund nicht verfügbar ist. In diesem Fall wird die für diesen Server bestimmte Nachricht wieder in die Warteschlange eingeordnet und zu einem späteren Zeitpunkt ein erneuter Zustell- versuch gestartet. Laut [Bra89] (und in Folge auch [Kle08]) soll bis zum nächsten Versuch eine Wartezeit von 30 Minuten eingehalten werden. Schlägt auch dieser Versuch fehl müssen weitere folgen, wobei der Server nicht vor 4–5 Tagen aufgeben darf. Dadurch besteht die Gefahr, dass Nachrichten verloren gehen, die das Relay zwar bereits angenommen, aber noch nicht zugestellt hat (z. B. im Falle eines Hardwaredefekts). Weder der Sender noch der Empfänger erfahren in diesem Fall etwas vom Verlust dieser Nachricht. Dies ist vor allem bei Firmen oder Behörden nicht akzeptabel. Ein SMTP-Proxy kann auch diese Komponente einsparen, da der Zielserver schon beim Verbindungsaufbau des Clients kontaktiert wird. Ist dieser Server nicht verfügbar, kann auch der Client keine Verbindung herstellen und ist selbst für einen erneuten Zustellversuch zuständig. Selbst bei einem Ausfall des Proxy ist eine Nachricht entweder korrekt zugestellt worden oder der Absender wurde über die Unzustellbarkeit informiert. Fällt der Proxy aus, bevor er die Antwort 250 des Servers an den Client weiterleiten konnte, muss der Client davon ausgehen, dass die Nachricht nicht erfolgreich zugestellt wurde. So geht selbst in diesem Fall keine Nachricht verloren, sondern wird höchstens doppelt versandt.

2.5 STARTTLS-Erweiterung

Die STARTTLS-Erweiterung (aus [Hof02]) für SMTP ermöglicht es, eine unverschlüsselte SMTP-Verbindung durch Verwendung von TLS aufzuwerten. Im Gegensatz zu HTTPS[Res00], wo der TLS-Handshake[DR08] direkt nach dem TCP-Handshake ausgeführt wird, beginnt eine

13Denial of Service (DoS) 2. Das Simple Mail Transfer Protocol 20

Verbindung bei SMTP zuerst unverschlüsselt und erlaubt später im weiteren Protokollverlauf ein Aushandeln der Verschlüsselung. Wie auch bei allen anderen SMTP-Kommandos geht die Initiative vom Client aus. Dazu muss er aber wissen, ob der Server die Erweiterung STARTTLS überhaupt unterstützt. Dies kann der Server in seiner Antwort auf das EHLO-Kommando durch Senden des Schlüsselwortes STARTTLS bekannt geben. Sendet nun der Client das STARTTLS-Kommando, so hat der Server 3 Möglichkeiten zu reagieren: 1. 220 Ready to start TLS: Signalisiert dem Client die Bereitschaft für den TLS-Handshake. 2. 501 Syntax error (no parameters allowed): Mögliche Fehlermeldung, falls der Client zusätzliche Parameter an das Kommando angehängt hat. 3. 454 TLS not available due to temporary reason: Falls der Aufbau einer TLS-Session gerade nicht möglich ist. Erhält nun der Client eine positive Antwort (220), muss er mit dem TLS-Handshake beginnen, bevor er weitere SMTP-Kommandos senden darf. War dieser erfolgreich, muss sich der Client erneut mit dem EHLO-Kommando vorstellen und der Server daraufhin mit seinen unterstützten Erweiterungen antworten. Diese Liste der Erweiterungen kann und wird von jener vor dem TLS-Handshake abweichen, vor allem, weil der Server die STARTTLS-Erweiterung nicht erneut ankündigen darf. Schlägt der TLS-Handshake jedoch fehl oder lehnt der Server STARTTLS ab, so entscheidet wiederum der Client, ob er mit der (unverschlüsselten) Verbindung fortfahren möchte. Der Server selbst darf die STARTTLS-Funktionalität zwar anbieten, aber ihre Verwendung nicht vom Client verlangen, solange es sich dabei um einen öffentlichen Server handelt. Wird er jedoch nur intern genutzt, sieht RFC3207 die Möglichkeit vor, alle Kommandos außer EHLO, NOOP, STARTTLS und QUIT mit der Meldung „530 Must issue a STARTTLS command first“ abzulehnen, solange keine TLS-Session besteht. Neben der Verschlüsselung kann STARTTLS auch Authentisierungsfunktionen übernehmen. Der Client kann prüfen, ob der Server ein gültiges Zertifikat gesendet hat; und der Server kann anhand des Client-Zertifikates den Client identifizieren und ihm z. B. erlauben, den Server als Relay zu benutzen. Es ist jedoch nicht möglich, damit den Absender einer Nachricht zu authentifizieren, da ein Client-Zertifikat darüber nichts aussagt. Weiters bietet STARTTLS keine Ende-zu-Ende-Verschlüsselung14, da eine Nachricht über mehrere SMTP-Server transportiert werden kann und eine TLS-Session immer nur zwischen zwei Servern stattfindet. Ob jeder Server auf dem Weg STARTTLS verwendet, kann vom Absender weder beeinflusst noch überprüft werden. Es ist für einen Angreifer möglich, den Aufbau der TLS-Session zu verhindern, indem er entweder STARTTLS aus der Liste der unterstützten Servererweiterungen oder eine positive Antwort auf das STARTTLS-Kommando herausfiltert. Das ist deshalb problematisch, weil es

14Eine Ende-zu-Ende-Verschlüsselung würden z. B. S/MIME[Ram04] oder OpenPGP[CDF+07] bieten. 2. Das Simple Mail Transfer Protocol 21 für den Benutzer weder ersichtlich noch erkennbar ist, ob ein TLS-Handshake durchgeführt wurde oder nicht. Kapitel 3

Vorhandene SMTP-Proxy-Lösungen

In diesem Kapitel werden vorhandene SMTP-Proxy-Lösungen auf ihre Möglichkeiten zur Spam- bzw. Viren-Abwehr sowie ihre Unterstützung für SMTPS oder STARTTLS untersucht. Die Auswahl beschränkt sich jedoch auf frei verfügbare Lösungen. Zwei dieser Lösungen arbeiten als Relay anstatt als Proxy, bieten jedoch auch interessante Ansätze und wurden deshalb ebenfalls inkludiert.

3.1 ProxSMTP/ClamSMTP

Die beiden Projekte ProxSMTP[43] und ClamSMTP[10] von Stefan Tobias Walter werden unter einer BSD-ähnlichen Lizenz veröffentlicht. Beide bauen auf der gleichen Codebasis auf und können sowohl als Content-Filter für postfix als auch als alleinstehender SMTP-Proxy betrieben werden. Ein Einsatz als transparenter SMTP-Proxy ist ebenfalls möglich. ClamSMTP beschränkt sich auf die Anbindung von ClamAV als Virenscanner, wogegen ProxSMTP als generischer SMTP-Proxy konzipiert ist. Dabei kann ProxSMTP den Inhalt der Nachricht entweder per Pipe (siehe [Ste95, Abschnitt 14.2]) an einen Contentfilter übergeben, oder ihn in einer Datei ablegen und dann vom Filter untersuchen lassen. Beide Projekte unterstützen jedoch weder SMTPS noch STARTTLS und filtern darüber hinaus sowohl das Ankündigen der STARTTLS-Unterstützung als auch das Kommando selbst aus dem SMTP-Dialog heraus.

3.2 Anti-Spam-SMTP-Proxy-Server (ASSP)

Der Anti-Spam-Proxy-Server[2] ist ein in [40] entwickelter SMTP-Proxy, der viele Methoden zur Erkennung bzw. zur Abwehr von SPAM inkludiert und unter der GNU Public License (GPL) veröffentlicht ist. Dabei setzt er nicht auf Produkte wie SpamAssassin[1], sondern auf eigene Realisierungen von Anti-Spam-Techniken: • Bayesian-Filter[7]

22 3. Vorhandene SMTP-Proxy-Lösungen 23

• DNS-Blacklists • White-/Blacklisting • PenaltyBox[3] • (SPF)[WS06] validation • Sender Rewriting Scheme (SRS)[Won03] • Greylisting[26] • ... ASSP kann eingeschränkt auch als Man-in-the-middle für SMTPS fungieren. Diese Funktiona- lität ist jedoch beschränkt auf einen einzigen fix eingestellten SMTP-Server, dessen Zertifikat und Private Key am Proxy hinterlegt werden müssen.

3.3 Hermes

Der Hermes Antispam-Proxy[28] steht ebenfalls unter der GPL. Er wird von der Firma Internet Telecomunicaciones e Ingeniería de Santander (ITEISA)[30] in C++ entwickelt und auch eingesetzt. Neben der Unterstützung für DNS-Blacklists und Greylisting implementiert Hermes auch noch folgende Ansätze zur Spam-Abwehr: • SMTP-Banner-Delay verzögert die (von RFC 5321 vorgeschriebene) 220-Begrüßungs- nachricht des SMTP-Servers. Normalerweise müsste ein SMTP-Client auf diese Nachricht warten, da er sonst nicht weiß, ob er SMTP verwenden muss oder auch ESMTP- Funktionalität verwenden kann. Spammer ignorieren dies aber oft. Sie beginnen sofort mit der Transaktion, damit sind sie einfacher zu identifizieren und zu blocken. • Throttling verzögert die Antwort auf jedes Kommando künstlich, um für Spammer als ein weniger lohnenswertes Ziel zu wirken. Dadurch werden entweder Ressourcen von Spammern gebunden, oder sie brechen die TCP-Verbindung inmitten der Transaktion ab. Wird die Verzögerung klein genug gewählt, ist ein solches Verhalten auch RFC-konform. Hermes unterstützt sowohl STARTTLS als auch SMTPS, jedoch nur mit statisch einem einzigen hinterlegten Zertifikat und dessen Private Key.

3.4 BarricadeMX

BarricadeMX[6] (bzw. dessen Dienst smtpf) der Firma SnertSoft[46] ist als Proxy-Filter für SMTP-Server ausgelegt. Neben der Unterstützung für SpamAssassin[1] inkludiert BarricadeMX auch noch weitere Tests zur Spam-Erkennung: Damit kann sowohl überprüft werden, ob es zu der IP-Adresse des Clients einen gültigen 3. Vorhandene SMTP-Proxy-Lösungen 24 rDNS-Eintrag1 gibt, und auch, ob in diesem Eintrag Teile der Adresse vorkommen (was auf eine von einem Provider dynamisch vergebene Adresse hindeutet). Genauso wie ein fehlender Eintrag kann auch eine dynamische Adresse ein Indiz für einen Spamversuch sein. Um DSN- und MDN-Backscatter[5] zu vermeiden, werden die Message-IDs von ausgehenden Nachrichten gespeichert und nur Notifications akzeptiert, die sich auf eine dieser IDs beziehen. BarricadeMX überprüft auch die Argumente des HELO-/EHLO-Kommandos auf RFC- Konformität. Weiters können Clients, die keinen FQDN als Argument senden, abgelehnt werden. Wird anstatt eines FQDN ein IP-domain-literal übergeben, so muss es mit der IP-Adresse des Clients übereinstimmen. Auch URI-Blacklists2 sind möglich. In diesem Fall werden die Nachrichten (falls nötig) mit Hilfe von Multipurpose Internet Mail Extensions (MIME) dekodiert und dann nach URIs in der Blacklist durchsucht. Zusätzlich werden auch Standardtechniken wie DNS-Blacklisting, DNS-Whitelisting, SPF sowie Greylisting unterstützt. Der Dienst unterstützt nicht nur Anti-Spam-Maßnahmen, sondern auch die Anbindung von Virenscannern wie avast![4], Clam Anti-Virus[9], F-Prot Anti-Virus[42] und Sophos Anti- Virus[47].

Trotz dieser Funktionsvielfalt unterstützt BarricadeMX weder SMTPS noch STARTTLS.

3.5 qpsmtpd qpsmtpd[45] wird von Ask Bjørn Hansen in Perl entwickelt und unter einer Form der MIT- License[35] lizenziert. Ursprünglich sollte diese Software als Ersatz für den SMTP-Teil von Qmail[44] (qmail-smtpd) dienen, unterstützt aber mittlerweile auch andere Mail Transfer Agents (MTAs) wie z. B. postfix[51] und exim[13].

Die Anti-Spam- bzw. Anti-Viren-Maßnahmen werden, wie ein Großteil der Funktionalität, durch Plugins abgebildet: • qpsmtpd bietet Plugins für Standardtechniken wie z. B. DNS-Blacklists, Greylisting und DomainKeys [ACD+07]. • Ähnlich wie bei Hermes ist es auch möglich, SMTP-Clients, die versuchen, vor dem Erhalt der 220-Willkommensnachricht zu senden, gesondert zu behandeln. • Mit dem Milter-Plugin können für sendmail entwickelte Milter-Mail-Filter [33] angebun- den werden. • Auch die Verwendung von SpamAssassin und Virenscannern ist auf diese Weise möglich. Das Virus-Plugin[17] unterstützt dazu die Virenscanner von Kaspersky, BitDefender,

1Reverse DNS (rDNS) 2Uniform Resource Identifier (URI) 3. Vorhandene SMTP-Proxy-Lösungen 25

ClamAV, AntiVir, Sophos und McAfee. • Sowohl SMTPS als auch STARTTLS kann mit Hilfe des TLS-Plugins[16] unterstützt werden. Dazu wird allerdings ein statisches Zertifikat verwendet und nicht ein dem Server angepasstes3. • Die direkte Integration mit dem MTA (auf dem gleichen Host) kann auch als Einschrän- kung gesehen werden. Das Plugin smtp-forward4 ermöglicht aber darüber hinaus ein Weiterleiten an einen weiteren Server mit SMTP und stellt so die Relay-Funktionalität wieder her.

3.6 Evaluation

Art SMTPS STARTTLS OTF-Zertifikate1 SpamAssassin Virenscanner Prox/ClamSMTP Proxy Nein Nein Nein Ja Ja ASSP Proxy Ja Nein Nein Nein Ja (ClamAV) Hermes Proxy Ja Ja Nein Nein Nein BarricadeMX Relay Nein Nein Nein Ja Ja qpsmtpd Relay Ja Ja Nein Ja Ja 1 on-the-fly

Tabelle 3.1: SMTP-Proxy-Lösungen

Tabelle 3.1 fasst die Eigenschaften der untersuchten Produkte zusammen. Nochmals sei darauf hingewiesen, dass nicht alle die Arbeitsweise eines Proxy aufweisen, sondern manche wie ein SMTP-Relay arbeiten. Dies ist zwar nicht explizit schlecht, erfüllt aber auch nicht die Anforderungen. Die Anbindung von Anti-Spam-Maßnahmen (durch SpamAssassin) oder Virenscannern ist durchgehend bei allen untersuchten Softwarepaketen möglich. Selbst Produkte, die Spa- mAssassin nicht direkt unterstützen und deshalb in dieser Spalte ein ‚Nein‘ aufweisen, können stattdessen mit anderen Möglichkeiten zur Spam-Bekämpfung aufwarten. Darunter befinden sich durchaus interessante Ansätze, wie zum Beispiel das verzögerte Senden von Antworten, um Spam-Sender zu entmutigen oder deren Ressourcen zu binden. Das mittlerweile obsolete SMTPS wird zwar nicht von allen Lösungen unterstützt, kann jedoch zum Beispiel durch Einsatz von Stunnel[50] nachgerüstet werden. Die Hauptanforderung, die Unterstützung von STARTTLS, wird nur von zwei Produkten angeboten, von denen qpsmtpd nur als Relay arbeitet. Hermes arbeitet zwar als Proxy, kann aber nur ein einzelnes, fixes Zertifikat verwenden. Um hier auf dem Client keine Sicherheits- warnung zu erzeugen, muss ein Zertifikat verwendet werden, das von einer Zertifizierungsstelle

3Dies wäre für ein SMTP-Relay auch nicht so leicht möglich, da ein Relay nicht schon beim Verbindungsaufbau des Clients eine Verbindung zum Server aufbaut. 4Dieses Plug-in wurde mittlerweile in qpsmtpd integriert. 3. Vorhandene SMTP-Proxy-Lösungen 26 signiert ist, welcher der Client vertraut. Dies könnte auch das Originalzertifikat eines SMTP- Servers sein, für den sich der Proxy ausgeben soll. Ein Erzeugen von Zertifikaten, die zum jeweiligen Server passen, unterstützt jedoch keine der Lösungen.

Aufgrund dieser Einschränkungen wird eine eigene Lösung auf Basis des TLS-Proxy [Asp09] entwickelt. Kapitel 4

TLS-Proxy-Engine von Underground_8

Als Grundlage für den praktischen Teil dieser Arbeit dient die TLS-Proxy-Implementierung von Roman Aspetsberger[Asp09], die für HTTP entwickelt wurde. Dieses Kapitel soll die Struktur und den Aufbau dieses Proxy erläutern und auch mögliche Erweiterungen vorstellen. Quellcode-Listings in diesem Kapitel wurden aus dem Quellcode des TLS-Proxy von Roman Aspetsberger entnommen.

4.1 Aufbau des TLS-Proxy

4.1.1 Multithreading

Um in der Lage zu sein, mehrere Sessions gleichzeitig abwickeln zu können, verwendet der TLS-Proxy die POSIX-Threads-Schnittstelle des Linux-Kernels. Um Verzögerungen beim Verbindungsaufbau zu vermeiden, werden mehrere Threads1 auf „Vorrat“ gestartet und in einem Threadpool vorgehalten. Reicht dieser Pool nicht aus, um die anstehenden TCP- Verbindungsanforderungen zu bedienen, können weitere Threads gestartet werden2. Dadurch muss bei einer Verbindungsanfrage eines Clients kein neuer Thread gestartet werden. Es wird einfach einer aus dem Pool zugewiesen, der nach Beendigung der Verbindung wieder an den Pool zurückgegeben wird. Für jede SMTP-Session werden im TLS-Proxy zwei Threads benützt, welche die Client- und die Serverseite abbilden. Ein Thread ist für die Verbindung zwischen Client und Middle-Proxy (siehe Abschnitt 4.1.2) sowie für die TLS-Session auf Client-Seite zuständig. Der andere Thread ist für die Verbindung zwischen Middle-Proxy und Server sowie für die TLS-Session mit dem Server zuständig.

1Die Anzahl ist mit den Konfigurationseinstellungen NUM_THREADS (siehe Abschnitt 7.1) einstellbar. 2Bis zu einem konfigurierbaren Limit, siehe Abschnitt 7.1: MAX_NUM_THREADS.

27 4. TLS-Proxy-Engine von Underground_8 28

Aufgrund dieser Struktur ist auch eine Thread-Synchronisation unabdingbar. Jedem Proxy- Objekt ist deshalb ein Mutex zugeordnet, um den Zugriff auf kritische Elemente zu steuern und nur einen parallelen Zugriff zu erlauben.

Um die verwendeten OpenSSL-Bibliotheken in einer Multi-Threaded-Umgebung sicher nutzen zu können, muss der TLS-Proxy Mutexe bereitstellen, welche von den Bibliotheken eingesetzt werden, um kritische Bereiche zu schützen. Dazu müssen mit Hilfe der in Listing 4.1 gezeigten Funktionen Callbacks gesetzt werden[38]. Ohne diese Callbacks müsste jeder Aufruf an die OpenSSL-Bibliothek mit Mutexen gesichert werden, was den Programmablauf quasi Serialisieren würde.

1 /∗ callback function for unique thread id ∗/ 2 CRYPTO_set_id_callback(openssl_thread_id); 3 4 /∗ callback lock function ∗/ 5 CRYPTO_set_locking_callback(openssl_mutex_lock); 6 7 /∗ callbacks for creating dynlock structures ∗/ 8 CRYPTO_set_dynlock_create_callback(openssl_dl_create); 9 CRYPTO_set_dynlock_destroy_callback(openssl_dl_destroy); 10 CRYPTO_set_dynlock_lock_callback(openssl_dl_lock); Listing 4.1: Setzen der OpenSSL Callbacks, für die Verwendung in Multi-Threaded- Umgebungen.

Werden diese Callbacks jedoch definiert, legt sich OpenSSL nicht auf eine Thread-Implemen- tierung oder Locking-Art fest. Wie das Locking genau durchgeführt wird, ist dem Programm überlassen. OpenSSL ruft nur bei Bedarf nach Locking die hinterlegten Callbacks auf. Ex- emplarisch findet sich in Listing 4.2 die Callback-Funktion openssl_mutex_lock, in der das Locking mit einem Array aus Mutexen implementiert wird. Die letzten drei Callbacks sind zwar optional, doch erlauben sie den OpenSSL-Bibliotheken die Verwendung von Dynlocks, die die Performance verbessern können. Wie in [57] erläutert, werden Dynlocks noch nicht von OpenSSL intern benutzt, es könnte aber in Zukunft nötig sein. Um also für kommende Versionen gerüstet zu sein, werden auch die optionalen Callbacks implementiert.

1 void openssl_mutex_lock(int mode, int n, const char *file, int line) 2 { 3 if (mode & CRYPTO_LOCK) // lock or unlock? 4 { 5 pthread_mutex_lock( &(openssl_mutex[n])); //lock mutex for thread n 6 } 7 else 8 { 9 pthread_mutex_unlock( &(openssl_mutex[n])); //unlock mutex for thread n 10 } 4. TLS-Proxy-Engine von Underground_8 29

11 } 12 13 /** 14 * Creates a new dynlock structure (is used as callback function). 15 * @param *file Source file, from which the call is executed (usefull for debugging). 16 * @param line Source line in file, where call is executed (usefull for debugging). 17 * @return Returns a pointer to a new CRYPTO_dynlock_value structure. 18 */ 19 struct CRYPTO_dynlock_value *openssl_dl_create(const char *file, int line) 20 { 21 int st; 22 struct CRYPTO_dynlock_value *dl; 23 24 /* allocate memory */ 25 dl = (CRYPTO_dynlock_value *)malloc(sizeof(pthread_mutex_t)); 26 if (dl != NULL) 27 { 28 /* init mutex */ 29 st = pthread_mutex_init( &dl->mutex, NULL); 30 if (st != 0) /* error? */ 31 { 32 free(dl); 33 dl = NULL; 34 } 35 } 36 return (dl ); /* return new dynlock structure */ 37 } 38 39 /** 40 * If a dynlock isn't necessary anymore, this function will destroy it. 41 * @param *dl pointer to the dynlock structure, which should be destroyed. 42 * @param *file Source file, from which the call is executed (usefull for debugging). 43 * @param line Source line in file, where call is executed (usefull for debugging). 44 */ 45 void openssl_dl_destroy(struct CRYPTO_dynlock_value *dl, const char *file, 46 int line) 47 { 48 pthread_mutex_destroy( &dl->mutex); 49 free(dl); 50 } 51 52 /** 53 * Locks or unlocks the given dynlock structure (is used as callback). 54 * @param mode Value indicating, if lock (CRYPTO_LOCK) or unlock should be done. 55 * @param *dl dynlock structure, which should be locked/unlocked. 56 * @param *file Source file, from which the call is executed (usefull for debugging). 57 * @param line Source line in file, where call is executed (usefull for debugging). 4. TLS-Proxy-Engine von Underground_8 30

58 */ 59 void openssl_dl_lock(int mode, struct CRYPTO_dynlock_value *dl, 60 const char *file, int line) 61 { 62 if (mode & CRYPTO_LOCK) /* lock or unlock? */ 63 pthread_mutex_lock( &dl->mutex); 64 else 65 pthread_mutex_unlock( &dl->mutex); 66 }

Listing 4.2: Locking-Callback-Funktionen für OpenSSL

4.1.2 Anbindung der Content-Filter

Die Anbindung der Content-Filter ist im TLS-Proxy durch sogenannte Middle-Proxys vorgese- hen. Dadurch ist es einfach, bestehende Proxy-Systeme mit angebundenen Content-Filtern in den TLS-Proxy einzubinden und diese dadurch TLS-fähig zu machen. Vorausgesetzt wird die Funktion, den Client-Thread und den Server-Thread des TLS-Proxy miteinander zu ver- knüpfen, indem die Connection-ID durch den Middle-Proxy übertragen wird. Bei HTTP ist dies durch eine Manipulation des Headers realisiert. Für andere Protokolle muss demnach eine äquivalente Möglichkeit gefunden werden3. Wie in [Asp09, Kapitel 5.4.2] beschrieben, muss ein solcher Middle-Proxy zusätzlich die Möglichkeit haben, eine SMTP-Session mit einem weiteren Proxy aufzubauen, anstatt sich selbst zum Server zu verbinden. Dadurch ist auch die Verwendung von mehreren Middle-Proxys in einer Proxy-Chain möglich. Der letzte Proxy in dieser Reihe (Upstream-Proxy) ist in diesem Anwendungsfall dann der TLS-Proxy selbst. Das heißt, dass der letzte der Middle-Proxys (falls es mehr als einen gibt) eine TCP-Verbindung zum TLS-Proxy aufbaut. Für HTTP sind der Proxy-Cache Squid[48] (mit dem URL-Filter SquidGuard[49]) und der HTTP Anti Virus Proxy (HAVP)[27] (mit einer Anbindungsmöglichkeit für Virenscanner) als Middle-Proxys vorgesehen.

4.1.3 Verbindungsablauf

Der TLS-Proxy greift nicht in die verschlüsselte Verbindung selbst ein, um die Übertragung zu untersuchen, sondern schaltet sich schon beim TLS-Handshake ein. Abbildung 4.1 zeigt, wie ein normaler TLS-Handshake ohne Proxy stattfindet. 1. Eine Zertifizierungsstelle (CA) stellt dem Server ein Zertifikat aus. 2. Der Client vertraut dieser Zertifizierungsstelle. 3. Nach dem TCP-Handshake beginnt der Client mit dem TLS-Handshake.

3Bei SMTP wird dies zum Beispiel mit Hilfe des Kommandos NOOP erfolgen. 4. TLS-Proxy-Engine von Underground_8 31

4. Der Server benutzt in diesem TLS-Handshake jenes Zertifikat, das von der Zertifizie- rungsstelle signiert wurde. 5. Dadurch vertraut der Client nicht nur der Zertifizierungsstelle, sondern auch dem Server. 6. Die TLS-Session zwischen Client und Server kann nun beginnen.

Client CA Server 1. Stellt Zertifikat aus

2. Vertraut

3. Client hello 4. Server hello + Zertifikat 5. Client key exchange

6. TLS 6. TLS

Abbildung 4.1: TLS-Verbindungsaufbau und Vertrauensverhältnisse ohne Proxy

Der Client vertraut dabei der Zertifizierungsstelle, die das Zertifikat des Servers ausgestellt hat. Durch den Einsatz des TLS-Proxy muss der Client nur noch dessen Zertifizierungsstelle vertrauen. Die Vertrauensstellung zu anderen Zertifizierungsstellen können direkt im Proxy konfiguriert werden. Abbildung 4.2 zeigt den Ablauf des TLS-Handshake sowie die neuen Vertrauensverhältnisse. 1. Eine interne Zertifizierungsstelle hinterlegt ihren Private-Key am TLS-Proxy. 2. Der Client vertraut dieser internen Zertifizierungsstelle. 3. Eine externe Zertifizierungsstelle stellt dem Server ein Zertifikat aus. 4. Der TLS-Proxy vertraut dieser externen Zertifizierungsstelle. 5. Der Client beginnt mit dem TLS-Handshake mit dem TLS-Proxy. 6. Der TLS-Proxy beginnt den TLS-Handshake mit dem Server. 7. Der Server verwendet in diesem TLS-Handshake sein zuvor ausgestelltes Zertifikat. 8. Der TLS-Proxy vertraut durch sein Vertrauen in die externe Zertifizierungsstelle dem Server. 9. Der TLS-Proxy erstellt ein neues Zertifikat auf Grundlage des Serverzertifikates und signiert es mit dem Private-Key der internen Zertifizierungsstelle. 10. Der TLS-Proxy präsentiert dem Client dieses generierte Zertifikat im TLS-Handshake. 11. Durch sein Vertrauen in die interne Zertifizierungsstelle, vertraut der Client auch diesem Zertifikat. 4. TLS-Proxy-Engine von Underground_8 32

12. Die TLS-Session zwischen Client und TLS-Proxy sowie die TLS-Session zwischen TLS- Proxy und Server kann nun beginnen.

Client Int. CA Proxy Ext. CA Server 1. Hinterlegt private key 3. Stellt Zertifikat aus

2. Vertraut 4. Vertraut

5. Client hello 6. Client hello 7. Server hello + Zertifikat 8. Client key exchange 9. und 10. Server hello + neues Zertifikat 11. Client key exchange

12. TLS 12. TLS 12. TLS 12. TLS

Abbildung 4.2: TLS-Verbindungsaufbau und Vertrauensverhältnisse mit (TLS-)Proxy

Abschnitt 4.1.4 erläutert genauer, welche Zertifikate hier zum Einsatz kommen. Wie in Abschnitt 4.1.1 beschrieben, verwendet der TLS-Proxy zwei Threads pro SMTP- Verbindung eines Clients. Beim Verbindungsaufbau durch einen Client wird vom Proxy sowohl eine Verbindung zum Zielserver als auch zum Middle-Proxy aufgebaut und ein Objekt der Klasse Proxy erzeugt, um die Verbindungen abzuwickeln. Der Middle-Proxy baut nun selbst eine Verbindung zum TLS-Proxy auf. Zu diesem Zeitpunkt ist es aber nötig, eine eingehende TCP-Verbindung vom Middle-Proxy einem bestehenden Proxy oder ProtocolHandler-Objekt zuzuordnen, da mehrere Verbindungen gleichzeitig aktiv sein können. Ein Objekt der Klasse ConnectionTracker führt zu diesem Zweck eine Liste von ConnectionIDs und deren Zuordnung zu den Proxy-Objekten. Durch den Verbindungsaufbau ist der Client-Connection schon eine ID und ein Proxy/ProtocolHandler-Objekt zugeordnet. Die Zuordnung zur passenden eingehenden TCP-Verbindung durch den Middle-Proxy steht zu diesem Zeitpunkt noch aus. Sie wird durch die Übertragung der ConnectionID durch den Middle-Proxy realisiert. Bei HTTP verwendet der TLS-Proxy dazu einen eigenen HTTP-Header (X-TLS-Proxy-Id), welcher die ID transportiert. Durch das Auslesen dieses Headers auf der anderen Seite des Middle-Proxy kann diese Verbindung nun ebenfalls dem Proxy-Objekt zugeordnet werden. Nachdem sowohl auf Client- als auch auf Serverseite eine TLS-Session hergestellt wurde, kann der Proxy als Man-in-the-middle die übertragenen Daten im Klartext untersuchen. Dazu muss der Proxy das zu untersuchende Protokoll (in diesem Fall HTTP) verstehen. Diese Funktionalität ist in der ProtocolHandler-Klassenstruktur abgebildet. Für jedes unterstützte 4. TLS-Proxy-Engine von Underground_8 33

Protokoll wird von der Basisklasse eine protokollspezifische Klasse abgeleitet (hier HTTPHand- ler), welche die Member-Funktionen handleClientSide und handleServerSide implementieren muss. Dabei ist erstere für die SMTP-Verbindung zwischen Client und Middle-Proxy und letztere für die SMTP-Verbindung zwischen Middle-Proxy und Server zuständig.

4.1.4 Zertifikate

Der TLS-Proxy muss einem Client beim TLS-Handshake ein Zertifikat präsentieren, zu dem er auch den Private-Key besitzt. Um das zu erreichen, können entweder Zertifikate und deren Private-Keys am Proxy hinterlegt oder aber neue Zertifikate am Proxy selbst erzeugt werden. Der TLS-Proxy unterstützt nur die letztere Methode, da bei HTTP normalerweise nicht bekannt ist, zu welchen Servern sich die Clients verbinden werden. Dazu verwendet der TLS-Proxy eine integrierte Zertifizierungsstelle, um passende Zertifikate auszustellen und zu signieren. Abbildung 4.3 zeigt, welche Daten dazu benötigt werden, woher sie die Zertifizierungsstelle bezieht und wie die erzeugten Zertifikate weiterverwendet werden.

Abbildung 4.3: Zertfikatserstellung im TLS-Proxy (privater Schlüssel: rot, öffentlicher Schlüssel: grün)[Asp09, Abbildung 4.3]. 4. TLS-Proxy-Engine von Underground_8 34

4.1.4.1 Verifikation der Zertifikate

Die Verwendung des TLS-Proxy macht es möglich, die Liste der vertrauenswürdigen Zer- tifizierungsstellen zentral am Proxy vorzuhalten, anstatt jeden Client dementsprechend zu konfigurieren. Nicht nur die Aussteller, sondern auch die Gültigkeitszeiträume sowie die Vollständigkeit der Zertifikate können so zentral überprüft werden. Es ist ebenfalls vorgesehen, das Verhalten des TLS-Proxy in Abhängigkeit der Verifikationsergebnisse konfigurierbar zu machen. Dies ist mit der Konfigurationseinstellung „CERT_VERIFY_LEVEL“ möglich, deren Werte und Bedeutungen aus Tabelle 4.1 ersichtlich sind.

Level Verhalten des TLS-Proxy 1 Selbst wenn die Zertifikatsverifikation fehlschlägt, wird dem Cli- ent immer ein gültiges Zertifikat präsentiert. 2 Fehler, die während der Verifikation auftreten, werden auch in das Zertifikat an den Client eingebaut und so weitergegeben. 3 Schlägt die Verifikation fehl, wird die TLS-Verbindung abgelehnt.

Tabelle 4.1: Zertifikat-Verifikationslevel im TLS-Proxy.

4.1.4.2 Vergabe der Seriennummern

Da die Seriennummern von Zertifikaten einer Zertifizierungsstelle eindeutig sein müssen[CSF+08], kann sie die Zertifizierungsstelle des TLS-Proxy nicht einfach aus den Originalzertifikaten übernehmen, sondern muss für jedes Zertifikat eine eindeutige Seriennummer erzeugen. Selbst nach dem Ablaufen der Gültigkeit eines Zertifikates darf die Seriennummer nicht wiederverwen- det werden. Deshalb muss sie über einen Neustart des TLS-Proxy hinaus gespeichert werden. Wird ein Zertifikat innerhalb seines Gültigkeitszeitraumes nochmals angefragt, muss ihm dieselbe Seriennummer zugeordnet werden. Diese Voraussetzungen werden erfüllt, indem zu jeder verwendeten Seriennummer der Hash (SHA-1[Nat08]) des Originalzertifikates gespeichert wird. Um die geforderte Persistenz zu erreichen, werden diese Zuordnungen und die nächste frei verfügbare Seriennummer in einer Datei abgelegt.

4.1.5 Erweiterbarkeit für weitere Protokolle

Bei der Entwicklung des TLS-Proxy wurde auf eine möglichst einfache Erweiterbarkeit für neue Protokolle geachtet. Es ist vorgesehen, ein Protokoll durch Ableitung von der Basisklasse ProtocolHandler einzuführen. 4. TLS-Proxy-Engine von Underground_8 35

4.1.6 Der TPROXY-Patch

Um einen Proxy zu verwenden, müssen die Clients die Verwendung prinzipiell unterstützen. Außerdem muss der richtige Proxy auf jedem Client konfiguriert werden. Aus diesem Grund ist es oft gewünscht, dass ein Proxy transparent, also unsichtbar für den Client, arbeiten soll. Dabei leitet ein Paketfilter die Pakete an den Proxy weiter, ohne dass der Client davon wissen muss. Auf der Serverseite ist das nicht so einfach, weil die TCP-Verbindung zum Server mit der IP-Adresse des Proxy als Quelle und nicht der IP-Adresse des Clients aufgebaut wird. Damit ein Proxy auch für den Server transparent ist, muss er beim TCP-Verbindungsaufbau mit dem Server die IP-Adresse des Clients als Quelle verwenden. Normalerweise ist es jedoch nicht möglich, eine nicht-lokale IP-Adresse als Quelladresse zu verwenden. Bei älteren Linux-Kernel-Versionen (Serie 2.2.x) war dies noch möglich, wurde aber später wieder entfernt. Um diese Funktionalität wieder zu aktivieren, wird beim Linux-Kernel (vor der Version 2.6.28) ein TPROXY-Patch benötigt (siehe [52]). Ab Kernel-Version 2.6.28 ist diese Funktionalität wieder im Kernel inkludiert. Der TLS-Proxy kann die TPROXY-Funktionalität bei Bedarf verwenden, um einen voll- ständig transparenten Proxy zu bieten. Dadurch ist sichergestellt, dass die Pakete der TCP- Verbindungen den TLS-Proxy in beiden Richtungen passieren, auch wenn dies durch asymme- trisches Routing nicht garantiert ist.

4.2 Erweiterung des TLS-Proxy

Im Rahmen dieser Arbeit wurde ein SMTP/S-Proxy als Erweiterung für den vorhandenen TLS- Proxy entwickelt. Neben der Unterstützung für SMTP gibt es auch zusätzliche Anforderungen. Diese werden in den folgenden Abschnitten erläutert.

4.2.1 RFC-konforme Fehlermeldungen

Um Clients über Probleme des Proxy informieren zu können, werden bei HTTP passende HTML-Fehlerseiten erstellt und mit dem passenden HTTP-Fehlercode an den Client gesen- det. Bei Fehlern, die am Server auftreten, werden die Fehlerseiten einfach an den Client weitergeleitet. Ähnlich soll dies auch bei SMTP gelöst werden. Die Fehlermeldungen müssen mit SMTP- Returncodes versehen werden, die zum aktuellen Transaktionsstatus des Clients und zum aufgetretenen Fehler passen. Genauso soll der Text der Fehlermeldung dem User weitere Informationen geben, warum der Fehler aufgetreten ist. Fehlermeldungen des Servers kön- nen prinzipiell wie bei HTTP an den Client weitergeleitet werden, müssen jedoch eventuell ausgewertet, verändert oder unterdrückt werden4. 4z. B. beim Starten der TLS-Session (siehe Abschnitt 6.7.6). 4. TLS-Proxy-Engine von Underground_8 36

Stellt der Proxy ein Fehlerzustand fest, weiß der Server normalerweise davon nichts. Der Client kann zwar mit einem SMTP-Response informiert werden, der Server jedoch nicht. Dies ist problematisch, da Client und Server dann nicht mehr vom selben Status der Transaktion ausgehen. Bei Fehlern, die diesen Status ändern, muss deshalb der Proxy die SMTP-Verbindung abbrechen, damit keine Nachrichten verloren gehen können. Allgemein ist darauf zu achten, die Codes und Texte der Fehlermeldungen so zu wählen, wie es RFC5321[Kle08] bzw. RFC3207[Hof02] vorsehen.

4.2.2 Gemeinsam genutzte Zertifizierungsstelle

Für einen einzelnen TLS-Proxy war es ausreichend, die Erzeugung der benötigten Zertifikate als Teil des Programms zu implementieren. Mit SMTP soll jetzt ein weiterer Proxy dazukommen, der ebenfalls auf die Erzeugung von Zertifikaten angewiesen ist. Die zentrale Verwaltung und das Erzeugen von Zertifikaten ist deshalb eine sinnvolle Erweiterungsmöglichkeit. Diese Zertifizierungsstelle soll von mehreren Proxys gemeinsam genutzt werden können. Ein möglicher Proxy für IMAPS oder andere Protokolle kann zukünftig ebenfalls diese Zertifizierungsstelle nutzen.

4.2.3 Relay

Ein weiteres Produkt der Firma Underground_8, das AS Communication Gateway, bietet Spam- und Virenfiltermöglichkeiten in Form eines SMTP-Relays an. Es soll in Zukunft möglich sein, auch dieses Relay in Verbindung mit dem TLS-Proxy für SMTP zu nutzen. Dabei stellt der Proxy die Nachrichten nicht an den Zielserver, sondern an das Communication-Gateway zu. Eine verschlüsselte SMTP-Verbindung zum Relay ist explizit nicht vorgesehen, da davon ausgegangen wird, dass beide Dienste auf demselben Host arbeiten.

4.2.4 Erzwingen von TLS

In Einsatzszenarien mit hohen Sicherheitsanforderungen ist es sinnvoll, nur verschlüsselte Ver- bindungen zuzulassen. Der Proxy unterstützt dies, indem er die Verwendung von STARTTLS erzwingen kann. Wird STARTTLS zu einem (firmen-)internen Server erzwungen, so soll auch die Verwendung eines hinterlegten Zertifikates, anstatt eines selbst erzeugten, verpflichtend sein. Das ist wünschenswert, weil damit Man-in-the-middle-Attacken verhindert werden können (siehe Abschnitt 4.2.5). Ein Erzwingen von TLS ist jedoch auch ohne hinterlegten Zertifikaten und Private-Keys möglich. 4. TLS-Proxy-Engine von Underground_8 37

4.2.5 Hinterlegen von Zertifikaten

Für interne (SMTP-)Server kann es sinnvoll sein, deren Zertifikate (und Private-Keys) am Proxy zu hinterlegen. Auf diese Weise kann der Proxy einen Schutz gegen Man-in-the-middle- Attacken von Insidern bieten. Das ist möglich, indem er das beim TLS-Handshake präsentierte Zertifikat mit dem hinterlegten vergleicht und im Fehlerfall die SMTP-Verbindung abbricht. Kapitel 5

Entwurf

5.1 Aufgabenstellung

Die in Kapitel 4 vorgestellte TLS-Engine soll um die Unterstützung für SMTP erweitert werden. Anstatt, wie bei HTTPS bzw. SMTPS, den TLS-Handshake schon beim TCP-Verbindungs- aufbau auszuführen, soll die STARTTLS-Erweiterung von SMTP unterstützt werden. Die Möglichkeit, TLS-Zertifikate on-the-fly zu erzeugen, die schon bei HTTPS verwendet wird, soll nun auch im SMTPS-Teil vorhanden sein. Es ist deshalb sinnvoll, diese Funktionalität aus der Engine herauszulösen, sodass eine zentrale Zertifizierungsstelle für alle durch den TLS-Proxy unterstützten Protokolle zur Verfügung steht. Dabei sollen die protokollspezifi- schen Proxys die Zertifizierungsstelle verwenden, indem sie das Originalzertifikat des Servers übergeben und daraufhin ein passendes generiertes Zertifikat erhalten. Das Standardszenario bei HTTP bzw. HTTPS besteht aus internen Clients, die sich zu externen Servern verbinden. Dies soll auch für den SMTP-Teil möglich sein, jedoch tritt gerade bei SMTP auch der umgekehrte Fall regelmäßig auf. Diese Lösung soll deshalb auch eine Reverse-Proxy-Funktionalität aufweisen, mit der Verbindungen von externen Clients bzw. Servern zu einem oder mehreren internen Servern möglich sind. Eine genauere Vorstellung der Szenarien findet sich in Abschnitt 5.2. Neben der Erzeugung von Zertifikaten on-the-fly soll es auch möglich sein, Zertifikate einzelner (interner) Server zu hinterlegen. Diese Zertifikate können verwendet werden, wenn ein Verbindungsversuch zu einem dieser Server erfolgt. In einem solchen Fall kann das vom Server präsentierte Zertifikat mit dem hinterlegten verglichen werden, um Man-in-the-middle-Attacken zu erkennen und zu verhindern. Anstatt Mail-Nachrichten direkt an den Zielserver zuzustellen, soll es möglich sein, diese an einen SMTP-Relay-Server zuzustellen, wo sie weiterverarbeitet werden. Trotzdem soll auch hier eine Verschlüsselung der SMTP-Verbindung bis zum Proxy ermöglicht werden. Die Untersuchung nach Spam und Viren soll weiterhin mit einem bereits vorhandenen

38 5. Entwurf 39

BASH[22]-Skript (mailscanner.sh) vorgenommen werden. Es ist noch zu evaluieren, ob der Middle-Proxy weiterhin für die Anbindung zuständig ist oder ob das Skript direkt durch den TLS-Proxy verwendet werden soll. Durch die vorhandene Filter-Infrastruktur des MF Security Gateway ist es erst dann möglich, eine Nachricht aufgrund ihrer Mail-Domäne abzulehnen, wenn sie vollständig ange- nommen wurde. Das ist nicht praktikabel. Deshalb soll es in der zu entwickelnden Lösung schon im SMTP-Dialog möglich sein, die Nachricht aufgrund ihrer Mail-Domäne abzulehnen. Es soll weiters möglich sein, die Verwendung von TLS mit Konfigurationsparametern zu erzwingen. Wird in diesem Fall keine STARTTLS-Unterstützung angekündigt oder diese vom Client nicht angefordert, so wird die Zustellung der Mail-Nachricht nicht zugelassen. Die Logging-Informationen der Anwendung sollen zentral mit Syslog[Ger09] zur Verfügung gestellt werden und wichtige Ereignisse wie Start/Stopp der Anwendung oder Fehlerfälle sowie Informationen zur Verbindung enthalten. Die Anwendung soll, wie die TLS-Engine für HTTPS, in der Programmiersprache C++ unter Verwendung der OpenSSL[39] Bibliothek entwickelt werden. Ebenfalls soll sie aus Performanzgründen multithreaded mit Posix-Threads[IG04, Kapitel 2.9] ausgelegt werden. Dabei sind geeignete Synchronisationsmechanismen zu verwenden. Um die Integration zu erleichtern, soll die Anwendung in die vorhandene LFS[31]-Build- Umgebung eingebettet werden.

5.2 Einsatzszenarien

Dieser Abschnitt beschreibt mögliche Einsatzszenarien des SMTPS-Proxy. Die genaue Abbil- dung mit dem Proxy sowie die Konfiguration der Szenarien finden sich in Abschnitt 9.2.

5.2.1 Interne Clients verwenden beliebige externe Mailserver

Gerade kleinere Firmen betreiben oft keinen eigenen (internen) Mailserver und so werden für den Mail-Versand ein oder mehrere externe Mailserver verwendet. Als Clients können hier sowohl Mail User Agents (MUAs) auf Endgeräten oder MTAs auf internen Servern fungieren. In solchen Fällen sollen ausgehende Mails sowohl auf dem Weg bis zur Firewall als auch von dort bis zum externen Mailserver verschlüsselt übertragen werden. Der SMTPS-Proxy kann zusätzlich zur normalen Funktionalität die Verwendung von STARTTLS erzwingen. In besonders sicherheitskritischen Umgebungen kann dies gewünscht sein, um zu verhindern, dass SMTP-Server oder SMTP-Clients ohne TLS-Funktionalität verwendet werden. Diese Anforderung kann jedoch auch „aufgeweicht“ werden, um älteren Clients, die STARTTLS nicht unterstützen, SMTP-Verbindungen zu ermöglichen. Eine TLS-Session zwischen Proxy und SMTP-Sever kann dennoch aufgebaut oder sogar erzwungen werden. 5. Entwurf 40

5.2.2 Interne Mailserver empfangen Mails von externen Servern

Die (firmen-)internen Mailserver sollen Mails von beliebigen externen Servern empfangen können. Ein Erzwingen von TLS auf Sender-Seite (extern) ist deshalb nicht empfehlenswert. Intern soll der Mail-Transport dennoch verschlüsselt ablaufen. In diesem Szenario ist es nützlich, zusätzlich zur Erzeugung von Zertifikaten on-the-fly, die Zertifikate und Private-Keys von internen Servern am Proxy zu hinterlegen. Wenn zusätzlich noch die Verwendung von STARTTLS zu internen Servern erzwungen wird, können auch Man-in-the-middle-Attacken im internen Netz erkannt und verhindert werden1. Der Proxy muss dazu bei jeder Verbindung zu einem internen Server das Zertifikat, das der Server beim Handshake präsentiert, mit dem passenden hinterlegten Zertifikat vergleichen. Sind diese Zertifikate nicht gleich, wurde ein Angriff erkannt und die Verbindung kann abgebrochen werden. Aufgrund der Netzwerktopologie kann es vorkommen, dass interne Clients, wenn sie den internen Server erreichen wollen, trotzdem den Proxy passieren. Dies tritt zum Beispiel auf, wenn der Server sich in einer DMZ2 befindet. In so einer Ausgangslage können auch die SMTP-Verbindungen zwischen Clients und Server verschlüsselt werden. Zusätzlich bietet der Proxy den Schutz gegen Man-in-the-middle-Attacken auch im internen Netz, indem er SMTP- Verbindungen abbricht, wenn das präsentierte Serverzertifikat nicht mit dem hinterlegten Zertifikat übereinstimmt.

5.2.3 TLS-Sessions trotz fehlender TLS-Unterstützung am Server

Nicht alle SMTP-Server unterstützen die STARTTLS-Erweiterung. Es mag deshalb wün- schenswert erscheinen, trotzdem eine TLS-Session aufzubauen (zumindest bis zum Proxy). Ein solches TLS-Offloading3 wird im SMTPS-Proxy nicht unterstützt4. Ein wichtiges Ziel bei der Entwicklung des Proxy ist es, eine Verbesserung und keine Verringerung der Sicherheit zu erreichen. Wird aber dem Client vorgespielt, dass er über eine verschlüsselte SMTP-Verbindung kommuniziert, obwohl die SMTP-Verbindung vom Proxy zum Server im Klartext stattfindet, so ist die Sicherheit nur vorgetäuscht.

5.2.4 Zentraler SMTP-Relay-Server

In vielen Firmen ist bereits ein zentrales SMTP-Relay vorhanden, das für die Untersuchung der Mails nach Spam oder Viren zuständig ist. Der SMTPS-Proxy kann diese bestehende Infrastruktur nutzen, indem er die Mails nicht an den Zielserver, sondern an dieses Relay zustellt. Die in Abschnitt 2.4 beschriebenen Nachteile von SMTP-Relays gelten hier dennoch. 1Das Hinterlegen des Private-Keys ist in diesem Fall für das Erzwingen von STARTTLS unbedingt erforder- lich. 2De-militarisierte Zone (DMZ) 3Terminierung der TLS-Session auf dem Proxy, um z. B. den Server zu entlasten. 4Eine Ausnahme gibt es bei der Verwendung der Funktion SMTP_RELAY_HOST (Siehe Abschnitt 9.2.5) 5. Entwurf 41

5.3 Design

5.3.1 Struktur

Die Proxys für SMTP bzw. HTTP teilen sich einen Großteil der Codebasis. Es liegt deshalb nahe, beide in der gleichen Applikation zusammenzufassen, um eine Parallelentwicklung zu vermeiden. Der TLS-Proxy sieht dazu bereits einen Kommandozeilenparameter vor, der schon beim Start das zu verwendende Protokoll festlegt. Dadurch kann trotz dieser Integration für jedes Protokoll ein separater Dienst betrieben werden.

5.3.2 Zertifizierungsstelle

In der vorhandenen TLS-Engine ist die Zertifizierungsstelle als Klasse implementiert. Sie enthält zwar schon Synchronisationsmechanismen für den parallelen Zugriff von mehreren Threads, ist jedoch auf die aktuell laufende Instanz des Proxy beschränkt. Diese Funktionalität soll nun ausgelagert werden und allen laufenden Instanzen zur Verfü- gung stehen. Weiters muss die neue Zertifizierungsstelle die vergebenen Seriennummern zentral verwalten, unabhängig davon, wann welcher Proxy gestartet oder gestoppt wird.

Die Kommunikation der Proxys mit der Zertifizierungsstelle wird mit Domain Sockets[Ste92, Abschnitt 6.3 ff.] wird unter Verwendung des in Tabelle 5.1 beschriebenen Protokolls imple- mentiert. Die korrekte Synchronisation zwischen den Threads der Zertifizierungsstelle ist vor allem wichtig, um ein erneutes Verwenden einer bereits vergebenen Seriennummer zu verhindern. Die wäre nicht zulässig, da laut [CSF+08] ein Zertifikat durch den Issuer (die Zertifizie- rungsstelle) und die Seriennummer eindeutig bestimmt ist und eine doppelte Vergabe einer Seriennummer diesem Prinzip widersprechen würde. Weiters muss der konsistente Zustand des Zertifikatspeichers auch im Falle eines unvorhergesehenen Abbruchs des Programms gesichert werden.

5.3.3 Anbindung der Content-Filter

Neben der Möglichkeit, TLS-gesicherte Verbindungen am Proxy im Klartext zu untersuchen, ist auch die Überprüfung dieses Klartextes auf Spam und Viren Teil der Aufgabe. Als Abstraktion zwischen den verschiedenen Filtern und dem bisher verwendeten Proxy (ProxSMTP) dient das BASH-Skript „mailscanner.sh“. Dadurch ist es möglich, zwischen den im Hintergrund verwendeten Virenscannern ClamAV und Kaspersky AntiVirus frei zu wechseln oder auch beide zu kombinieren. Dieses Skript soll nun auch weiter verwendet werden, wobei die Art der Anbindung an den TLS-Proxy noch entschieden werden muss. 5. Entwurf 42

Kommandos der Proxys

GENCRT [CAERR] [TIMEERR] CRLF Weist die Zertifizierungsstelle an, ein Zertifikat

mit den Werten des Originalzertifikats zu erzeugen.

Parameter CAERR Erzeugt ein fehlerhaftes Zertifikat.

Parameter TIMERR Übernimmt den Gültigkeitszeitraum des Originalzertifikats.

Parameter LEN Länge der DER-Daten des Zertifikats in Bytes.

QUIT CRLF Beendet die Kommunikation mit der Zertifizierungsstelle. Antworten der Zertifizierungsstelle

+OK GENCRT CRLF Signalisiert die erfolgreiche Erzeugung des Zertifikats

und übergibt es im DER-Format.

Parameter LEN Länge der DER-Daten des Zertifikats in Bytes.

-ERR GENCRT [Fehlermeldung] CRLF Signalisiert einen Fehler.

Parameter Fehlermeldung Enthält eine Beschreibung des aufgetretenen Fehlers. 1 Schlüsselwörter bzw. Parameter in eckigen Klammern ’[]’ sind optional. 2 Schlüsselwörter bzw. Parameter in spitzen Klammern ’<>’ sind verpflichtend.

Tabelle 5.1: Protokoll zur Kommunikation mit der Zertifizierungsstelle

5.3.3.1 ProxSMTP als Middle-Proxy

Die erste Möglichkeit, die Beibehaltung des ProxSMTP als Middle-Proxy, kann schon eine fertige Anbindung an das „mailscanner.sh“-Skript vorweisen. Bei der Verwendung durch den TLS-Proxy könnte das bestehende Middle-Proxy-Konzept, das schon der HTTPS-Teil benützt, beibehalten werden. Zum Zeitpunkt des Entwurfs erweckte die Software den Anschein, nicht mehr weiterent- wickelt zu werden (Letztes Release 1.8 vom 30.6.2008). Jedoch gibt es seit 23.1.2011 wieder Commits des Autors in seinem GIT[15]-Repository und auch ein neues Release (Version 1.9). Der Quellkode des ProxSMTP-Projekts ist nur spärlich dokumentiert, was eigene Erweite- rungen oder Fehlerbehebungen schwierig und aufwendig macht. Details zu ProxSMTP finden sich auch in Kapitel 3.

5.3.3.2 Direkte Anbindung

Um das Skript „mailscanner.sh“ direkt an den TLS-Proxy anzubinden, müsste die Funktionali- tät des ProxSMTP ebenfalls integriert werden. Dazu müsste aber auch die Struktur verändert werden, was Auswirkungen auf den HTTPS-Teil des Proxy haben würde. Andererseits würden dadurch auch zeitaufwendige Änderungen oder Erweiterungen am 5. Entwurf 43

ProxSMTP, falls die Funktionalität nicht ausreicht, unnötig.

5.3.3.3 Entscheidung

Der TLS-Proxy für HTTPS wird in aktuellen Produkten verkauft und auch eingesetzt. Eine Weiterentwicklung für SMTPS soll daher die bestehende Funktionalität nicht bzw. möglichst wenig beeinflussen. Für die direkte Anbindung des „mailscanner.sh“-Skripts würde jedoch ein Abrücken vom Middle-Proxy-Konzept (zumindest für den SMTPS-Teil) erforderlich sein. Darum wurde für eine Beibehaltung von ProxSMTP als Middle-Proxy entschieden. Reicht dessen Funktionalität nicht mehr aus oder muss er aus anderen Gründen ausgetauscht werden, können ihn leicht andere SMTP-Proxy-Lösungen (siehe z. B. Kapitel 3) ersetzen, da mit SMTP eine stabile Schnittstelle zur Verfügung steht.

5.3.4 TLS-Funktionalität

Die Möglichkeit, die SMTP-Verbindung mit STARTTLS zu verschlüsseln, soll vom Vorhanden- sein einer separaten TLS-Lizenz für das MF Security Gateway abhängig gemacht werden. Ist eine solche nicht vorhanden, so soll eine Unterstützung dafür auch nicht angekündigt werden. Versucht ein Client in diesem Fall trotzdem dieses Kommando auszuführen, so wird es vom Proxy abgelehnt. Ist eine Lizenz vorhanden, wird die Ankündigung noch von der STARTTLS-Unterstützung des Servers abhängig gemacht. Dadurch wird kein falscher Eindruck von Sicherheit erweckt, wenn der Server eine solche gar nicht bieten kann. Die Entscheidung, ob die TLS-Funktionalität bei einer SMTP-Verbindung überhaupt verwendet wird, bleibt aber immer noch dem Client überlassen. Dies ist in besonders sicher- heitskritischen Bereichen aber möglicherweise nicht akzeptabel. Der TLS-Proxy soll deshalb die Möglichkeit bieten, die Verwendung von TLS zu erzwingen. Hierbei wird unterschieden, ob dies auf Client- oder Serverseite erfolgen soll. Eine genauere Konfiguration soll es möglich machen, dies auf externe oder interne Clients oder Server zu beschränken. Um dem Client ein gültiges Zertifikat präsentieren zu können, muss durch die Zertifi- zierungsstelle (siehe 5.3.2) ein für den aktuellen Server passendes Zertifikat generiert und signiert werden. Für Server, deren Zertifikate und Private-Keys vorliegen, können diese am Proxy hinterlegt und im Falle eines Verbindungsaufbaus verwendet werden, anstatt ein neues Zertifikat zu erzeugen. Durch diese Hinterlegung ist es auch möglich, das Zertifikat mit jenem zu vergleichen, welches der Server präsentiert. Dadurch kann ein Man-in-the-middle-Angriff erkannt und verhindert werden. Der TLS-Proxy übernimmt auch die zentrale Verwaltung der vertrauenswürdigen Zertifizie- rungsstellen, damit dies nicht auf jedem einzelnen Client nötig ist. Dadurch kann der Proxy die von Servern präsentierten Zertifikate auf ihre Gültigkeit hin überprüfen. Die Verifikationstiefe kann mittels Konfigurationsparameter eingestellt werden. 5. Entwurf 44

5.3.5 Relay

Die Aufgabenstellung sieht eine Möglichkeit vor, alle Nachrichten per Relay zu einem weiteren Contentfilter weiterzuleiten. Dieser Filter soll zwar als SMTP-Relay angesprochen werden, läuft jedoch lokal auf demselben System. Eine unverschlüsselte SMTP-Verbindung auf Serverseite (zum Relay) ist deshalb akzeptabel. Auf der Clientseite kann das jedoch nicht akzeptiert werden. Um hier für eine TLS-Session bereit zu sein, muss trotz Relay eine direkte Verbindung zum Zielserver aufgebaut werden, um dessen Zertifikat zu empfangen.

5.3.6 Black-/Whitelists

Der TLS-Proxy soll sowohl auf IP-Adressen als auch auf Hostnamen der Server basierende Black- und Whitelists verwenden. Verbindungen zu Servern in der Blacklist werden nicht zugelassen, wogegen Verbindungen zu Servern in der Whitelist vom Proxy nicht weiter untersucht, sondern unverändert weitergeleitet werden. Ob sich eine Server-IP in einer der Listen befindet, kann schon beim TCP-Verbindungsaufbau überprüft werden. Der Hostname des Servers ist jedoch erst bekannt, wenn dieser sein Zerti- fikat präsentiert5. Der Ansatz, einen Reverse-DNS Lookup nach der IP-Adresse des Servers auszuführen, um zu einem Hostnamen zu kommen, ist in diesem Fall nicht zielführend (siehe [Asp09, Abschnitt 4.1.6]).

5.3.7 Fehlerbehandlung

Fehler, die ein Server über SMTP meldet, müssen sowohl danach überprüft werden, ob eine Behandlung im Proxy nötig ist, als auch (möglicherweise angepasst) an den Client weitergeleitet werden. Werden jedoch vom Proxy Fehlerzustände erkannt, ist eine genauere Behandlung erfor- derlich. Neben einem sinnvollen Logging ist es wichtig, auch für den Client verständliche Fehlermeldungen zu senden. Dazu werden zur aktuellen Fehlersituation passende SMTP- Responses nach RFC 5321[Kle08] erzeugt, um den Client über den Status der Transaktion zu informieren. Erwartet ein Client allerdings gerade keine Antwort, da er keine Anfrage gesendet hat, ist es unmöglich, die SMTP-Verbindung sinnvoll fortzusetzen. Ein Beenden der Verbindung ist jedoch nur durch den Client vorgesehen. Gegenüber dem Server tritt der Proxy als Client auf und kann durch RSET die Transaktion zurücksetzen oder durch QUIT die Kommunikation beenden. Gegenüber dem Client kann ein Server (in diesem Fall der Proxy) nur in einem Fall von sich aus handeln. Er kann, falls er den Dienst (vorübergehend) einstellen muss, dies dem Client mit einer Response „Service shutting down and closing transmission

5Die in der Willkommensnachricht oder der Antwort auf HELO/EHLO verwendeten Hostnamen werden nicht als verlässlich angesehen. 5. Entwurf 45 channel“ mitteilen und danach die TCP-Verbindung trennen. Auf diese Möglichkeit kann der Proxy ebenfalls zurückgreifen, falls er die SMTP-Verbindung nicht fortführen kann oder keine andere Reaktion zur Situation passt.

5.3.8 Behandlung von Timeouts

Wie schon in Abschnitt 2.1.9 erläutert, werden die in [Kle08] spezifizierten Timeouts nicht immer eingehalten (vergleiche Tabelle 2.1 mit Tabelle 2.2). Deshalb ist es nicht möglich, das Timeoutverhalten von Clients und Servern vorauszusagen. Auch das Hinterlegen von Timeoutwerten zu bekannten Servern ist nicht zielführend, da die Wartung einer solchen Liste sehr aufwendig ist. Ein Ansatz, mit Timeouts umzugehen, ist der Versuch, diese zu vermeiden. Gegenüber dem Server kann das NOOP-Kommando benutzt werden, um bei längerer Inaktivität des Clients die SMTP-Verbindung dennoch aufrechtzuerhalten. Dieses Kommando muss einerseits vom Server bestätigt werden, darf aber andererseits dessen internen Zustand nicht beeinflussen. Die einzige erlaubte Änderung des internen Zustands ist das Zurücksetzen des Timeoutzählers. Diese NOOP-Kommandos könnten also relativ problemlos in regelmäßigen Abständen gesendet werden6. Leider sieht [Kle08] in Richtung des Clients keine solche Möglichkeit vor. Jede Antwort an den Client würde dieser im Zusammenhang mit dessen letztem Kommando interpretieren. Der Proxy müsste also die Antwort senden, bevor er sie vom Server erhalten hat. Das ist weder vorgesehen noch ist es in den meisten Fällen möglich, eine sinnvolle Antwort auszuwählen. Der Proxy muss deshalb dafür sorgen, dass im Falle eines Timeouts des Clients auch die Verbindung mit dem Server unterbrochen wird.

6Wird ProxSMTP als Middle-Proxy verwendet, kann diese Aufgabe vom Middle-Proxy übernommen werden. Kapitel 6

Implementierung

6.1 Entwicklungsumgebung

Die Unterstützung für SMTP im TLS-Proxy wurde wie auch der Rest des Proxy in der Programmiersprache C++ entwickelt. Als Entwicklungsumgebung dient C/C++ Development Tooling (CDT)[12], eine C/C++ Integrated Development Environment (IDE) basierend auf der Eclipse[11]-Plattform. Neben Tests auf der Entwicklungs-Arbeitsstation wurde regelmäßig auch die Funktionalität auf einer Security-Appliance getestet, auf der das Endprodukt auch zum Einsatz kommen soll.

6.2 Verwendete Bibliotheken

Der TLS-Proxy soll auf einer Appliance laufen, die eine eingeschränkte Menge von Bibliotheken zur Verfügung hat. Es wird deshalb bewusst auf möglicherweise hilfreiche Bibliotheken, wie zum Beispiel boost[8], verzichtet. Andere Software auf der Appliance ist auf die vorhandenen Bibliotheksversionen angepasst. Eine Aktualisierung ist deshalb oft nicht möglich. Dies ist gerade bei besonders sicherheitsrelevanten Bibliotheken problematisch. In solchen Fällen1 wird die betreffende Bibliothek nicht für das gesamte System aktualisiert, sondern die aktuelle Version statisch zum TLS-Proxy gelinkt. Bei OpenSSL in der Versionsreihe 12 gab es einige Änderungen an der Programmierschnitt- stelle, sodass die TLS-Kernfunktionalität, die vor deren Veröffentlichung entwickelt wurde, nicht mehr damit kompatibel ist. Der TLS-Proxy verwendet deshalb eine OpenSSL-Version aus der 0.9-Reihe3. Das ist aber nicht weiter schlimm, da Fehlerbehebungen und Sicherheitspatches weiter in die 0.9-Reihe eingepflegt werden. Neben OpenSSL verwendet der TLS-Proxy noch die GNU C Library (glibc[18]) und

1Aktuell ist dies bei OpenSSL der Fall. 2Aktuell mit 4.6.2011 ist die Version 1.0.0d. 3Aktuell mit 4.6.2011 ist die Version 0.9.8r.

46 6. Implementierung 47

libcap[41].

6.3 Einbindung der SMTP-Funktionalität

Der TLS-Proxy sieht bereits eine Erweiterungsmöglichkeit für weitere Protokolle neben HTTP vor. Beim Start des Proxy wird festgelegt, welches Protokoll er benützen soll. Abhängig davon wird ein Handler-Objekt von einem passenden Typ (einer Subklasse von ProtocolHandler) für jede ankommende SMTP-Verbindung instantiiert. In Abbildung 6.1 ist jener Auszug der Klassenhierarchie ersichtlich, der für die Protokoll-Handler relevant ist. Der Handler muss

ProtocolHandler SMTPHandler

# proxy - proxy_mutex - serverPid - server_tls_mutex - mutex - relay_mutex - serverThreadRunning - server_tls_cond - working - relay_cond - connection + ProtocolHandler() - version + runClientThread() - serverGreeting + runServerThread() - first250 + handleError() - serverSupportsSTARTTLS + ~ProtocolHandler() - serverTLSdone # connectMiddleProxy() - forceClient # handleClientSide() - forceServer # handleServerSide() - relay - passThrough - serverTLSresult EmptyHandler HTTPHandler - clientEHLO - count250ResponseServer - mutex - count250ResponseClient - connection - midProxyClientSide + EmptyHandler() - version - midProxyServerSide + ~EmptyHandler() - smtpCommandTimeout - handleClientSide() + HTTPHandler() - handleServerSide() + handleError() + SMTPHandler() - handleError() + ~HTTPHandler() + handleError() - handleBody() + ~SMTPHandler() - handleRequestBody() - handleClientSide() - createRequestHeader() - handleServerSide() - handleResponse() - resetHandler() - handleClientSide() - getResponseCode() - handleServerSide() - handleMidProxyResponse() - handleServerResponse() - handleClientCommand() - handleMidProxyCommand()

Abbildung 6.1: Klassenhierarchie der Protokoll-Handler

für jede Verbindung zwei Funktionen implementieren, die jeweils in einem separaten Thread betrieben werden. Die Funktionen runClientThread bzw. runServerThread aus der Basis- klasse ProtocolHandler rufen dazu handleClientSide bzw. handleServerSide der jeweiligen Subklasse auf. Hierbei ist handleClientSide für die Kommunikation zwischen dem Client und der Clientseite des Middle-Proxy zuständig. Analog dazu behandelt handleServerSide die Session zwischen der Serverseite des Middle-Proxy und dem Server. Dadurch ist es möglich, den 6. Implementierung 48

Datenverkehr an diesen beiden Schnittstellen zu überprüfen und die Befehle und Antworten von Client, Server und Middle-Proxy zu behandeln und falls erforderlich zu ändern. Dies ist unter anderem nötig, um das STARTTLS-Kommando zu erkennen und die benötigten Schritte zur Herstellung der TLS-Sessions4 einzuleiten. Die Struktur des SMTP-Handlers ist in Abbildung 6.7 ersichtlich. Wie diese Funktionen die Verbindung abwickeln, ist je nach Protokoll unterschiedlich, weshalb jede Instanz des TLS-Proxy auch nur für jeweils ein Protokoll zuständig sein kann. Zu beachten ist weiters, dass eine Instanz eines ProtokollHandlers (bzw. einer seiner Sub- klassen) nach dem Ende einer SMTP-Verbindung auch wiederverwendet werden kann. Dadurch fällt der Aufwand der Instantiierung zwar nicht am Beginn jeder Verbindung an, es werden aber gewisse Aufräumarbeiten nötig, um nicht Daten verschiedener SMTP-Verbindungen zu vermischen.

6.4 Verbindungsablauf im TLS-Proxy

Die SMTP-Funktionalität stellt eine Erweiterung des TLS-Proxy für HTTP dar und verwendet deshalb auch dessen Struktur. Diese definiert den Ablauf der Verbindung und soll hier nur grob beschrieben werden (für Details siehe [Asp09]).

6.4.1 Verwaltung von Sockets und TLS-Session

OpenSSL[39] bietet mit der Datenstruktur BIO eine Abstraktionsebene zwischen der Pro- grammlogik und Ein-/Ausgabegeräten (Sockets, Dateien etc.). Durch die Verwendung dieser Struktur erhält man eine einheitliche Schnittstelle, unabhängig davon, ob auf dem Gerät eine TLS-Session gestartet wurde oder nicht. Diese Strukturen sind aber nicht unbedingt für die Verwendung in einer Applikation mit mehreren Threads geeignet (siehe [Asp09, Seite 99 ff.]). Um die Probleme zu lösen und eine einfachere Handhabung zu ermöglichen, bietet der TLS-Proxy die Klasse PIO (Proxy-I/O) als Wrapper bzw. Container für BIO-Strukturen an. Ein Objekt dieser Klasse kann (unter anderem) mit einem Socket verknüpft werden, um dessen TCP-Verbindung zu abstrahieren. Weiters wird eine BIO-Chain erzeugt, die eine BIO- Struktur für den Socket und ein Buffer-BIO enthält. Dadurch ist es genauso möglich, mit der Funktion readLine5 eine Zeile von Daten zu lesen wie auch eine SSL-Filter-BIO hinzuzufügen, um TLS-Sessions zu erzeugen. Ersteres ist besonders nützlich, da SMTP ein zeilenbasiertes Protokoll ist. Der Handler für SMTP verwendet hauptsächlich die Funktionen write bzw. writeString und read bzw. readLine. Es werden auch die Funktionen passOnTo und passOnToChunked angeboten, die aber im SMTP-Teil nicht verwendet werden (siehe Abschnitt 6.7.2).

4Im Normalfall ist dies eine TLS-Session zwischen Client und TLS-Proxy und eine weitere zwischen TLS-Proxy und Server. 5readLine verwendet intern die Funktion BIO_gets, die ein Buffer-BIO voraussetzt. 6. Implementierung 49

Sender Proxy Receiver Verbindungsaufbau Verbindungsaufbau 221 smtp.test.com Welcome 221 smtp.test.com Welcome HELO smtp.example.com HELO smtp.example.com 250 smtp.test.com 250 smtp.test.com MAIL FROM: MAIL FROM: 250 OK 250 OK RCPT TO: RCPT TO: 250 OK 250 OK DATA 354 go ahead Send Message Scan Message

DATA

354 go ahead Send Message Proccess Message

250 OK Message_ID

250 OK Message_ID QUIT QUIT 221 Bye 221 Bye

Abbildung 6.2: SMTP-Verbindungsablauf

Wird ein PIO-Objekt für Non-Blocking I/O verwendet, ist auch noch die Funktion waitOnEvent von Bedeutung (mehr dazu in Abschnitt 6.6), die es unter anderem ermög- licht, auf eingehende Daten zu warten. Mit insertSSL kann auf einem PIO eine TLS-Session gestartet werden, wogegen mit getSSL die SSL/TLS-Struktur des PIO-Objekts ausgelesen werden kann.

6.4.2 Threads

Für die Behandlung von Verbindungen werden für jede SMTP-Session eines Clients zwei Threads verwendet. Um nicht bei jedem TCP-Verbindungsaufbau die Threads erzeugen zu müssen, werden schon beim Start des Proxy ThreadPools erzeugt. Jeder der Threadpools verwendet einen Dispatcher, um eingehende Verbindungen anzu- nehmen6 und in eine Work-Queue einzureihen. Die Dispatcher sind ebenfalls dafür zuständig, neue Threads für den Pool zu erzeugen, falls alle Threads beschäftigt sind und die maximale Threadanzahl noch nicht erreicht ist.

6Der ThreadPool clientSide wartet hierbei auf Verbindungen vom Client, während der ThreadPool serverSide auf Verbindungen des MidProxy wartet. 6. Implementierung 50

Proxy

- client - server - serverSideCtx - clientSideCtx - originalClientCtx ThreadPool - createdCert - originalCert - minNumThreads - caSock - maxNumThreads - clientSock - listenSock - mutex PIO - waiting - depositedCert - name - bio - workQueue + Proxy() - buffer - workMutex + start() - sslChain - aliveMutex + startTLS() - nullBio - push + startServerTLS() - mutex - workerEnd + startClientTLS() + PIO() - threadSet + getDepositedCert() + connect() - dispatcherTid + tunnelTCP() + waitOnEvent() - workerMethod + getClientPIO() + insertSSL() - running + getServerPIO() + getClientIP() + getSSL() + ThreadPool() + getServerIP() + getIP() + start() + getCertificate() + getSocket() + isRunning() + getSSLContext() + isUP() + getWork() + setSSLContext() + read() + getListenSocket() + restartServer() + write() + thrLog() + disconnect() + readLine() + addWork() + disconnectClient() + writeString() + exitThread() + disconnectServer() + passOnTo() + stop() + ~Proxy() + passOnToChunked() + ~ThreadPool() - connectServer() + disconnect() - startWorker() - createOTFCert() + ~PIO()

(a) Klassendiagramm (b) Klassendiagramm (c) Klassendiagramm PIO ThreadPool Proxy Abbildung 6.3: Klassendiagramme ThreadPool, Proxy und PIO

Die Workerthreads beider Pools versuchen mit getWork eine Verbindung aus der Work- Queue zu erhalten. Ist diese jedoch leer, versetzen sich die Threads in einen Sleep-Zustand, bis sie mit einer Pthread-Condition (pthread_cond_t) vom Dispatcher geweckt werden. Konnte ein Thread eine Verbindung aus der Queue erhalten, ist er bis zu ihrer Beendigung für die Bearbeitung zuständig. Nach Abschluss der Verbindung versucht der Thread neue Arbeit zu bekommen und legt sich ansonsten schlafen.

6.4.3 Proxy-Objekte

Um nun die PIO-Objekte auf Client- sowie auf Serverseite zu verwalten, werden Proxy-Objekte verwendet. Beim Start einer TCP-Verbindung wird ein Proxy-Objekt erstellt, das sowohl den Socket zum Client als auch den Socket zum Server in PIO-Objekte verpackt. Um eine Verbindung zum Server herzustellen (Methode: start), muss zuerst dessen IP-Adresse aus der Netfilter-Tabelle ausgelesen werden (Siehe Listing 6.1 bzw. Methode: connectServer). Mit dieser Information ist auch schon möglich, eine White- bzw. Blacklist-Filterung nach Zieladresse 6. Implementierung 51 durchzuführen oder zu überprüfen, ob eine Schleife vorliegt (z. B. wenn die Zieladresse gleich der Adresse des Proxy ist). Wird eine IP-Adresse in der Whitelist gefunden, darf die SMTP- Verbindung nicht weiter untersucht werden. Mit tunnelTCP werden die Daten direkt zwischen Client und Server weitergeleitet.

1 struct sockaddr_in serverAddr; //original address will be written to this 2 socklen_t slen; 3 slen = sizeof(serverAddr); //length of address 4 /* 5 clientSock: file descriptor of client socket 6 SOL_IP: specifies socket operation on IP level 7 SO_ORIGINAL_DEST: socket operation to retreivce original destination address 8 */ 9 getsockopt(clientSock, SOL_IP, SO_ORIGINAL_DST, &serverAddr, &slen); Listing 6.1: Auslesen der originalen Zieladresse aus der Netfilter-Tabelle

An dieser Stelle würde, sofern TLS_ON=yes konfiguriert ist, versucht werden, eine TLS-Session herzustellen (Methode: startTLS, welche die Methoden startServerTLS und startClientTLS aufruft), zuerst mit dem Server, um sein Zertifikat zu erhalten, und dann mit dem Client. Für SMTP ist dies nicht anwendbar, da der Proxy das Klartextprotokoll so lange untersuchen muss, bis das STARTTLS-Kommando gesendet wird, und erst dann die SMTP-Verbindung auf TLS erweitern kann7. Ein Proxy-Objekt bietet auch Hilfsfunktionen, um Informationen zur aktuellen TLS-Session (getSSLContext und getCertificate), zu Client und Server (getClientPIO, getClientIP, getServerPIO, getServerIP) zu erhalten. Auch Funktionen zum Neustart einer Verbindung (restartServer) und zu deren Beendi- gung (disconnect, disconnectClient und disconnectServer) sind vorhanden. Die HTTP-Version des TLS-Proxy enthält zusätzlich in jedem Proxy-Objekt ein Objekt der Klasse CertificateAuthority, um die Zertifikate On the Fly (OTF) zu erzeugen. Das ist nun nicht mehr nötig, da die Zertifizierungsstelle im Rahmen dieser Arbeit ausgelagert wurde (siehe Abschnitt 6.5).

6.4.4 Connection Tracking

Ein Proxy soll natürlich nicht nur eine SMTP-Verbindung zur selben Zeit abwickeln können. Deshalb ist es nötig, eine Verbindung eines Clients mit der passenden Verbindung des Middle- Proxy zu assoziieren. Im TLS-Proxy wird dazu jeder Client-Verbindung eine ConnectionID zugewiesen. Nach dem Aufbau der Client-Verbindung wird vom TLS-Proxy eine Verbindung zum Middle-Proxy hergestellt. Sobald der Middle-Proxy eine Verbindung zum TLS-Proxy aufbaut, muss diese Verbindung einer ConnectionID zugeordnet werden. Diese IDs müssen nun verwaltet werden. 7In diesem Fall werden die Methoden startServerTLS und startClientTLS getrennt aufgerufen. 6. Implementierung 52

CertificateAuthority

- caCert - caPrivateKey - proxyPublicKey - serialNumber CAThread - mutex - certificates + threadId - file - clientSocketfd ConnectionTracker - validPeriod - clientPIO - nextId - ca + CertificateAuthority() - connectionMap + createCertificate() + CAThread() - mutex + ~CertificateAuthority() + ~CAThread() + ConnectionTracker() + loadFromFile() + getClientSocketfd() + getNextConnectionId() + startUp() + run() + removeConnection() + cleanUp() + threadCleanUp() + getConnectionById() - getCertInfo() - readLine() + ~ConnectionTracker() - save() - sendResponse()

(a) Klassendiagramm Connecti- (b) Klassendiagramm Certifica- (c) Klassendiagramm CA- onTracker teAuthority Thread Abbildung 6.4: Klassendiagramme ConnectionTracker CertificateAuthority CATHread

Die Klasse ConnectionTracker übernimmt diese Aufgabe, indem sie eine Liste von IDs und zugehörigen Proxy- oder ProtocolHandler-Objekten vorhält und durch Synchronisations- mechanismen einen Thread-sicheren Zugriff von mehreren Threads ermöglicht. Es ist durch die Verwendung eines void-Zeigers freigestellt, welchen Objekttyp man einer ConnectionID zuordnen möchte. Dieser Ansatz wurde gewählt, um für zusätzliche Erweiterungen flexibler zu sein. Allerdings kann der Compiler in diesem Fall keine Typprüfung durchführen. In der vorliegenden Version ist dies nicht direkt problematisch, da der Zeiger nur für Objekte des Typs ProtocolHandler (bzw. dessen Subklassen) verwendet wird. Ein Typecast ist deshalb problemlos möglich. Ändert sich das jedoch bei zusätzlichen Erweiterungen, muss eine manuelle Typprüfung erfolgen. Zu Beginn einer Verbindung durch einen Client wird unter anderem ein ProtocolHandler- Objekt von passendem Typ erzeugt und dessen Methode runClientThread aufgerufen. Diese Methode lässt durch Aufruf der Methode getNextConnectionId(this) vom Connection-Tracker eine neue ID für den Handler erzeugen. Diese ID muss nun durch den Middle-Proxy übertra- gen werden. Der Vorschlag aus [Asp09, Seite 89 f.] kann dazu in einer vereinfachten Weise angewendet werden. Die Vereinfachung ist deshalb möglich, weil der verwendete Middle-Proxy ein NOOP-Kommando auch vor dem Erhalt der Willkommensnachricht des Servers zulässt. Die Connection-ID wird wie folgt übertragen: • Nachdem die Client-Seite des ProtocolHandler die Verbindung zum Middle-Proxy herge- stellt hat, wird folgendes Kommando übertragen: „NOOP ConnID=“. 6. Implementierung 53

SMTPS−Proxy Clientseite Middle−Proxy SMTPS−Proxy Serverseite

Verbindungsaufbau

Verbindungsaufbau NOOP ConnID=

NOOP ConnID= getServerSideData()

getConnectionById()

handleClientSide()

handleServerSide()

Abbildung 6.5: Ablauf: Übertragung der Connection-ID

• Sobald die TCP-Verbindung des Middle-Proxy von einem ServerSideThread angenommen wurde, versucht dieser mit getServerSideData die ConnectionID zu erhalten. Diese Funktion benutzt, je nach verwendetem Protokoll, eine passende Methode. • Im Fall von SMTP versucht die Funktion eine Zeile vom Middle-Proxy zu lesen und, falls sie der obigen Form entspricht, zu parsen. • Mit der so erhaltenen ID kann die Methode getConnectionById des Connection-Trackers aufgerufen werden, um einen Zeiger auf das zugehörige ProtocolHandler-Objekt zu erhalten. • Der Thread ruft daraufhin die Funktion handleServerSide des ProtocolHandler-Objekts auf. • Somit sind beide Threads durch den ProtocolHandler verbunden. Sendet ein Client ein Kommando der Art NOOP ConnID=, darf es natürlich nicht durch den Middle-Proxy weitergeleitet werden. Stattdessen wird es in ein einfaches Kommando NOOP umgewandelt.

6.5 Ausgelagerte Zertifizierungsstelle

Die ausgelagerte Zertifizierungsstelle arbeitet als eigener Daemon, mit dem verschiedene TLS- Proxy-Prozesse über Unix-Domain-Sockets kommunizieren können. Es ist auch sehr leicht möglich, stattdessen netzwerkfähige Sockets zu verwenden, um die Zertifizierungsstelle auch auf einem anderen Rechner betreiben zu können. Neben der Implementierung des in Tabelle 5.1 aus Abschnitt 5.3.2 vorgestellten Protokolls muss dieser Daemon noch folgende Aufgaben 6. Implementierung 54 erfüllen: • Sichere parallele Verarbeitung von mehreren Anfragen • Verwaltung der vergebenen Seriennummern8 • Erzeugung von gültigen Zertifikaten • Erzeugung von ungültigen Zertifikaten (nach Anfrage) • Erzeugung von abgelaufenen oder noch nicht gültigen Zertifikaten Die Kernfunktionalität befindet sich auch schon bei der Implementierung aus [Asp09] in einer separaten Klasse und kann deshalb großteils übernommen werden.

6.5.1 Kernfunktionalität der Zertifizierungsstelle

Bevor das erste Zertifikat erzeugt werden kann, muss die CertificateAuthority mit der statischen Klassenmethode startUp initialisiert werden. Obwohl die Zertifizierungsstelle an dieser Stelle bereits einsatzbereit wäre, werden normalerweise mit loadFromFile die Seriennummern und Gültigkeitsbereiche der bereits erstellten Zertifikate sowie die nächste freie Seriennummer geladen. Um nun ein Zertifikat zu generieren, muss zuerst ein Objekt der Klasse CertificateAuthority erzeugt werden. Dazu sind das Zertifikat der Zertifizierungsstelle, deren Private-Key und der Proxy-Public-Key, der in jedes erzeugte Zertifikat eingefügt wird, nötig. createCertificate

Für die Erzeugung selbst ist es dann nur noch nötig, der Methode createCertificate das Originalzertifikat zu übergeben und folgende Einstellungen vorzunehmen: • Der Parameter caerr legt fest, ob das Zertifikat bewusst als ein ungültiges Zertifikat erzeugt werden soll. • Der Parameter timerr legt fest, ob der Gültigkeitszeitraum des neuen Zertifikates aus dem Originalzertifikat übernommen werden soll oder nicht. Zuerst wird das Subject des Originals übernommen und Seriennummer und Gültigkeits- zeitraum von der Methode getCertInfo bezogen. Als Issuer des neuen Zertifikats wird das Subject des CA-Zertifikats eingetragen, um dem Client eine Überprüfung der Zertifikatskette zu ermöglichen. Falls per Parameter gewünscht, wird anstatt des generierten Gültigkeitszeitraumes jener des Originalzertifikates eingetragen (z. B. um ein abgelaufenes Zertifikat zu erzeugen). Ein ungültiges Zertifikat wird erzeugt, indem als Issuer jener des Originalzertifikats mit dem Zusatz „TLSProxy: Couldn’t verify CA“ eingetragen wird. Für den Client ist dieses

8Dabei muss sichergestellt werden, dass einmal vergebene Seriennummern nicht wiederverwendet werden. 6. Implementierung 55

Zertifikat durch den veränderten Issuer nun nicht mehr gültig, ein Benutzer müsste eine Ausnahme für dieses Zertifikat erlauben. getCertInfo

Die Methode getCertInfo überprüft, ob zu einem übergebenen Key (Secure Hash Algorithm, Version 1 (SHA1) Hash des Originalzertifikats) bereits ein Zertifikat erzeugt wurde (das noch mindestens 10 Minuten gültig ist). Ist dies nicht der Fall, werden die Informationen zum Zertifikat in die interne Datenstruktur eingetragen. Die Seriennummer wird dabei aus dem internen Zähler übernommen, der auch regelmäßig in einer Datei gespeichert wird. Der Gültigkeitszeitraum wird so gewählt, dass das Zertifikat für eine konfigurierbare Anzahl an Tagen9 gilt. Am Ende der Methode wird in beiden Fällen eine Struktur mit den Informationen Serien- nummer und Gültigkeitszeitraum des Zertifikates zurückgegeben. save

Die Methode save wird benutzt, um die aktuellen Daten der Zertifikate persistent in einer Datei abzulegen. Dazu wird in die erste Zeile die nächste freie Seriennummer geschrieben und danach durch die Zertifikate im Speicher iteriert. Von jenen Zertifikaten, die noch gültig sind, werden die Seriennummer, der Zeitraum der Gültigkeit und der Hashwert des originalen Zertifikates (SHA1) in die Datei eingetragen. Durch den Hashwert des originalen Zertifikates wird indirekt auch festgehalten, für welchen Server das Zertifikat ausgestellt wurde. Abgelaufene Zertifikate werden an dieser Stelle auch aus der Datenstruktur im Speicher entfernt. Mithilfe dieser Datei ist es auch nach einem Absturz oder bei einem Neustart der Zertifi- zierungsstelle möglich, den korrekten Zustand wiederherzustellen (nächste freie Seriennummer, aktuell gültige Zertifikate). Die Zertifikate selbst müssen nicht gespeichert werden, da sie jederzeit aus den vorhandenen Informationen neu erzeugt werden können. Ein Caching von Zertifikaten findet nicht statt, wäre aber als Erweiterung denkbar.

1 2 3 4 5 ... Listing 6.2: Aufbau des Zertifikatsspeichers

6.5.2 Initialisierung

Bei der Initialisierung der Zertifizierungsstelle müssen folgende Aufgaben erledigt werden:

9Konfigurationsparameter: CERT_VALID_PERIOD 6. Implementierung 56

• Parsen der Kommandozeilenparameter • Initialisierung der OpenSSL Bibliothek • Entkoppelung von Standardinput und Standardoutput (Betrieb als Daemon) • Ablegen der Root-Rechte • Binden an den Socket Bis auf die Bindung an einen Socket kann die Implementierung dazu aus dem TLS-Proxy annähernd übernommen werden. Die Zertifizierungsstelle verwendet eine eigene Konfigurati- onsdatei und eigene Konfigurationsparameter.

6.5.3 Signalbehandlung

Im Normalzustand wartet die Zertifizierungsstelle, meist als Daemon im Hintergrund, auf eingehende Verbindungen. Eine direkte Interaktion mit einem Benutzer ist nicht vorgesehen. Die Zertifizierungsstelle verlässt sich deshalb auf Signale, um zu erfahren, wann sie beendet werden soll. Läuft die Zertifizierungsstelle im Vordergrund, so sendet die Tastenkombination Control-C ein SIGINT-Signal. Läuft sie jedoch als Daemon, kann natürlich kein Control-C empfangen werden, da sie nicht mit einem Terminal verbunden ist. In diesem Fall können mit Hilfe des kill-Kommandos Signale zur Beendigung des Prozesses gesendet werden. Normalerweise ist das SIGTERM (kill -15 Process ID (PID)) oder, falls ein Programm darauf nicht reagiert, SIGKILL (kill -9 PID). Weiterführende Details zu Signalen finden sich in [Ste95, Kapitel 10]. Um die Signale10 zu empfangen, muss das Hauptprogramm dafür einen Signal-Handler installieren. Wird ein Signal empfangen, für das kein Handler definiert wurde, wird die jeweilige Standardaktion ausgeführt11. Die Standardaktion ist nicht ausreichend, da noch „Aufräumarbeiten“ durchgeführt werden müssen, bevor das Programm beendet wird. Dazu zählt das Freigeben von Speicher und das Schließen von offenen Verbindungen. In einem Multithreaded-Programm kann nur ein Thread Signale empfangen. Damit dies der Hauptthread mit den korrekten Handlern ist, müssen alle anderen Threads diese Signale blockieren. Der Handler wird als statische Funktion cleanUp realisiert (siehe Abschnitt 6.5.4).

1 struct sigaction act; 2 memset (&act, '\0', sizeof(act)); // fill with zeroes 3 act.sa_handler = &cleanUp; 4 act.sa_flags = 0; //use no special mode 5 sigaction(SIGTERM, &act, NULL); //setup cleanUp as signal handler for SIGTERM 6 sigaction(SIGINT,&act,NULL); //setup cleanUp as signal handler for SIGINT 7 sigaction(SIGQUIT,&act,NULL); //setup cleanUp as signal handler for SIGQUIT 8 sigaction(SIGHUP,&act,NULL); //setup cleanUp as signal handler for SIGHUP Listing 6.3: Installieren eines Signal-Handlers

10In diesem Fall sind dies SIGINT oder SIGTERM. SIGKILL kann nicht abgefangen werden. 11Bei SIGINT, SIGTERM und SIGKILL führt dies zur sofortigen Beendigung des Programms. 6. Implementierung 57

1 sigset_t new_set,old_set; 2 sigemptyset(&new_set); //create empty sets -> all signals will be blocked 3 sigemptyset(&old_set); 4 pthread_sigmask(SIG_BLOCK,&new_set,&old_set);//block all signals. they are handled by the main thread Listing 6.4: Blockieren aller Signale an einen Thread

6.5.4 Threadverwaltung in der Zertifizierungsstelle

Die Zertifizierungsstelle muss mehrere Anfragen parallel bearbeiten und abwickeln können. Dazu setzt sie, wie der TLS-Proxy, auf einen Aufbau mit Threads. Für jede eingehende Verbindung wird ein Thread gestartet und ein Objekt vom Typ CAThread zugewiesen. Die Verwendung eines Thread-Pools ist hier ebenfalls denkbar. Dieser Ansatz wurde aber nicht gewählt, weil die Zeit, die zum Starten eines Threads benötigt wird, im Gegensatz zu der Zeit, die für kryptographischen Operationen der Zertifizierungsstelle benötigt wird, vernachlässigbar klein ist. Da es in C++ nicht direkt möglich ist, eine Klassenfunktion als Handler für einen Thread zu definieren, muss dieser Handler eine statische Funktion sein. Dieser Funktion wird das CAThread-Objekt übergeben, welches unter anderem den File-Descriptor der eingehenden Verbindung enthält. Der Handler (handleCARequest) maskiert alle Signale für diesen Thread, da diese bereits vom Hauptthread behandelt werden. Danach ruft er die Memberfunktion run des CAThread-Objekts auf, um die Bearbeitung von Anfragen zu starten. Nach Beendigung dieser Funktion ist auch die Verbindung bereits beendet und der Handler führt mit threadCleanUp Aufräumarbeiten durch und gibt dann den Speicher des CAThread- Objekts frei. Der Thread ist nun am Ende seiner Laufzeit angekommen und wird beendet.

CAThread::run

Diese Methode ist für die Abhandlung des Kommunikationsprotokolls zuständig. Sie benutzt die Klasse PIO aus dem TLS-Proxy zur Abstraktion der Socket-Kommunikation, welche den Non-Blocking-Modus (siehe Abschnitt 6.6) voraussetzt. Dadurch ist es auf einfache Weise möglich, jeweils eine Zeile (die einem Kommando entspricht) mit readLine vom Socket zu lesen. Wird so das SMTP-Kommando „QUIT“ empfangen, wird die Verarbeitung beendet und die Verbindung geschlossen. Wird ein unbekanntes Kommando empfangen, wird eine passende Fehlermeldung zurück- gesendet („-ERR GENCRT Unknown Command“). Bei dem Kommando „GENCRT“ wird zuerst die Syntax geprüft, dann werden die Parameter gelesen. Der letzte Parameter enthält die Länge des Zertifikats (in Bytes), das im nächsten Schritt übertragen wird. Wurde nun auch das Zertifikat vollständig empfangen, wird es in 6. Implementierung 58 eine X509-Struktur umgewandelt und der Methode createCertificate übergeben (siehe Abschnitt 6.5.1). Nachdem das neue Zertifikat erzeugt wurde, muss es zur Übertragung in das Binärformat Distinguished Encoding Rules (DER)[29] umgewandelt werden. Dann wird mit „+OK GENCRT “ der erfolgreiche Abschluss der Erzeugung signalisiert und die Länge der DER-Struktur in Bytes übergeben. Ein Client kann nun weitere Zertifikate anfordern oder die Kommunikation beenden. cleanUp

Ein Signal zur Beendigung der Zertifizierungsstelle kann jederzeit auftreten. Der Signal- Handler cleanUp sorgt in einem solchen Fall dafür, dass nicht gespeicherte Änderungen gesichert werden. Gleichzeitig muss er allen noch laufenden Threads mitteilen, dass sie sich beenden müssen. Dies geschieht mit der Variable „stopping“, welche die Threads vor kritischen Operationen überprüfen. Damit wird sichergestellt, dass einerseits keine Verbindungen mehr angenommen werden und andererseits keine Aufgaben mehr durchgeführt werden, die den Status der Zertifizierungsstelle ändern würden. Die Funktion cleanUp wartet danach, bis sich alle Threads beendet haben, und gibt den verwendeten Speicher frei, bevor sie die Zertifizierungsstelle beendet.

6.6 Blocking vs. Non-Blocking I/O

Ohne dem Setzen von speziellen Flags arbeiten Operationen auf (TCP-)Sockets im Blocking- Modus. Das heißt, z. B. beim Befehl read, dass der Aufruf erst zurückkehrt, wenn Daten gelesen werden konnten. Der Befehl write blockiert so lange, bis die Daten gesendet wer- den konnten. Und connect und accept blockieren so lange, bis die Verbindung mit dem Kommunikationspartner aufgebaut ist. Diese Arbeitsweise ist bei Programmen, die nur einen Socket bedienen müssen (z. B. normale Serverdienste), auch völlig ausreichend. Wenn nun aber ein Programm mehrere Sockets bedienen soll (wie es zum Beispiel bei Proxys der Fall ist), ist dies oft nicht zweckmäßig. Einerseits kann das Programm nicht wissen, auf welchem Socket als nächstes Daten anliegen werden. Andererseits könnten, während auf eine Antwort eines Kommunikationspartners gewartet wird, schon Daten von einem anderen Kommunikationspartner empfangen oder verarbeitet werden. Für solche Fälle bieten Sockets die Möglichkeit, in einen nicht blockierenden (non-blocking) Betrieb zu schalten (siehe Listing 6.5). In diesem Modus blockieren Socket-Operationen nicht, sondern kehren sofort zurück, egal ob sie erfolgreich sind oder nicht. Würde eine solche Operation blockieren, so wird der Fehlercode EWOULDBLOCK zurückgegeben und der Vorgang kann später nochmals versucht werden. Ein einfacher Ansatz für ein Programm ist es, zu versuchen, permanent alle seine Sockets 6. Implementierung 59 abzufragen (polling). Das funktioniert zwar, ist aber nicht effizient, da durch die ständigen Abfragen CPU-Zeit verschwendet wird. Zu diesem einfachen Ansatz gibt es bessere Alternativen. Eine davon, Multiplex-I/O, wird im folgenden Abschnitt vorgestellt, eine andere ist asynchroner I/O (vgl. z. B. [Ste95, Abschnitt 12.6]), welcher im TLS-Proxy aber nicht verwendet und deshalb hier nicht behandelt wird. Ebenfalls ist es denkbar, für jeden Socket einen eigenen Thread zu verwenden. Durch diesen Ansatz entsteht aber ein sehr hoher Synchronisationsaufwand und er wird deshalb im TLS-Proxy nicht verwendet. Im TLS-Proxy ist ein Thread für jeweils zwei Sockets zuständig.

6.6.1 Multiplexing-I/O mit select

Anstatt alle Sockets abzufragen, ist eine Methode wünschenswert, die ermittelt, welche Ope- rationen auf welchen Sockets nicht blockieren würden. Diese Funktionalität bieten select und poll, wobei hier nur auf select eingegangen wird12. Stevens beschreibt die benötigten Parameter und die Rückgabewerte für select wie folgt:

[...] Ihre Parameter teilen dem Systemkern mit,

1. an welchen Deskriptoren wir interessiert sind, 2. welche Bedingungen uns bei jedem Deskriptor interessieren (ob wir lesen oder schreiben oder von Fehlerbedingungen erfahren wollen), 3. wie lange wir warten wollen. (Wir können unbegrenzt lang, für eine bestimmte Zeit oder überhaupt nicht warten.)

Bei der Rückkehr von select liefert der Systemkern folgende Informationen:

1. Die Gesamtzahl der Deskriptoren, die bereit sind 2. Welche Deskriptoren für jede der drei Bedingungen bereit sind (Lesen, Schrei- ben oder Fehler)

[Ste95, Seite 443]

Durch die verschiedenen Wartezeiten kann select sehr flexibel eingesetzt werden. Eine Möglichkeit ist die Abfrage der Status von verschiedenen Sockets. Die Methode select kann aber auch eingesetzt werden, um zu warten, bis ein beliebiger Socket aus einer Gruppe für eine gewünschte Operation nicht blockiert.

6.6.2 OpenSSL und Non-Blocking-Sockets

Um Multiplexing-I/O mit der OpenSSL-Bibliothek gemeinsam zu verwenden, sieht die Doku- mentation von OpenSSL explizit den Einsatz von Non-Blocking-Sockets vor:

12Zu poll siehe [Ste95, Abschnitt 12.5.1] 6. Implementierung 60

One technique sometimes used with blocking sockets is to use a system call (such as select(), poll() or equivalent) to determine when data is available and then call read() to read the data. The equivalent with BIOs (that is call select() on the underlying I/O structure and then call BIO_read() to read the data) should not be used because a single call to BIO_read() can cause several reads (and writes in the case of SSL BIOs) on the underlying I/O structure and may block as a result. Instead select() (or equivalent) should be combined with non blocking I/O so successive reads will request a retry instead of blocking. [36]

6.6.3 Verwendung im TLS-Proxy

Wie die Kommunikationsstruktur in Abbildung 6.6 zeigt, muss der TLS-Proxy mehrere Sockets gleichzeitig (innerhalb eines Threads) bedienen können. Um dies zu ermöglichen, wird Multiplexing-I/O mit select verwendet. Wie in Abschnitt 6.6.2 ausgeführt, verlangt dies zusätzlich die Verwendung von Non-Blocking-Sockets. Bei HTTPS oder auch SMTPS findet der TLS-Handshake zu Beginn der TCP-Verbindung statt und der Socket kann danach in den Non-Blocking-Modus versetzt werden. Bei der Verwendung von STARTTLS findet jedoch schon vor dem TLS-Handshake Kommunikation auf dem Socket statt. Die OpenSSL Bibliotheken verlangen, dass der Socket für die Dauer des TLS-Handshake in den Blocking-Modus zurückversetzt wird. Die Verbindung mit der Zertifizierungsstelle verwendet nicht OpenSSL und könnte deshalb auch im Blocking-Modus erfolgen. Da jedoch auch hier die PIO-Kommunikationsstruktur verwendet wird, bietet sich ein Non-Blocking-Betrieb an.

1 bool setSocketNB(int socket, bool nb) 2 { 3 int flags = fcntl(socket, F_GETFL, 0); // get current flags of socket 4 if (nb) //set non blocking 5 { 6 flags |= O_NONBLOCK; // set nonblocking bit 7 } 8 else //set blocking 9 { 10 flags &= (~O_NONBLOCK); // clear nonblocking bit 11 } 12 return (! (fcntl(socket, F_SETFL, flags) < 0) ); // set new socket flags and return success or error 13 }

Listing 6.5: Versetzen eines Sockets in den Blocking- oder Non-Blocking-Modus 6. Implementierung 61

Firewall

TLS Proxy

handleServerSide clientConnection handleClientSide serverConnection

Client Server

midProxy Midproxy midProxy Connection Connection

Abbildung 6.6: Kommunikationsstruktur

6.7 Protokollhandler für SMTP

6.7.1 Struktur des SMTP-Handlers

handleClientSide handleServerSide

waitOnEvent waitOnEvent

handleClientCommand handleMidProxyResponse handleMidProxyCommand handleServerResponse

disconnect disconnect

Abbildung 6.7: Struktur des SMTP-Handlers

Um eine Verbindung zu bedienen, läuft die Methode handleClientSide in einem und die Methode handleServerSide in einem anderen Thread. Jede dieser Methoden behandelt zwei Sockets und leitet Nachrichten zwischen ihnen weiter (siehe Abbildung 6.6). Für viele SMTP- Kommandos und -Antworten ist diese Vorgehensweise ausreichend, doch manche müssen vom Proxy gesondert behandelt, verändert, verzögert oder unterdrückt werden. Dazu benutzt handleClientSide die Methoden handleClientCommand und handleMidProxyResponse, um Kommandos des Clients bzw. Antworten des MidProxy zu filtern. Die Methode handleSer- verSide benutzt handleMidProxyCommand und handleServerResponse, um Kommandos des MidProxy und Antworten des Severs zu filtern (siehe auf Abbildung 6.7). 6. Implementierung 62

Bevor die Methode handleServerSide jedoch mit der Verarbeitung beginnen kann, muss sie noch die Connection-ID durch den Proxy übertragen, damit der passende serverseitige Thread die Methode handleServerSide aufrufen kann (Genaueres in Abschnitt 6.4.4).

6.7.2 SMTP-Data und SMTP-Dialog

Das Filtern und Weiterleiten von Nachrichten ist nur möglich, solange sich alle Kommunikati- onspartner im SMTP-Dialog befinden. Der Client kann (und wird dies normalerweise auch tun) an einer Stelle im Dialog mit dem Kommando DATA den Wunsch äußern, den Inhalt der Mail-Nachricht zu übertragen. Erst wenn dieses Kommando vom Server bestätigt wurde, muss auch der Proxy in den SMTP-Data-Modus umschalten. In diesem Modus werden Daten zeilenweise gelesen und an den Server (durch den Middle- Proxy) weitergeleitet. Die Filter, die im SMTP-Dialog-Modus zur Anwendung kommen, werden hier nicht verwendet, damit im Mail-Text vorkommende Wörter nicht als Kommandos fehlinterpretiert werden. Die zeilenweise Bearbeitung ist deshalb nötig, weil sonst der End- Of-Mail-Indikator (.) nicht erkannt werden kann. Wird er jedoch erkannt, muss der jeweilige Handler wieder in den SMTP-Dialog-Modus zurückschalten.

6.7.3 Multiplex-I/O

Wie in Abbildung 6.7 ersichtlich, ist die Methode waitOnEvent aus Listing 6.6 ein zentraler Punkt in den Handler-Methoden. Damit ist es möglich, auf eine Aktivität eines oder mehrerer PIO-Objekte zu warten. Die Methode wird in einer Schleife so lange immer wieder aufgerufen, bis die TCP-Verbindung beendet wird. Die Methode blockiert beim Aufruf so lange, bis auf einem der beiden Sockets entweder Daten anliegen oder einer der Sockets die TCP-Verbindung abgebrochen hat. Zusätzlich ist es möglich, einen Wert als Timeout festzulegen, nachdem die Methode auch ohne Ereignis zurückkehren soll. 1 int PIO::waitOnEvent(PIO *pio2, bool read, int timeoutSec) 2 { 3 ... 4 if (timeoutSec > 0) // timeout is set, create timeout struct 5 { 6 timeout = new timeval; 7 timeout->tv_sec = timeoutSec; 8 timeout->tv_usec = 0; 9 } 10 ... 11 /* 12 first parameter specifies socket count in sockets struct +1 13 wait until on of the sockets has data to read 14 */ 15 result = select(max(socket1, socket2) + 1, &sockets, NULL, NULL, timeout); 16 if (result > 0) 6. Implementierung 63

17 { 18 if (FD_ISSET(socket1,&sockets)) // first socket has data to read 19 { 20 result = 1; 21 } 22 else if (FD_ISSET(socket2,&sockets)) // second socket has data to read 23 { 24 result = 2; 25 } 26 else // error no socket has data to read but select still returned 27 { 28 result = -1 29 } 30 } 31 ... 32 else //result is 0 -> timeout 33 { 34 result = PIO_TIMEOUT 35 } 36 ... 37 return result; 38 } Listing 6.6: Multiplex-I/O mit waitOnEvent

6.7.4 Limits

Der zeilenorientierte Aufbau von SMTP legt nahe, die Zeichenfolge CRLF als Endkriterium beim Lesen von Kommandos oder Antworten zu verwenden. In diesem einfachen Ansatz liest man von einem Socket solange, bis diese Zeichenfolge auftritt. Dies birgt aber die Gefahr eines Buffer-Overflows, wenn der Platz im dafür reservierten Speicher nicht ausreicht und andere Speicherbereiche überschrieben werden. Es ist deshalb nötig, die Anzahl der zu lesenden Bytes zu limitieren. Die maximale Länge eine SMTP-Kommandos (512) und die einer SMTP- Antwort (512) wurden dazu aus [Kle08] entnommen. Dieser Wert muss, laut RFC, mindestens als Länge für Kommandos und Antworten akzeptiert werden. Wurde beim Empfang eines SMTP-Kommandos die maximale Länge erreicht, ohne dass ein CRLF gelesen wurde, so wird das (unvollständige) Kommando nicht weitergeleitet und eine Fehlermeldung an den Client gesendet (500 line too long). Zu lange Antworten eines Servers werden auch unvollständig weitergeleitet, da der Client eine Antwort erwartet.

6.7.5 Behandlung von Verbindungsabbrüchen

Eine primäre Anforderung an jede Software, die mit Mail-Nachrichten umgeht, ist, dass auf keinen Fall Nachrichten unbemerkt verloren gehen dürfen. Für Client und Server ist eine 6. Implementierung 64

Verbindung über den TLS-Proxy transparent. Bricht nun eine Seite die Verbindung ab, so muss der Proxy dafür sorgen, dass auch die andere Seite den Verbindungsabbruch erkennt. Bricht der Server die Verbindung ohne eine Fehlermeldung ab, kann noch versucht werden, den Client zu informieren, indem eine passende SMTP-Antwort gesendet wird (Code 421). Neben der Verwendung des passenden Codes kann eine Nachricht mitgegeben werden, um den Benutzer genauer zu informieren, z. B. „421 Server has terminated the connection, cannot continue“. Bricht der Client die Verbindung ab, kann versucht werden, die Verbindung zum Server sauber zu beenden, indem ein Kommando QUIT gesendet wird.

6.7.6 Behandlung von STARTTLS

Um die STARTTLS-Erweiterung für SMTP zu unterstützen und gleichzeitig Zugriff auf die unverschlüsselte Kommunikation zu haben, baut der Proxy zwei TLS-Sessions auf. Im normalen Betriebsmodus wartet der Proxy darauf, das STARTTLS-Kommando vom Client zu empfangen, und versucht, nicht von sich aus eine TLS-Session zu starten. Wurde das Kommando auf der Clientseite des Proxy empfangen, so muss es als nächstes durch den Middle-Proxy übertragen werden. Besteht jedoch bereits eine TLS-Session mit dem Client, so muss der Proxy das STARTTLS-Kommando mit der Meldung „454 TLS is already active“ ablehnen. Viele SMTP- Proxys (auch der verwendete ProxSMTP) filtern das STARTTLS-Kommando und leiten es nicht an den Server weiter13. Um diese Beschränkung zu umgehen, wird das NOOP-Kommando verwendet (NOOP STARTTLS). Dies wird vom Middle-Proxy unmodifiziert weitergeleitet und kann auf der Serverseite des TLS-Proxy wieder in das STARTTLS Kommando zurückübersetzt und an den Server gesendet werden. Auch die Ankündigung der STARTTLS-Funktionalität bei den Antworten auf das EHLO-Kommando wird vom Middle-Proxy gefiltert und müssen deshalb vom Proxy wieder eingefügt werden. Sendet ein Client das Kommando NOOP STARTTLS, darf es natürlich nicht durch den Middle-Proxy weitergeleitet werden. Wie schon in Abschnitt 6.4.4, wird es stattdessen in ein einfaches Kommando NOOP umgewandelt. Der TLS-Proxy benötigt das Zertifikat des Servers, bevor er den TLS-Handshake mit dem Client durchführen kann, entweder um es mit einem hinterlegten Zertifikat zu vergleichen oder um daraus ein Zertifikat on-the-fly zu erstellen. Negative Antworten des Servers (z. B. 454 TLS not available oder 502 Command not implemented) können jedoch sofort an den Client weitergeleitet werden. Schlägt der TLS-Handshake mit dem Server fehl, so wird der Client mit einer Antwort mit dem Code 454 und einer passenden Fehlermeldung als Parameter informiert. Wird beim TCP-Handshake mit dem Server erkannt, dass dieser auf der Whitelist steht, so darf die Verbindung nicht weiter untersucht werden. Der Client erwartet an dieser Stelle aber nicht, dass er erneut versuchen muss, das STARTTLS-Kommando zu senden. Aus diesem Grund

13ProxSMTP sendet beim Empfang des STARTTLS-Kommandos folgende Antwort: 502 Command not imple- mented. 6. Implementierung 65 startet der TLS-Proxy die TCP-Verbindung zum Server neu und sendet das zuvor vom Client empfangene EHLO-Kommando und danach das STARTTLS-Kommando. Das ist unproblematisch, da es sich von Anfang an um verschiedene TCP-Verbindungen handelt. Danach wird jeglicher weiterer Datenaustausch zwischen Client und Server unbesehen durchgereicht. Auf diese Weise kann der TLS-Handshake direkt zwischen Client und Server stattfinden. Dieses Durchreichen der Daten muss ebenfalls geschehen, wenn der Server beim TLS-Handshake ein Client-Zertifikat anfordert und der Proxy konfiguriert ist, dieses nicht zu blocken. Wurde er konfiguriert, um Client-Zertifikate zu blocken, so muss der Proxy an dieser Stelle die TCP-Verbindung abbrechen, da er den TLS-Handshake nicht abschließen kann. Dem Client kann er dies noch mit einer Antwort mit dem Code 421 mitteilen. War der TLS-Handshake mit dem Server erfolgreich, so kann eine Antwort an den Client gesendet werden (220 Ready to start TLS), damit er mit dem TLS-Handshake beginnt. Nach dem TLS-Handshake muss der Client erneut ein HELO- oder EHLO-Kommando senden, die Antworten des Servers darauf dürfen keine Ankündigung für die STARTTLS-Funktionalität mehr enthalten. Auch der Client darf kein STARTTLS mehr anfordern, versucht er es doch, so wird es mit „454 TLS is already active“ abgelehnt.

6.7.6.1 Lizenzabhängige STARTTLS-Funktionalität

Die STARTTLS-Funktionalität soll im TLS-Proxy nur abhängig von der aktiven Lizenz zur Verfügung stehen. Dies ist in der Underground_8-Firewall auch schon bei HTTPS vorgesehen und muss auch bei SMTPS so funktionieren. Der Proxy soll jedoch auch ohne TLS-Lizenz für normalen SMTP Datenverkehr funktionieren. In diesem Fall darf der Proxy die Funktionalität in den Antworten auf das EHLO-Kommando nicht ankündigen. Versucht ein Client trotzdem eine TLS-Session zu starten, wird er mit der Antwort „454 TLS not available. missing License or not enabled“ abgewiesen. Das Erzwingen von STARTTLS, wie es in Abschnitt 6.7.6.2 vorgestellt wird, ist ohne TLS-Lizenz natürlich auch nicht möglich.

6.7.6.2 Erzwingen von STARTTLS

In besonders sicherheitsrelevanten Bereichen kann es eine Anforderung sein, nur verschlüsselten Mail-Transfer zuzulassen. Der TLS-Proxy bietet diese Möglichkeit und erlaubt auch eine detaillierte Konfiguration, um festzulegen, in welchen Fällen STARTTLS erzwungen werden soll. Siehe Kapitel 7 für die Beschreibung der Konfigurationsparameter und Abschnitt 9.2 für mögliche Einsatzszenarien.

6.7.6.2.1 Erzwingen von serverseitigem STARTTLS

Wurde in der Konfiguration das Erzwingen von serverseitigem STARTTLS aktiviert, so kann der Proxy nicht abwarten, bis der Client eine TLS-Session initiiert, da sonst Teile der 6. Implementierung 66

Kommunikation unverschlüsselt zum Server übertragen werden. Aus diesem Grund muss der Proxy von sich aus versuchen eine TLS-Session herzustellen. Dies ist aber erst möglich, nachdem der Server auf das EHLO-Kommando geantwortet und die Unterstützung für STARTTLS angekündigt hat. Hat der Client jedoch nur ein HELO-Kommando gesendet, würde der Server seine unter- stützten Erweiterungen nicht ankündigen. Deshalb wird stattdessen ein EHLO-Kommando mit den gleichen Parametern an den Server gesendet. Dass der Client nach einem HELO-Kommando keine mehrzeilige Antwort erwartet, ist hier kein Problem, da die Antworten an dieser Stelle noch nicht an den Client weitergegeben werden. Kündigt der Server keine Unterstützung für STARTTLS an, so muss der Proxy die SMTP- Verbindung abbrechen14, da er kein TLS erzwingen kann. Schlägt der TLS-Handshake mit dem Server fehl oder akzeptiert der Server das STARTTLS- Kommando nicht, muss der Proxy die SMTP-Verbindung ebenfalls abbrechen. Der Client erhält die Fehlermeldung, die beim TLS-Handshake auftrat, als Parameter der 421-Antwort. Wurde die TLS-Session erfolgreich aufgebaut, sieht RFC3207[Hof02] vor, dass der Client erneut ein HELO- oder EHLO-Kommando sendet. Da der Client nichts von dem Aufbau der TLS-Session weiß, muss dies auch der Proxy erledigen. Er sendet dazu das originale Kommando des Clients und leitet auch die Antwort des Servers wieder an der Client weiter. Der Client erhält erst jetzt eine Antwort auf sein HELO- oder EHLO-Kommando, wobei Antworten auf das EHLO-Kommando vom Proxy um STARTTLS erweitert werden, und hat die Möglichkeit, selbst eine TLS-Session zu starten. Es ist auch möglich, STARTTLS nur für interne oder nur für externe Server zu erzwingen. Um externe und interne Server zu unterscheiden, müssen alle internen Subnetze oder IP- Adressen in einer Datei abgelegt werden, auf die die Konfigurationsoption SMTP_IP_- LOCAL_LIST verweist. Alle Adressen, die in dieser Liste nicht enthalten sind, werden als extern behandelt. In der Standardeinstellung ist diese Liste leer und es werden alle Server gleich (als extern) behandelt. Soll STARTTLS für interne Server erzwungen werden, so verlangt der Proxy, dass dafür die passenden Zertifikate hinterlegt wurden (siehe Abschnitt 6.8).

6.7.6.2.2 Erzwingen von clientseitigem STARTTLS

Um STARTTLS auf der Clientseite zu erzwingen, muss der Proxy nicht von sich aus aktiv werden. Es ist ausreichend, alle Kommandos außer EHLO, QUIT, NOOP und natürlich STARTTLS abzulehnen15, solange keine TLS-Session besteht. Auch das Kommando HELO wird abgelehnt, da der Client damit anzeigt, dass er keine SMTP-Erweiterungen (und damit auch kein STARTTLS) unterstützt.

14Dazu wird folgende Antwort an den Client gesendet: „421 Server does not support STARTTLS but it is forced by config. Shutting down Connection.“ 15RFC3207 schlägt dazu folgende Antwort vor: „530 Must issue a STARTTLS command first“. 6. Implementierung 67

6.7.7 Relay

Eine weitere Betriebsart, die der TLS-Proxy unterstützen muss, ist der Relay-Modus. Hier übergibt der Proxy die Nachrichten nicht an den Zielserver, sondern an ein lokales SMTP-Relay. Um dem Client aber trotzdem STARTTLS-Funktionalität bieten zu können, muss der Proxy mit dem Zielserver zumindest so lange eine Verbindung aufnehmen, bis er dessen Zertifikat erhalten hat. Im Relay-Modus wird deshalb sofort nach dem Erhalt der Willkommensnachricht des Servers (Code 220) ein EHLO-Kommando gesendet, ohne auf den Client zu warten. Auf diese Weise wird festgestellt, ob der Server überhaupt die STARTTLS-Funktionalität unterstützt. Ist dies der Fall, versucht der Proxy mit Hilfe des STARTTLS-Kommandos einen TLS-Handshake mit dem Server zu starten. Danach ist das Serverzertifikat verfügbar und die Verbindung mit dem Server kann getrennt werden. Dazu wird, wie in RFC5321[Kle08] vorgesehen, das Kommando QUIT benutzt. Im nächsten Schritt wird auch die TCP-Verbindung zum Middle-Proxy getrennt, da das Relay die Untersuchung der Nachrichten übernimmt. Um möglichst große Teile des vorhandenen Codes weiterverwenden zu können, wird der Socket des Middle-Proxy danach für die TCP- Verbindung zum Relay benutzt. Auch der serverseitige Thread wird nicht mehr benötigt, und kann wieder an den Thread-Pool zurückgegeben werden. Erst nachdem die TCP-Verbindung mit dem Relay aufgebaut wurde, wird die Willkom- mensnachricht16 an den Client weitergeleitet und er kann mit der Kommunikation beginnen. Auch STARTTLS ist für den Client möglich, da das Zertifikat des Zielservers vorhanden ist. Um den Client nicht zu lange auf den SMTP-Verbindungsaufbau warten zu lassen, soll der TLS-Handshake mit dem Server und die TCP-Verbindung mit dem Relay parallel erfolgen. Dadurch kann der Client bereits mit dem Relay kommunizieren, während der Proxy versucht das Serverzertifikat zu erhalten. Die Antwort auf das STARTTLS-Kommando muss jedoch verzögert werden, bis feststeht, dass der Server dies unterstützt (siehe Listing 6.7).

1 pthread_mutex_lock(&server_tls_mutex); 2 while(!serverTLSdone) 3 { 4 pthread_cond_wait(&server_tls_cond,&server_tls_mutex); // wait until condition notify 5 //mutex is locked after this 6 } 7 pthread_mutex_unlock(&server_tls_mutex); 8 debug("serverside got Certificate, may now starttls ");

Listing 6.7: Warten auf Beendigung des serverseitigen TLS-Handshake mit Pthread- Conditions

16In diesem Fall jene des SMTP-Relay. 6. Implementierung 68

6.7.8 Weiterleitung ohne Untersuchung

Für den SMTPS-Proxy gibt es zwei Situationen, in denen er eine Mail-Kommunikation nicht mehr untersuchen kann oder soll und den Datenaustausch zwischen Client und Server ohne Untersuchung weiterleiten muss. Das ist der Fall, wenn der Server beim TLS-Handshake ein Client-Zertifikat verlangt und der Proxy nicht konfiguriert wurde, Client-Zertifikate zu blocken. Auch wenn der Proxy beim TLS-Handshake feststellt, dass sich der Server auf der Whitelist befindet, darf die Verbindung nicht untersucht werden. In beiden Fällen trennt die TLS-Proxy-Engine die TCP-Verbindung zum Server und startet sie erneut, damit sie dann ohne Untersuchung durchgereicht wird. Dieses Verhalten ist für HTTP ausreichend, für SMTP müssen aber noch weitere Schritte durchgeführt werden. Zum Zeitpunkt des TLS-Handshake hat der Client schon Kommandos mit dem Server ausgetauscht und wartet auf die Antwort auf das STARTTLS-Kommando, wogegen der Server von der alten Verbindung keine Informationen behalten hat. Der Proxy muss deshalb dafür sorgen, dass Client und Server wieder auf den gleichen Stand gebracht werden. Zuerst muss er dazu das EHLO-Kommando des Clients erneut an den Server senden und dessen Antwort nicht weiterleiten. Erst dann kann er das STARTTLS-Kommando an den Server absetzen. Nun darf der Proxy aber in den TLS-Handshake nicht mehr eingreifen und leitet deshalb die Antwort des Servers auf das STARTTLS-Kommando direkt an den Client weiter. Ab diesem Zeitpunkt muss jeglicher Datenverkehr zwischen Client und Server durch den Proxy getunnelt werden (siehe Listing 6.8).

1 debug("Pass Through in normal Mode"); 2 debug("closing Server Connection to midProxy"); 3 midProxyServerSide->disconnect(); 4 debug("resending STARTTLS"); 5 proxy->getServerPIO()->writeString("STARTTLS\r\n"); //send STARTTLS to server 6 if (config->getInt("CONNECTION_LOG")) 7 { 8 log(LOG_WARNING,"PASS THROUGH: connection from %s to %s",proxy->getClientIP().c_str(), proxy->getServerIP().c_str()); 9 } 10 if (proxy->tunnelTCP()!= NO_ERR) // tunnel any traffic between without inspection 11 { 12 log(LOG_WARNING,"PASS THROUGH ERROR: connection from %s to %s",proxy->getClientIP(). c_str(),proxy->getServerIP().c_str()); 13 } 14 debug("Tunnel done");

Listing 6.8: Tunneln von TCP-Verbindungen durch den Proxy

Da nach erfolgreichem TLS-Handshake die TCP-Verbindung verschlüsselt ist, ist auch keine Untersuchung durch den Middle-Proxy mehr nötig oder möglich. Die TCP-Verbindungen zum Middle-Proxy können deshalb an dieser Stelle getrennt werden. Es ist ausreichend, eine 6. Implementierung 69 der TCP-Verbindungen zu trennen, da der Middle-Proxy danach auch die andere Seite trennt.

6.7.9 Behandlung sonstiger Kommandos

Die normale Vorgehensweise des TLS-Proxy ist es, jedes Kommando und jede Antwort einfach weiterzuleiten. In den oben genannten Fällen (z. B. bei STARTTLS) sind vom Proxy Aktionen nötig, um seine Funktionalität umzusetzen. Dieser Abschnitt beschreibt Kommandos und deren Antworten, die bisher noch nicht behandelt wurden.

6.7.9.1 TCP-Verbindungsaufbau

Der TCP-Verbindungsaufbau an sich ist kein Kommando, jedoch antwortet der Server darauf mit seiner Willkommensnachricht. Diese Nachricht wird leider vom verwendeten Middle-Proxy (ProxSMTP) durch „220 smtp.passthru“ ersetzt. Manche SMTP-Clients versuchen nur dann ESMTP-Funktionalität zu benutzen, wenn in der Begrüßung des Servers das Schlüsselwort ESMTP enthalten ist. Deshalb ist für den Client die Information in der Willkommensnachricht des Servers unter Umständen wichtig. Der TLS-Proxy speichert daher die originale Nachricht und gibt sie, anstatt der vom Middle-Proxy modifizierten, an den Client weiter.

6.7.9.2 EHLO/HELO

Die Kommandos EHLO und HELO können unmodifiziert weitergeleitet werden. Es gibt aber Situationen, in denen das Kommando im Verlauf der Kommunikation nochmals benötigt wird. Der Proxy speichert deshalb das Kommando und dessen Parameter. Ähnlich wie bei der Willkommensnachricht verändert der Middle-Proxy auch die erste Antwort auf das EHLO- oder HELO-Kommando. In diesem Fall wird es durch „250 smtp.passthru“ bei einer einzeiligen Antwort oder durch „250-smtp.passthru“ bei einer mehrzeiligen Antwort ersetzt. Auch hier stellt der TLS-Proxy den originalen Inhalt der Antwort wieder her.

6.7.9.3 Nicht unterstützte SMTP-Erweiterungen

Der TLS-Proxy wurde entwickelt, um die minimal vorgesehenen Kommandos des SMTP- Standards zu unterstützen und zusätzlich die STARTTLS-Erweiterung zu ermöglichen. Norma- lerweise sind SMTP-Erweiterungen unproblematisch, da sie der Proxy einfach an den Server durchreichen kann (z. B. AUTH[SM07] oder 8BITMIME[KFRC11]). Es kann jedoch vorkom- men, dass SMTP-Server Erweiterungen anbieten, mit denen der SMTP-Proxy nicht umgehen kann. Diese Erweiterungen müssen vom TLS-Proxy aus den Antworten des Servers auf das EHLO-Kommando herausgefiltert werden, sofern dies nicht schon durch den Middle-Proxy passiert. 6. Implementierung 70

Exemplarisch wird dazu die Erweiterung PIPELINING[Fre00] vorgestellt. Diese Erweite- rung erlaubt es einem Client, eine Reihe von Kommandos zu senden, ohne nach jedem auf eine Antwort des Servers zu warten. Der Server muss aber trotzdem jedes der Kommandos beantworten. Der Client muss die Antworten in der Reihenfolge des Empfangs den gesendeten Kommandos zuordnen. Der TLS-Proxy unterstützt diese Erweiterung nicht, da er sich für die Verarbeitung auf die Abfolge von Kommando und Antwort verlässt. Ein Zuordnen von Kommandos und Antworten im PIPELINING-Modus würde den Code aufblähen und unnötig komplex machen. Da auch der verwendete Middle-Proxy ProxSMTP die PIPELINING-Erweiterung nicht unterstützt, wurde auf eine Implementierung verzichtet.

6.8 Hinterlegung von Zertifikaten

Da bei HTTP Verbindungen zu vielen verschiedenen Servern aufgebaut werden, ist das Erzeugen von on-the-fly-Zertifikaten sinnvoll und ausreichend. Dies gilt besonders, da nicht bekannt ist, zu welchen Servern zukünftige Verbindungen aufgebaut werden, und diese Server meist nicht unter Kontrolle des eigenen Unternehmens stehen. Etwas anders liegt der Fall bei SMTP, da hier typischerweise Verbindungen zu bekannten und vor allem vom Unternehmen kontrollierten Servern aufgebaut werden. Deshalb ist es eine Anforderung an den SMTPS-Proxy, Zertifikate (und Schlüssel) von bekannten Servern am Proxy zu hinterlegen. Dies hat den Vorteil, dass kein on-the-fly-Zertifikat erstellt werden muss und das hinterlegte Zertifikat mit jenem verglichen werden kann, das der Zielserver im TLS- Handshake präsentiert. Stimmen diese beiden Zertifikate nicht überein, kann die Verbindung abgebrochen und ein möglicher Man-in-the-middle-Angriff verhindert werden. Die Private-Keys sind nur notwendig, wenn auch beim TLS-Handshake mit dem Client das hinterlegte Zertifikat verwendet werden soll. Für den reinen Vergleich könnte auf die Private-Keys verzichtet werden. Die Hinterlegung von Private-Keys birgt jedoch auch ein gewisses Sicherheitsrisiko. Eine dementsprechende Absicherung ist jedoch auch im reinen On-the-fly-Betrieb notwendig, weil sich der Private-Key der Zertifizierungsstelle auf der Appliance befindet.

6.8.1 Verwaltung der hinterlegten Zertifikate

Zur Verwaltung der hinterlegten Zertifikate wurde die Klasse CertList entwickelt. Sie wird benutzt, um aus einem definierten Verzeichnis Dateien zu lesen, welche die Zertifikate und deren Schlüssel enthalten. Ist der Private-Key eines solchen Zertifikates verschlüsselt, so kann auch die passende Passphrase in der Datei hinterlegt werden. Abschnitt 6.8.2 zeigt den Aufbau einer solchen Datei. Jedes geladene Zertifikat (und die zugehörigen Schlüssel) wird in einem Objekt der Klasse CertEntry gespeichert. Wie in Abbildung 6.8b ersichtlich, enthalten die Objekte der Klasse 6. Implementierung 71

CertList CertEntry

- certs + cert + privateKey + CertList() + passPhrase + getCertFromDeposit() + loadCertsFromDir() + getPassPhrase() + ~CertList() + CertEntry() - loadEntryFromFile() + ~CertEntry()

(a) Klassendiagramm CertList (b) Klassendiagramm CertEn- try Abbildung 6.8: Klassen zur Verwaltung von hinterlegten Zertifikaten

CertEntry neben Zertifikat und Private-Key auch die zugehörige Passphrase. Um die CertEntry- Objekte bei Bedarf wieder leicht aufzufinden, werden sie in einer Map innerhalb der Klasse CertList vorgehalten. Als Zugriffsschlüssel für die Map wird das Hash des Subjects des Zertifikats benutzt. Das Subject muss zwar nicht eindeutig sein, jedoch ist es für den TLS- Proxy ausreichend für jedes Subject nur ein Zertifikat zu verwalten.

1 map *certs; Listing 6.9: Definition der CertEntry-Map

6.8.2 Aufbau einer Zertifikatsdatei

Jede Zertifikatsdatei ist eine Textdatei, die aus drei Blöcken besteht. Block 1 ist optional und enthält, falls nötig, die Passphrase des privaten Schlüssels. Syntax: PASS:

Block 2 enthält das Zertifikat selbst in base64-Kodierung. Um das Zertifikat von den anderen Blöcken abzugrenzen und ein Laden durch die OpenSSL-Bibliotheken zu ermöglichen, wird es von zwei Trennelementen umschlossen. Startelement: —–BEGIN CERTIFICATE—– Endelement: —–END CERTIFICATE—–

Block 3 enthält (ebenfalls base64-kodiert) den zum Zertifikat passenden privaten Schlüssel. Auch dieser Schlüssel muss von den anderen Blöcken abgegrenzt werden, OpenSSL verlangt jedoch die Angabe des verwendeten Algorithmus in den Trennelementen. Mögliche Startelemente: —–BEGIN RSA PRIVATE KEY—– oder 6. Implementierung 72

—–BEGIN DSA PRIVATE KEY—– oder —–BEGIN PRIVATE KEY—– Mögliche Endelemente: —–END RSA PRIVATE KEY—– oder —–END DSA PRIVATE KEY—– oder —–END PRIVATE KEY—–

1 PASS:foo 2 -----BEGIN CERTIFICATE----- 3 MIIFcjCCA1qgAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCQVQx 4 ... 5 qLMN6fln 6 -----END CERTIFICATE----- 7 -----BEGIN RSA PRIVATE KEY----- 8 gOk3XToUvFh2ELBXYzFWO1dkKCeCJD8StLmLuDSpxapnH/b1XU0cwF5Z3NH3UCum 9 ... 10 WsV+LRwDXIsqJT1Hp22CeMxpGK+/9nUD5PbIfH14sxFQ8IbMwyQwKA== 11 -----END RSA PRIVATE KEY-----

Listing 6.10: Beispiel für eine Zertifikatsdatei

6.8.3 Verwendung

Beim Start des TLS-Proxy wird, sofern vorhanden, der mit CERT_DEPOSIT_PATH definierte Pfad zum Verzeichnis des Zertifikatsspeichers an die Funktion CertList::loadCertsFromDir übergeben und es werden so die Zertifikate geladen. Wird nun eine TLS-Session mit einem Server aufgebaut, so wird der Hash des Serverzertifikats im Zertfikatsspeicher gesucht (Funktion CertList::getCertFromDeposit). Wenn der Hash nicht gefunden wird, ist für den Server kein Zertfikat hinterlegt und es muss auf die on-the-fly-Erzeugung zurückgegriffen werden. Ist ein passendes Zertifikat jedoch vorhanden, können die beiden Zertifikate verglichen werden. Sind sie nicht identisch, so wird die TCP-Verbindung oder der TLS-Handshake abgebrochen, um einen Man-in-the-middle-Angriff zu verhindern. Theoretisch gibt es auch die Möglichkeit einer Hash-Kollision. Das heißt, dass zwei unterschiedliche Zertifikate existieren, die denselben Hash haben. Selbst das ist aber hier kein Sicherheitsproblem, da bei einer Übereinstimmung der Hashes die ganzen Zertifikate verglichen werden. Dadurch wird weiters sichergestellt, dass, auch falls ein Angreifer Kontrolle über eine vertrauenswürdige Zertifizierungsstelle erlangen und ein gültiges Zertifikat ausstellen würde, die SMTP-Verbindung nicht hergestellt wird. Soll nun das hinterlegte Zertifikat verwendet werden, muss ein neuer SSL-Context für die Client-Seite erzeugt werden. Normalerweise wird für alle Verbindungen derselbe SSL-Context verwendet, da auch für alle on-the-fly-Zertifikate dasselbe Schüsselpaar verwendet wird. Der neue Kontext muss deshalb das Schüsselpaar des hinterlegten Zertifikats enthalten. Listing 6.11 zeigt, wie der Vergleich der Zertifikate und das Erzeugen des SSL-Client-Context durchgeführt 6. Implementierung 73 wird.

1 //compare server certificate with certificate from deposit 2 int compareResult=X509_cmp(depCert->cert,proxy->getCertificate(true)); 3 if(compareResult!=0) 4 { 5 log(LOG_WARNING,"Certificates differ, return code: %d",compareResult); 6 ret=CERT_VERIFY_ERR; 7 } 8 else 9 { 10 debug("Certificates match!"); 11 SSL_CTX *oldClientContext=proxy->getSSLContext(true); 12 SSL_CTX *newClientContext=SSL_CTX_new(SSLv23_server_method()); //create new SSL Context 13 debug("Context has been created"); 14 SSL_CTX_set_options(newClientContext,SSL_CTX_get_options(oldClientContext)); 15 debug("Options from original context are set!"); 16 SSL_CTX_set_mode(newClientContext,SSL_CTX_get_mode(oldClientContext)); 17 debug("Mode from original context has been set"); 18 if(SSL_CTX_set_cipher_list(newClientContext,config->getC("CIPHER_LIST"))!=1) 19 log(LOG_ERR,"Could not set even one cipher"); 20 else 21 debug("Cipher list from config has been set"); 22 if (config->getInt("PERMIT_DEFAULT_CA_VERIFY_PATH")) 23 { 24 if(SSL_CTX_set_default_verify_paths(newClientContext)!=1) 25 log(LOG_WARNING,"Could not set default verify paths"); 26 else 27 debug("Default verify paths have been enabled"); 28 } 29 if (config->getInt("PERMIT_CA_VERIFY_LOCATIONS")) 30 { 31 if(SSL_CTX_load_verify_locations(newClientContext,config->getC("CA_VERIFY_FILE"),config ->getC("CA_VERIFY_PATH"))!=1) 32 log(LOG_WARNING,"Could not load verify locations from config"); 33 else 34 debug("Verify locations have been loaded from config"); 35 } 36 SSL_CTX_set_session_cache_mode(newClientContext,SSL_SESS_CACHE_OFF | SSL_SESS_CACHE_NO_INTERNAL); 37 debug("Session cache mode has been set to off"); 38 if(SSL_CTX_use_PrivateKey(newClientContext,depCert->privateKey)!=1) 39 { 40 log(LOG_WARNING,"Could not set private key for context"); 41 ret=CERT_CREATE_ERR; 42 } 43 else 44 debug("Private key from deposit has been set"); 6. Implementierung 74

45 if(SSL_CTX_use_certificate(newClientContext,depCert->cert)!=1) 46 { 47 log(LOG_WARNING,"Could not set Certificate for context"); 48 ret=CERT_CREATE_ERR; 49 } 50 else 51 debug("Certificate from deposit has been set"); 52 proxy->setSSLContext(newClientContext,true); 53 debug("Original Context has been replaced by the created one"); 54 } Listing 6.11: Vergleichen der Zertifikate und Erzeugen eines neuen SSL-Client-Context Kapitel 7

Konfigurationsoptionen

Die in den folgenden Abschnitten angegebenen Standardwerte für die Konfigurationsoptionen sind nur gültig, wenn sie in den Konfigurationsdateien nicht überschrieben werden. Die Konfigurationsdateien befinden sich standardmäßig in /etc/tlsproxy/. Dieser Pfad kann jedoch mit einer Kommandozeilenoption geändert werden (siehe Abschnitt 9.1.2.2). Der Dateiname für den TLS-Proxy lautet proxy.config und jener für die Zertifizierungsstelle ca.config. In jeder Zeile der Konfigurationsdateien können je eine Option und ein Wert durch Leerzeichen (oder Tabulatoren) getrennt angegeben werden. Befindet sich ein einer Zeile ein #-Symbol so wird alles ab dem Symbol bis zum Ende der Zeile ignoriert. Dadurch können die Dateien mit Kommentaren versehen werden.

7.1 Allgemeine Optionen

Dieser Abschnitt enthält die allgemeinen Optionen, welche für die protokollspezifischen Proxys gültig sind.

DAEMON

Legt fest, ob der Proxy bzw. die Zertifizierungsstelle als Dienst im Hintergrund (Daemon) gestartet werden soll oder nicht. Standardwert: yes

PID_FILE

Beim Start legt der Proxy seine Prozess-ID in dieser Datei ab. Standardwert: /var/run/tlsproxy/tlsproxy.pid

75 7. Konfigurationsoptionen 76

EGD_SOCKET

Der TLS-Proxy benötigt für kryptographische Operationen Zufallswerte, die aus /dev/random gelesen werden können. Als Alternative dafür kann ein Entropy Gathering Daemon (EGD)1 verwendet werden. Die Kommunikation findet über den hier spezifizierten Unix-Domain-Socket statt. Standardwert: NULL

TIMEOUT

Ist jene Zeit (in Sekunden), nach der eine Socket-Operation (z. B. read, write etc.) mit einem Fehler abbricht. Standardwert: 60, sollte nicht verändert werden

LOGLEVEL

Legt fest, bis zu welchem Level (Fehler-)Meldungen im Log-File (beim Betrieb als Daemon) oder auf Standard Filehandle für die Fehlerausgabe (stderr) ausgegeben werden (siehe auch Tabelle 7.1). Standardwert: 3

Numerical Severity Code 0 Emergency: system is unusable 1 Alert: action must be taken immediately 2 Critical: critical conditions 3 Error: error conditions 4 Warning: warning conditions 5 Notice: normal but significant condition 6 Informational: informational messages 7 Debug: debug-level messages

Tabelle 7.1: Syslog Message Severities. Aus [Ger09].

LOGNAME

Alle Meldungen werden unter diesem Namen geloggt. Standardwert: TLSProxy

1z. B. von http://egd.sourceforge.net/ 7. Konfigurationsoptionen 77

NUM_THREADS

Legt die Anzahl an Threads fest, die beim Programmstart gestartet werden und für eingehende TCP-Verbindungen zur Verfügung stehen. Standardwert: 20

MAX_NUM_THREADS

Sind alle Threads in Verwendung, werden nach Bedarf weitere gestartet, jedoch nur bis zum in MAX_NUM_THREADS festgelegten Wert. Standardwert: 40

PORT

Um den Datentransfer transparent untersuchen zu können, muss er auf diesen Port weitergeleitet werden. Dies wird normalerweise durch einen Paketfilter (z. B. iptables2) durchgeführt. Weiters wartet der Proxy auf PORT+1 auf ausgehende TCP-Verbindungen vom Middle-Proxy. Standardwert: 4000

MID_PROXY_ADDR

Legt die Adresse des Middle-Proxy fest (z. B. squid3 für HTTP oder ProxSMTP4 für SMTP). Standardwert: 127.0.0.1

MID_PROXY_PORT

Legt zusätzlich zur Adresse den Port des Middle-Proxy fest. Weiters muss der Middle-Proxy dazu konfiguriert werden, ausgehende TCP-Verbindungen auf PORT+1 weiterzuleiten. Standardwert: 8081

USER

Nach dem Start legt der Proxy seine Root-Rechte ab und arbeitet als dieser User weiter. Standardwert: tlsproxy

GROUP

Auch die Gruppenzugehörigkeit des Proxy wechselt nach dem Start von root auf die angegebene Gruppe. Standardwert: tlsproxy

2http://netfilter.org/projects/iptables/index.html 3http://www.squid-cache.org/ 4http://memberwebs.com/stef/software/proxsmtp/ 7. Konfigurationsoptionen 78

CA_SOCKET

Die Zertifizierungsstelle kommuniziert mit den Proxys über einen Unix-Domain-Socket. Der Pfad des Socket im Filesystem wird mit dieser Einstellung festgelegt. Standardwert: /var/limes/tlsproxy/ca.socket

IP_WHITELIST

IP-Adressen oder Subnetze können in die hier spezifizierte Datei eingetragen werden, um eine Untersuchung der Verbindung zu verhindern.

1 10.0.0.1 2 172.16.0.0/16 Listing 7.1: Beispiel für eine Whitelist-Datei: white.ip

Standardwert: /var/limes/tlsproxy/white.ip

IP_BLACKLIST

Adressen aus dieser Datei werden als Zieladressen abgelehnt und die TCP-Verbindung termi- niert.

1 192.168.0.1 2 192.168.40.0/24 Listing 7.2: Beispiel für eine Blacklist-Datei: black.ip

Standardwert: /var/limes/tlsproxy/black.ip

CONNECTION_LOG

Wird diese Option aktiviert, so werden Verbindungsversuche von Clients und ihre Behandlung geloggt. Standardwert: yes

TPROXY

Mit dieser Option benutzt der Proxy die TPROXY-Funktionalität des Kernels, um die Quelladresse des Clients als Quelladresse der ausgehenden TCP-Verbindungen zu verwenden. Dazu muss beim Kompilieren das Autoconf-Flag-enable-tproxy gesetzt sein. Standardwert: no

7.2 SSL/TLS-Optionen

In diesem Abschnitt werden die Secure Sockets Layer (SSL)-/TLS-Optionen vorgestellt, auf die sowohl die Proxys als auch die Zertifizierungsstelle zurückgreifen. 7. Konfigurationsoptionen 79

CA_VERIFY_FILE

Zertifizierungsstellen, deren Zertifikate in dieser Datei gefunden werden, stuft der Proxy als vertrauenswürdig ein. Der Wert NULL bedeutet, dass keine Zertifikatsdatei benützt wird. Standardwert: NULL

CA_VERIFY_PATH

Zertifizierungsstellen, deren Zertifikate in Dateien in diesem Verzeichnis gefunden werden, stuft der Proxy als vertrauenswürdig ein. In jeder Datei in diesem Verzeichnis wird ein base64-kodiertes Zertifikat abgelegt. Standardwert: certs

CA_CERT_FILE

Diese Datei enthält das Zertifikat der Zertifizierungsstelle. Standardwert: cacert.pem

CA_KEY_FILE

Diese Datei enthält den Private-Key zum Zertifikat der Zertifizierungsstelle. Standardwert: cakey.pem

CA_PASSPHRASE

Optional kann für den Private-Key der Zertifizierungsstelle auch eine Passphrase angegeben werden. Standardwert: NULL

PROXY_KEYS_FILE

Diese Datei enthält den Private- und den Public-Key des von der Zertifizierungsstelle ausge- stellten Proxy-Zertifikates. Standardwert: /var/limes/tls-proxy/proxy-keypair.pem

PROXY_PASSPHRASE

Falls der Private-Key verschlüsselt ist, kann auch hier die passende Passphrase eingestellt werden. Standardwert: NULL 7. Konfigurationsoptionen 80

HOST_WHITELIST

Im Gegensatz zu IP-Whitelists können Host-Whitelists eine Übereinstimmung erst beim TLS- Handshake mit dem Server feststellen. Ab diesem Zeitpunkt wird jedoch die Verbindung nicht mehr untersucht und die Daten werden direkt an den Server weitergeleitet. 1 mail.underground8.com Listing 7.3: Beispiel für eine Whitelist-Datei: white.host

Standardwert: /var/limes/tlsproxy/white.host

HOST_BLACKLIST

Wird beim TLS-Handshake eine Übereinstimmung mit einem Host aus der Blacklist gefunden, wird die SMTP-Verbindung terminiert. 1 badmail.example.com 2 attacker.example.com Listing 7.4: Beispiel für eine Blacklist-Datei: black.host

Standardwert: /var/limes/tlsproxy/black.host

BLOCK_CLIENT_CERTS

Da die Behandlung von Client-Zertifikaten nicht unterstützt wird, kann die Reaktion auf eine dementsprechende Anfrage des Servers wie folgt konfiguriert werden: • yes: Die TLS-Session wird abgebrochen • no: Die SMTP-Verbindung wird unmodifiziert durchgereicht und kann nicht weiter untersucht werden. Standardwert: yes

CERT_VERIFY_LEVEL

Tritt bei der Verifikation des Server-Zertifikates ein Fehler auf, wird dies je nach eingestelltem Level wie folgt behandelt: • 1: Der Fehler wird ignoriert und dem Client ein fehlerfreies Zertifikat präsentiert. • 2: Die Fehler im Zertifikat werden an den Client weitergereicht. • 3: Die SMTP-Verbindung wird terminiert. Standardwert: 2

SSLv2

Wird SSLv2 hier deaktiviert, ist es im TLS-Handshake nicht verfügbar. Standardwert: no 7. Konfigurationsoptionen 81

SSLv3

Wird SSLv3 hier deaktiviert, ist es im TLS-Handshake nicht verfügbar. Standardwert: yes

TLSv1.0

Wird TLSv1.0 hier deaktiviert, ist es im TLS-Handshake nicht verfügbar. Standardwert: yes

7.3 SMTP-spezifische Optionen

TLS_ON

Ist diese Option aktiviert, erwartet der Proxy gleich nach dem TCP-Handshake einen TLS- Handshake vom Client und führt auch mit dem Zielserver einen TLS-Handshake aus. Diese Betriebsart ist geeignet, um den Proxy für einen separaten Port zu aktivieren, auf dem TLS Voraussetzung ist. Wenn die STARTTLS-Funktionalität benutzt werden soll, darf diese Betriebsart nicht verwendet werden. Deshalb muss für den Betrieb der Standartwert von „yes“ auf „no“ geändert werden. Standardwert: yes Dieser Standardwert ist nur für HTTPS sinnvoll.

SMTP_CMD_TIMEOUT

Wird dieser Wert gesetzt (in Sekunden, > 0), wird nur bis zum spezifizierten Timeout auf ein neues Kommando des Clients bzw. auf eine neue Antwort des Servers gewartet. Ansonsten wartet der Proxy, bis eine Seite die TCP-Verbindung abbricht. Ein solcher Timeout sollte laut [Kle08] mindestens 5 Minuten (300 Sekunden) betragen. Da aber eine Verzögerung durch den Middle-Proxy eingerechnet werden muss, sollte der Wert für diese Option höher sein. Standardwert: 360

SMTP_STARTTLS

Diese Option steuert die Unterstützung des Proxy für das STARTTLS-Kommando. Der Proxy ist zwar auch ohne dieses Kommando betriebsfähig, jedoch nur als Klartext-Proxy für SMTP. Standardwert: yes

SMTP_IP_LOCAL_LIST

Die hier spezifizierte Datei enthält eine Liste aller IP-Adressen bzw. Subnetze, die vom Proxy als intern angesehen werden. Aufgrund dieser Liste und der folgenden vier Optionen entscheidet 7. Konfigurationsoptionen 82 der Proxy, ob TLS auf einer SMTP-Verbindung erzwungen wird oder nicht.

1 10.0.0.0/24 2 10.1.0.0/16 3 10.2.1.1 Listing 7.5: Beispiel für die Datei: local.ip

Standardwert: /var/limes/tlsproxy/local.ip

SMTP_FORCE_SERVER_TLS_INT

Mit dieser Option versucht der Proxy auf jeden Fall eine TLS-Session zu einem internen Server aufzubauen. Schlägt dies fehl oder unterstützt der Server kein STARTTLS, terminiert der Proxy die SMTP-Verbindung. Standardwert: no

SMTP_FORCE_SERVER_TLS_EXT

Mit dieser Option versucht der Proxy auf jeden Fall eine TLS-Session zu einem externen Server aufzubauen. Schlägt dies fehl oder unterstützt der Server kein STARTTLS, terminiert der Proxy die SMTP-Verbindung. Standardwert: no

SMTP_FORCE_CLIENT_TLS_INT

Mit dieser Option erlaubt der Proxy einem internen Client keine anderen Kommandos als EHLO, NOOP, QUIT und STARTTLS, bevor er eine TLS-Session aufgebaut hat. Standardwert: no

SMTP_FORCE_CLIENT_TLS_EXT

Mit dieser Option erlaubt der Proxy einem externen Client keine anderen Kommandos als EHLO, NOOP, QUIT und STARTTLS, bevor er eine TLS-Session aufgebaut hat. Standardwert: no

CERT_DEPOSIT_PATH

Anstatt Zertifikate on-the-fly erzeugen zu lassen, ist es möglich, Zertifikate und die dazuge- hörigen Private-Keys am Proxy zu hinterlegen. Diese Option spezifiziert einen Ordner im Dateisystem, der für jedes hinterlegte Zertifikat eine Datei enthält. In dieser Datei muss zusätzlich ein passender Private-Key und kann eine Passphrase für den Key enthalten sein.

1 (optional) In der ersten Zeile kann mit PASS: die Passphrase des Private-Key angegeben werden. 2 -----BEGIN CERTIFICATE----- 7. Konfigurationsoptionen 83

3 Das base64 kodierte Zertifikat des Servers. 4 -----END CERTIFICATE----- 5 -----BEGIN RSA PRIVATE KEY----- oder -----BEGIN DSA PRIVATE KEY----- oder -----BEGIN PRIVATE KEY----- 6 Der base64 kodierte private Key des Servers. 7 -----END RSA PRIVATE KEY----- oder -----END DSA PRIVATE KEY----- oder -----END PRIVATE KEY ----- Listing 7.6: Aufbau einer Datei des Zertifikatsspeichers

Standardwert: /var/limes/tlsproxy/CertDeposit

SMTP_RELAY_ADDR

Anstatt eine SMTP-Verbindung zum Zielserver herzustellen, kann der Proxy sich zu einem SMTP-Relay-Host verbinden. Standardwert: NULL Beispielwert: 10.2.1.1

SMTP_RELAY_PORT

Der Port des Relay-Hosts. Wird nur interpretiert, wenn auch SMTP_RELAY_ADDR gesetzt ist. Standardwert: NULL Beispielwert: 25

7.4 Optionen für die Zertifizierungsstelle

CA_CERT_STORE

In dieser Datei legt die Zertifizierungsstelle alle benötigten Informationen zu den von ihr erzeugten Zertifikaten ab, um sie bei Bedarf (z. B. beim Neustart) neu erzeugen zu können. Standardwert: castore.txt.

CA_SOCKET

Die Zertifizierungsstelle kommuniziert mit den Proxys über einen Unix-Domain-Socket. Sein Pfad im Filesystem wird mit dieser Einstellung festgelegt. Standardwert: n/a Beispielwert: /var/run/tlsproxy/ca.socket

CERTIFICATE_LOG

Mit dieser Option gibt die Zertifizierungsstelle beim Erzeugen von Zertifikaten Informationen zum Zertifikat per Syslog aus. 7. Konfigurationsoptionen 84

Standardwert: yes

CERT_VALID_PERIOD

Gültigkeitsdauer der erzeugten Zertifikate (in Minuten). Je höher dieser Wert gewählt wird, desto weniger oft müssen Zertifikate erzeugt werden. Je geringer der Wert ist, desto weniger Zertifikate müssen gespeichert bleiben. Standardwert: 24 Kapitel 8

Tests

Dieses Kapitel beschreibt sowohl den Aufbau und die Konfiguration der Testumgebung als auch die erwarteten Funktionalität und dazu passende Tests. Zuerst werden noch einige der verwendeten Testwerkzeuge vorgestellt.

8.1 Testwerkzeuge

8.1.1 swaks

Das Werkzeug Swiss Army Knife SMTP (swaks)[55] ermöglicht es, automatisiert einen SMTP- Dialog durchzuführen und diesen sehr fein zu konfigurieren. Weiters werden auch verschiedene SMTP-Erweiterungen, wie zum Beispiel STARTTLS, unterstützt. Bei den Tests verwendete Parameter: • –to, –from: Empfänger, Absender • –protocol SMTP: Keine Erweiterungen, Beginn mit HELO • –protocol ESMTP: Unterstützt Erweiterungen, Beginn mit EHLO • –protocol ESMTPS: Beginn mit EHLO, danach STARTTLS • –quit-after: bricht den SMTP-Dialog nach einem bestimmten Kommando ab • –server: baut eine SMTP-Verbindung zu einem bestimmten Server auf anstatt zu dem MX • ...

8.1.2 OpenSSL s_client

OpenSSL bietet, neben den Crypto-Bibliotheken, auch Kommandozeilenwerkzeuge, unter anderem den OpenSSL s_client[37]. Damit ist es möglich, eine TLS-Session aufzubauen und die darin beteiligten Zertifikate zu verifizieren. Für den Test einer STARTTLS-Verbindung müssen bei SMTP jedoch vor dem TLS-Handshake SMTP-spezifische Kommandos gesendet

85 8. Tests 86

Haupt-Mailserver (Server 2003 / MS Exchange) mailserver.test.underground8.com Interne Test-VM (Ubuntu / ) exchange.underground8.com Haupt-Firewall

fw.underground8.com

Firewall mit TLS Proxy Externer Server

client.test.underground8.com (Gentoo / qmail)

external.example.com Lokale Arbeitsstation

fw.test.underground8.com Andere externe Server Mail-Relay mailrelay.test.underground8.com

Abbildung 8.1: Aufbau der Testumgebung

werden (siehe Abschnitt 2.5). Die Option „-starttls smtp“ des s_client kann diese Kommandos verwenden. Bei den Tests verwendete Parameter: • -starttls smtp: benutzt das STARTTLS-Kommando, passend zum angegeben Protokoll1, bevor der TLS-Handshake ausgeführt wird • -crlf: Wird am Terminal nur ein LF zum Beenden einer Zeile benutzt, so wird es zu einem CRLF konvertiert, wie es von SMTP erwartet wird • -connect: gibt an, zu welchem Server (IP:Port) die Verbindung aufgebaut werden soll • -debug / -msg: aktiviert zusätzliche Ausgaben, um den Ablauf des TLS-Handshakes genau verfolgen zu können • -CAfile / -CApath: zeigt auf eine Datei oder ein Verzeichnis, welches die Zertifikate der vertrauenswürdigen Zertifizierungsstellen enthält

8.2 Testumgebung

In den ersten Phasen der Entwicklung des SMTPS-Proxy war es ausreichend, die Funktionalität auf der lokalen Arbeitsstation zu testen. Doch Tests unter Bedingungen, wie sie auch im geplanten Einsatz zu finden sind, sind trotzdem notwendig. Aus diesem Grund wurde, wie in Abbildung 8.1 ersichtlich, eine Testumgebung aufgebaut, um zu testen, ob der SMTPS-Proxy die gewünschten Anforderungen erfüllt.

1In diesem Fall SMTP 8. Tests 87

Vorbereitungen: 1. Installation des SMTPS-Proxy auf einem MF Security Gateway (fw.test.underground8. com) 2. Erzeugen des Schlüsselpaares für den Proxy und die Zertifizierungsstelle (oder hinterlegen von bereits vorhandenen Schüsselpaaren) 3. Am Client (client.test.underground8.com) muss das Zertifikat der Zertifizierungsstelle als vertrauenswürdig eingestuft werden. 4. Konfiguration von Proxy und CA (siehe Kapitel 7) 5. Einrichten des Middle-Proxy proxsmtpd (siehe Abschnitt 9.1.4.3); als FilterCommand wird jedoch das bereits am MF Security Gateway (fw.test.underground8.com) vorhandene Skript „mailscanner.sh“ verwendet. 6. Einrichten von IPTABLES-Redirect-Regeln, um den SMTP-Datenverkehr durch den Proxy zu leiten (siehe 9.1.4.1). 7. Starten der Dienste SMTPS-Proxy, proxsmtpd, CA 8. An dieser Stelle ist der SMTPS-Proxy einsatzbereit. 9. Vor den Tests muss jedoch noch der Default-Gateway der lokalen Arbeitsstation auf die Adresse von fw.test.underground8.com gesetzt werden. In den nachfolgenden Abschnitten werden verschiedene Szenarios abgearbeitet und die Funktionalität überprüft. Dazu werden die in Abschnitt 8.1 erwähnten Testtools verwendet und je nach Testfall die Tests mit einem oder mehreren der Testserver (siehe Abbildung 8.1) durchgeführt.

8.3 Non-TLS-Tests

8.3.1 Grundlegender Test des Mail-Versands

Der SMTP-Proxy ist auf dem unverschlüsselten SMTP-Port (25) aktiv und unterstützt ein „Verbindungsupgrade“ mit Hilfe von STARTTLS. Die SMTP-Funktionalität muss daher auch ohne TLS erhalten bleiben.

8.3.1.1 Konfigurationsparameter

Die folgenden Einstellungen ermöglichen einen TLS-losen Test: • SMTP_FORCE_SERVER_TLS_INT = no • SMTP_FORCE_SERVER_TLS_EXT = no • SMTP_FORCE_CLIENT_TLS_INT = no • SMTP_FORCE_CLIENT_TLS_EXT = no 8. Tests 88

Eine genaue Beschreibung aller Konfigurationsparameter findet sich in Kapitel 7. Für einen TLS-losen Betrieb spielt der Status der TLS-Lizenz keine Rolle, dementsprechend ist die zugehörige Einstellung SMTP_STARTTLS für diese Tests nicht relevant.

8.3.1.2 Erwartete Funktionalität

In diesem Testszenario muss jeder SMTP-Dialog möglich sein, der auch bei einer direkten Kommunikation mit dem Mail-Server möglich ist. Dies wird aber eingeschränkt, da der verwendete Middle-Proxy (proxsmtpd) manche Kommandos oder Features nicht unterstützt und herausfiltert2. Der Proxy arbeitet transparent für jeden Transfer, der mit Zielport 25 über fw.test.underground8.com geroutet wird. Ohne TLS soll sich der Proxy äquivalent zu einem System verhalten, das proxsmtpd als transparenten Proxy einsetzt. Kommandos, die von proxsmtpd ausgefiltert werden, sind auch mit dem TLS-Proxy nicht zugelassen.

Um den Mail-Versand zu testen, werden mit swaks Testnachrichten übertragen.

1 swaks -t [email protected] --protocol SMTP 2 swaks -t [email protected] --protocol ESMTP 3 swaks -t [email protected] --protocol SMTP 4 swaks -t [email protected] --protocol ESMTP 5 swaks -t [email protected] --protocol SMTP 6 swaks -t [email protected] --protocol ESMTP

Listing 8.1: Senden einer Testnachricht mit swaks

8.3.2 Filtern von SMTP-Kommandos und Antworten

SMTP-Kommandos/Responses werden durch den Proxy einfach durchgereicht, wobei aber vom proxsmtpd einige ausgefiltert werden: Ausgefilterte (E)SMTP-Responses: • EHLO Response: PIPELINING • EHLO Response: CHUNKING • EHLO Response: XCLIENT • EHLO Response: XEXCH50 • EHLO Response: CHECKPOINT • EHLO Response: BINARYMIME Ausgefilterte (E)SMTP-Kommandos: • BDAT (CHUNKING Extension)

2z. B. PIPELINING oder spezifische Features für Microsoft Exchange 8. Tests 89

8.3.2.1 Erwartetes Ergebnis

Die Antworten auf das EHLO-Kommando enthalten die gefilterten Features, je nachdem, ob der TLS-Proxy benutzt wird oder nicht.

Für diesen Test ist der Dialog nach dem Erhalt der Antworten auf das EHLO-Kommando nicht mehr relevant. Mit der Option -q EHLO beendet swaks die Verbindung genau an dieser Stelle. Dieser Test wird nicht nur mit dem Test-Mailserver, sondern auch mit exchange.underground8. com durchgeführt, um die Filterung der für Exchange spezifischen Features zu testen.

1 swaks -t [email protected] -protocol ESMTP -q EHLO 2 swaks -t [email protected] -protocol ESMTP -q EHLO 3 swaks -t [email protected] -protocol ESMTP -q EHLO Listing 8.2: Überprüfung, welche ESMTP-Features der Proxy erlaubt

8.4 TLS-Tests

8.4.1 Grundlegender TLS-Test

Auch ohne das Erzwingen von TLS ist es möglich, eine SMTP-Verbindung mit Hilfe von STARTTLS auf eine verschlüsselte SMTP-Verbindung zu erweitern. Nach erfolgreichem Abschluss des STARTTLS-Kommandos ist die Kommunikation auf beiden Seiten des Proxy (Client zu Proxy und Proxy zu Server) verschlüsselt. Dies kann zum Beispiel mit wireshark oder tcpdump getestet werden. Innerhalb des Proxy liegt die Kommunikation im Klartext vor und wird mit proxsmtpd/mailscanner.sh auf Viren oder Spam untersucht.

8.4.1.1 Konfigurationsparameter

Die Konfigurationsparameter werden aus Abschnitt 8.3.1.1 übernommen. In diesem Fall ist, im Gegensatz zu vorher, eine vorhandene TLS-Lizenz Voraussetzung, und dementsprechend muss auch SMTP_STARTTLS = yes gesetzt sein.

8.4.1.2 Erwartete Funktionalität

Wird im SMTP-Dialog ein STARTTLS-Kommando gesendet, versucht der Proxy eine TLS- Session mit dem Server auszuhandeln. Je nach Ergebnis des TLS-Handshake antwortet der Proxy entsprechend auf das STARTTLS-Kommando des Clients. Bei einem Erfolg (220-Response), kann ein TLS-Handshake mit dem Client stattfinden. Für den TLS-Handshake verwendet der Proxy entweder ein passendes hinterlegtes Zertifikat (falls vorhanden) oder generiert ein Zertifikat auf Basis des originalen Zertifikats mit der CertificateAuthority. Danach müssen Client, Proxy und Server jegliches Wissen von vor dem TLS-Handshake verwerfen; das heißt, der Client beginnt erneut mit einem EHLO- bzw. HELO-Kommando. 8. Tests 90

Auch das Verbindungsupgrade durch STARTTLS kann mit swaks getestet werden. Dazu muss ESMTPS als Protokoll ausgewählt werden. Durch die Option -q EHLO beendet swaks die Verbindung, nachdem das Programm die Antworten auf das zweite EHLO-Kommando empfangen hat.

1 swaks -t [email protected] --protocol ESMTPS -q EHLO 2 swaks -t [email protected] --protocol ESMTPS -q EHLO 3 swaks -t [email protected] --protocol ESMTPS -q EHLO

Listing 8.3: Senden einer Nachricht unter Verwendung von STARTTLS mit swaks

8.4.2 STARTTLS mit On-The-Fly-Zertifikat

Um den TLS-Handshake mit dem client.test.underground8.com durchzuführen, erzeugt der Proxy ein Zertifikat auf Basis des Server-Zertifikats. Signiert wird dieses Zertifikat von der Zertifizierungsstelle, der auch client.test.underground8.com vertrauen muss.

8.4.2.1 Erwartete Funktionalität

Das Zertifikat wird von client.test.underground8.com ohne Warnmeldung akzeptiert.

In diesem Test wird mit OpenSSL s_client eine SMTP-Verbindung zu bsmtp.telekom.at aufgebaut und mit STARTTLS ein TLS-Handshake gestartet. Der s_client verifiziert das im TLS-Handshake erhaltene Zertifikat. Dieses Zertifikat wurde vom TLS-Proxy on-the-fly erzeugt und deshalb von client.test.underground8.com akzeptiert.

1 openssl s_client -starttls smtp -crlf -connect bsmtp.telekom.at:25 -debug -CAfile rootca_cert.crt

Listing 8.4: Überprüfung des Zertifikats mit OpenSSL

8.4.3 Server kündigt keine STARTTLS-Unterstützung an

Wenn der Server keine STARTTLS-Unterstützung ankündigt, kündigt sie auch der Proxy dem Client nicht an (siehe Abschnitt 5.2.3).

8.4.3.1 Erwartete Funktionalität

Versucht der Client dennoch ein STARTTLS-Kommando zu senden, antwortet der Proxy (genauer der proxsmtpd) mit „502 Command not implemented“. Der Client muss nun entscheiden, ob die Kommunikation weiter stattfinden soll, obwohl sie ohne TLS und damit unverschlüsselt ablaufen würde. Auch wenn der Client, trotz Ablehnung des STARTTLS-Kommandos, einen TLS-Handshake beginnt, soll dieser fehlschlagen. 8. Tests 91

Für diesen Test wird der OpenSSL s_client angewiesen, eine STMP-Verbindung zu einem Mail- server ohne STARTTLS-Unterstützung herzustellen und zu versuchen STARTTLS zu benützen. Zu diesem Zweck wurde die STARTTLS-Unterstützung auf mailserver.test.underground8.com deaktiviert.

1 openssl s_client -starttls smtp -crlf -connect mailserver.test.underground8.com:25 Listing 8.5: Testen der Reaktion beim Senden von STARTTLS bei Servern ohne STARTTLS- Unterstützung

8.4.4 Server präsentiert ungültiges oder abgelaufenes Zertifikat

Die Reaktion des Proxy auf ein ungültiges oder abgelaufenes Zertifikat hängt vom Konfigura- tionsparameter CERT_VERIFY_LEVEL ab: • CERT_VERIFY_LEVEL = 1: Selbst wenn der Server ein ungültiges oder abgelaufenes Zertifikat präsentiert, wird die Verbindung erlaubt und ein gültiges On-the-fly-Zertifikat erzeugt. • CERT_VERIFY_LEVEL = 2: Fehler bei der Verifikation des Server-Zertifikats werden in das generierte Zertifikat übernommen. Bei abgelaufenen Server-Zertifikaten werden dementsprechend abgelaufene Zertifikate generiert. Dem Client wird deshalb eine War- nung angezeigt, aufgrund deren er entscheiden kann, die SMTP-Verbindung abzubrechen oder fortzusetzen. • CERT_VERIFY_LEVEL = 3: Bei einem ungültigen oder abgelaufenen Zertifikat wird eine 454-Response (TLS not available due to temporary reason) als Antwort auf sein STARTTLS-Kommando an den Client gesendet. Der TLS-Handshake kann nun nicht mehr stattfinden.

8.4.5 CA ist nicht erreichbar

Ein nicht erreichbarer CA-Dienst verhindert zwar eine On-the-fly-Erzeugung der Zertifikate, darf aber den normalen SMTP-Betrieb (ohne TLS) nicht beeinflussen. Ein Versuch, STARTTLS zu benutzen, wird mit einer 454-Response abgelehnt, da dies normalerweise ein temporärer Zustand ist.

8.4.6 STARTTLS mit hinterlegtem Zertifikat

Der Proxy bietet die Möglichkeit, Zertifikate (und die zugehörigen privaten Schlüssel) von SMTP-Servern zu hinterlegen. Anstatt ein Zertifikat on-the-fly zu generieren, wird ein hinter- legtes Zertifikat verwendet. Dazu muss der Hash-Wert des Subjects des hinterlegten Zertifikats mit dem Hash-Wert des Subjects des Zertifikats des Ziel-Servers übereinstimmen. Wird kein passendes Zertifikat gefunden, ist die On-the-fly-Erzeugung als Fallback immer noch möglich. 8. Tests 92

8.4.6.1 Normale Funktionalität

Wird versucht eine SMTP-Verbindung zu einem Server herzustellen, für den ein Zertifikat hinterlegt wurde, so soll dieses verwendet und dem Client während des TLS-Handshake präsentiert werden.

Zertifikat für mailserver.test.underground8.com ist auf fw.test.underground8.com hinterlegt.

1 openssl s\_client -starttls smtp -crlf -connect mailserver.test.underground8.com:25

Listing 8.6: Test, ob das hinterlegte Zertifikat verwendet wird

Wird der Proxy nur für SMTP-Server verwendet, für die auch ein Zertifikat hinterlegt wurde, so ist ein Betrieb auch ohne die CertificateAuthority möglich.

8.4.6.2 Zertifikat des Servers stimmt nicht mit dem hinterlegten überein

Wurde ein zum Subject des Server-Zertifikats passendes hinterlegtes Zertifikat gefunden, werden die beiden Zertifikate noch miteinander verglichen (bzw. deren Hash-Werte), um Man-in-the- middle-Attacken zu erkennen. Stimmen die Zertifikate nicht überein, so ist kein TLS-Handshake möglich und der Client erhält auch das STARTTLS-Kommando, eine 454-Response.

Ein Zertifikat, dessen Subject zwar passt, aber eine andere Prüfsumme aufweist, wird hinterlegt. Dadurch stimmt es nicht mehr mit dem vom Server präsentierten Zertifikat überein, und der Proxy wird den TLS-Handshake abbrechen.

1 #if proxy cannot read the file it cannot use den certifikate 2 chmod a-r /var/limes/tlsproxy/smtps/CertDeposit/paulibaer.pem 3 #enable a certificate with another checksum 4 chmod +r /var/limes/tlsproxy/smtps/CertDeposit/paulibaer.fake.pem 5 #restart tlsproxy 6 /etc/rc.d/rc.tlsproxy restart smtps 7 8 swaks --protocol ESMTPS --to [email protected] -q EHLO

Listing 8.7: Erkennen von gefälschten Zertifikaten

8.4.7 Relay zu mailrelay.test.underground8.com

Mit den Konfigurationsparametern SMTP_RELAY_ADDR und SMTP_RELAY_PORT kann mailrelay.test.underground8.com als SMTP-Relay benutzt werden. In diesem Fall wird die SMTP-Kommunikation nicht am Proxy untersucht. 8. Tests 93

8.4.7.1 TLS terminiert am Proxy

Der Proxy baut zum Server nur eine SMTP-Verbindung auf, um per TLS-Handshake ein Zertifikat zu erhalten. Der Client kann nun, per STARTTLS, die SMTP-Verbindung bis zum Proxy verschlüsseln. Der restliche SMTP-Dialog wird vom Proxy zum Relay weitergeleitet.

8.4.7.2 Relay ohne TLS

Unterstützt der Server kein STARTTLS oder schlägt der TLS-Handshake fehl, kann auch der Client keine TLS-Session zum Proxy aufbauen. Ein Relay zu mailrelay.test.underground8.com ist dennoch möglich.

1 swaks --protocol ESMTPS --to [email protected] 2 swaks --protocol ESMTP --to [email protected] 3 swaks --protocol ESMTPS --to [email protected] 4 swaks --protocol ESMTP --to [email protected] 5 swaks --protocol ESMTPS --to [email protected] 6 swaks --protocol ESMTP --to [email protected] Listing 8.8: Testen der Relay-Funktionalität mit und ohne STARTTLS

8.5 Pass-Through

Soll der Proxy für bestimmte TCP-Verbindungen nicht aktiv werden und die Daten ohne Analyse durchreichen, gibt es die Möglichkeit, Whitelists zu definieren. Dies ist sowohl auf Basis von IP-Adressen als auch auf Basis von Hostnamen möglich. Weiters kann ein Pass-Through nötig sein, wenn ein Server beim TLS-Handshake ein Client-Zertifikat verlangt.

8.5.1 Konfigurationsparameter

• IP_WHITELIST : Pfad zu einer Datei mit IP-Adressen/Subnetzen • HOST_WHITELIST: Pfad zu einer Datei mit Hostnamen • BLOCK_CLIENT_CERTS : yes/no

8.5.2 Erwartete Funktionalität

Scheint eine Server-IP in der IP_WHITELIST auf, kann mit dem Durchreichen der Daten schon vor dem Start des SMTP-Handlers begonnen werden. Um aber die Whitelist auf der Basis von Hostnamen zu verwenden, muss erst der TLS-Handshake mit dem Server erfolgt sein, da erst dann der Name aus dem Serverzertifikat zur Verfügung steht. Wird BLOCK_CLIENT_CERTS auf yes gesetzt, muss der Proxy den TLS-Handshake abbrechen, 8. Tests 94 falls der Server ein Client-Zertifikat verlangt. Bei BLOCK_CLIENT_CERTS = no wird die TCP-Verbindung wie bei einem Whitelist-Eintrag durchgeschaltet.

8.5.3 IP in Whitelist

Sofort nach dem TCP-Verbindungsaufbau werden die Daten direkt zum Server durchgereicht, es findet keine Überprüfung auf Spam oder Viren statt. Scheint der Eintrag „PASS THROUGH: connection from to “ im Log auf, war der Test erfolgreich.

8.5.4 Hostname in Whitelist

Erst nachdem durch den TLS-Handshake mit dem Server sein DNS-Name bekannt ist, kann überprüft werden, ob er auf der Whitelist steht. Wenn ja, wird die TCP-Verbindung zum Server neu aufgebaut und sofort zum Client durchgereicht.

8.5.5 Client-Zertifikate

Verlangt einer der Server (siehe Abbildung 8.1) ein Client-Zertifikat, gibt es folgende Möglich- keiten:

8.5.5.1 Blockieren von Client-Zertifikaten

In diesem Fall soll das STARTTLS-Kommando mit einer 421-Response beantwortet und somit abgelehnt werden. Die SMTP-Verbindung wird dadurch unterbrochen. smtpd_tls_req_ccert = yes und smtpd_tls_security_level = encrypt müssen in der Datei /etc/postfix/main.cf auf mailserver.test.underground8.com gesetzt sein, damit er Client-Zertifikate verlangt.

8.5.5.2 Tunneln der TCP-Verbindung bei Nachfrage nach einem Client-Zertifikat

Sollen die Client-Zertifikate nicht geblockt werden, bleibt nur die Möglichkeit, die TCP- Verbindung mit Hilfe von Pass-Through durchzureichen. In diesem Fall kommen Viren-Scanner und Spam-Filter nicht zum Einsatz.

8.6 Forced-TLS-Tests

Es ist möglich, mit Hilfe der verschiedenen Optionen SMTP_FORCE..., die Verwendung von STARTTLS entweder serverseitig oder clientseitig zu erzwingen. Wird STARTTLS auf der Server-Seite erzwungen, so baut der Proxy schon nach den EHLO- Antworten eine TLS-Session zum Server auf. Schlägt dies fehl oder unterstützt der Server die STARTTLS-Erweiterung nicht, muss der Proxy die SMTP-Verbindung unterbrechen3. Um

3Dazu sendet er ein QUIT-Kommando an der Server 8. Tests 95 aber die SMTP-Verbindung zum Client zu unterbrechen, gibt es laut RFC nur die Möglichkeit einer 421-Antwort (Server going down). Diese wird dabei an den Client gesendet und danach wird die TCP-Verbindung geschlossen. Wird STARTTLS auf der Client-Seite erzwungen, so reagiert der Proxy auf jedes Kom- mando mit Ausnahme von EHLO, STARTTLS, NOOP und QUIT mit der Meldung „530 Must issue a STARTTLS command first“. Eine darüber hinausgehende Kommunikation mit dem Server ist somit erst nach erfolgtem TLS-Handshake möglich. Diese Vorgangsweise wird auch in RFC-3207 ([Hof02]) empfohlen.

8.6.1 Konfigurationsparameter

Auch bei diesen Tests ist eine TLS-Lizenz erforderlich (SMTP_STARTTLS). Neben der Möglichkeit, STARTTLS auf Server- und Client-Seite zu erzwingen, kann mit den folgenden Parametern festgelegt werden, ob dies jeweils nur für interne oder auch für externe IP-Adressen gelten soll:

• SMTP_FORCE_SERVER_TLS_INT = yes/no • SMTP_FORCE_SERVER_TLS_EXT = yes/no • SMTP_FORCE_CLIENT_TLS_INT = yes/no • SMTP_FORCE_CLIENT_TLS_EXT = yes/no

Die Einstellung SMTP_IP_LOCAL_LIST muss auf eine Datei verweisen, die die lokalen IP-Adressen oder Subnetze enthält. Wird dies nicht konfiguriert oder ist die Datei nicht vorhanden, so werden alle Adressen als extern behandelt.

8.6.2 Serverseitiges Erzwingen von TLS

In diesem Modus initiiert der Proxy nach Erhalt der EHLO-Antworten eine TLS-Session mit dem Server. Ist in den Antworten auf das EHLO-Kommando das STARTTLS-Feature nicht aufgeführt oder schlägt der TLS-Handshake fehl, muss der Proxy die SMTP-Verbindung abbrechen. Dies ist laut RFC nur mit einer 421-Response an den Client möglich. Die SMTP- Verbindung zum Server kann der Proxy einfach mit dem QUIT-Kommando beenden.

8.6.2.1 Server-TLS ist erfolgreich

Empfängt der Client die EHLO-Response, so ist sichergestellt, dass der TLS-Handshake mit dem Server erfolgreich war. Ansonsten wäre die SMTP-Verbindung schon vom Proxy abgebrochen worden. Dies kann z. B. mit tcpdump oder wireshark am externen Interface des Proxy getestet werden. Ein STARTTLS des Clients ist optional immer noch möglich. 8. Tests 96

8.6.2.2 Server-TLS-Handshake schlägt fehl

Der TLS-Handshake mit dem Server kann aus verschiedenen Gründen fehlschlagen: • Das Zertifikat kann nicht verifiziert werden oder ist abgelaufen (abhängig vom CERT_- VERIFY_LEVEL). • Das Zertifikat stimmt nicht mit dem hinterlegten überein. • Der Server verlangt ein Client-Zertifikat und BLOCK_CLIENT_CERTS ist aktiviert. • Beim Erzeugen des On-The-Fly-Zertifikats tritt ein Fehler auf. • Die CertificateAuthority ist nicht erreichbar oder reagiert nicht. • Der DNS-Name des Servers befindet sich in der Blacklist. In diesen Fällen bricht der Proxy die SMTP-Verbindung mit einer 421-Response an den Client ab. Der TLS-Proxy beschreibt die Art des Fehlers im Textteil der Antwort genauer.

8.6.2.3 Server bietet kein STARTTLS an

Auch in diesem Fall muss der Proxy die SMTP-Verbindung mit einer 421-Response auf das EHLO-Kommando des Clients abbrechen.

8.6.2.4 Force-Server-Internal setzt hinterlegtes Zertifikat voraus

Wird Force-Server-Internal konfiguriert, muss auch zu jedem internen Server ein passendes Zertifikat hinterlegt sein. Wird versucht eine Verbindung ohne ein solches Zertifikat aufzubauen, muss der Proxy die SMTP-Verbindung mit einer 421-Response abbrechen.

8.6.2.5 HELO-/EHLO-Replacement

Sendet der Client anstatt eines EHLO ein (legacy) HELO, kann der Proxy aus der Antwort des Servers nicht feststellen, ob STARTTLS unterstützt wird. Deshalb sendet der Proxy in diesem Fall selbst dann ein EHLO an den Server, wenn der Client nur HELO sendet. Der Proxy muss dann die EHLO-Antwort des Servers so ändern, wie sie vom Client als Antwort auf ein HELO-Kommando erwartet wird.

8.6.3 Clientseitiges Erzwingen von TLS

In diesem Modus erlaubt der Proxy ohne eine aufrechte TLS-Session nur bestimmte Komman- dos.

8.6.3.1 Client-TLS ist erfolgreich

Nach einem erfolgreichen TLS-Handshake auf Client-Seite werden alle Kommandos des Clients wieder normal behandelt. 8. Tests 97

8.6.3.2 Versuchte Mail-Zustellung ohne Client-TLS

Solange keine aufrechte TLS-Session mit dem Client besteht, reagiert der Proxy auf alle Kommandos außer EHLO, QUIT, STARTTLS und NOOP, wie in RFC 3207 vorgeschlagen, mit „530 Must issue a STARTTLS command first“.

8.6.3.3 Kombinierte Tests

Client- und serverseitiges Erzwingen von TLS kann auch in Kombination miteinander verwen- det werden. Serverseitiges Erzwingen bewirkt einen TLS-Handshake nach erfolgtem EHLO, clientseitiges Erzwingen verhindert eine weitere Kommunikation ohne TLS-Session auf Client- Seite. Kapitel 9

Handbuch zur Systemintegration

Dieses Kapitel soll als Handbuch zur Systemintegration auch losgelöst von dieser Arbeit verwendet werden. Es enthält neben einer Beschreibung der typischen Einsatzszenarien und deren Abbildungsmöglichkeiten mit dem SMTPS-Proxy auch die notwendigen Konfigurations- optionen.

9.1 Installation

Der SMTPS-Proxy wurde zum Einsatz in einer Security-Appliance1 der Firma Underground_8 secure computing entwickelt. Die Verwendung ohne eine solche Appliance ist ebenfalls möglich und wird in diesem Abschnitt genauer beschrieben.

9.1.1 Softwareabhängigkeiten

Die Versionen in Tabelle 9.1 verstehen sich als Mindestanforderungen. Bei manchen Linux- Distributionen (z. B. Debian,Ubuntu, etc.) ist es außerdem nötig, zusätzlich die passenden -dev-Pakete zu installieren.

9.1.2 Installation auf einem Linux-System

9.1.2.1 Übersetzen des Quelltextes

Damit die Software auf verschiedensten Systemen lauffähig ist, wird sie direkt aus dem Quelltext übersetzt. Das Übersetzen kann vereinfacht werden, indem der TLS-Proxy das GNU2-build-system3 verwendet, um sowohl das Vorhandensein der Abhängigkeiten als auch deren Versionen und

1MF Security Gateway 2Ein rekursives Akronym für „GNU’s Not Unix!“ (GNU) 3Auch bekannt als ”autotools”

98 9. Handbuch zur Systemintegration 99

Name Version Quelle glibc 2.3.3 gnu.org[18] gcc 3.3.3 gnu.org[14] libtool 1.5.6 gnu.org[23] libcap 1.10 kernel.org[41] binutils 2.15.90.0.3 gnu.org[21] openssl >=0.9.8o <1.0.0 openssl.org[39] autoconf 2.59 gnu.org[19] automake 1.9.6 gnu.org[20] make 3.80 gnu.org[24] iptables 1.4.0 netfilter.org[34] linux-kernel >=2.4.36.7 <2.6.28 kernel.org[32] tproxy patch TPROXY2 nicht TPROXY4 balabit.com[53]

Tabelle 9.1: Software-Voraussetzungen für den TLS-Proxy

Pfade im Filesystem zu überprüfen. Dies kann mit den Befehlen aus Listing 9.1 automatisiert werden.

1 autoreconf -vifs 2 ./configure --enable-https --enable-tproxy --enable-debug --enable-rcvd-via --enable-smtps 3 make

Listing 9.1: Übersetzen des Quelltextes

Der erste Befehl in Listing 9.1 ruft jene Teile der Autotools (aclocal, autoconf, autoheader and automake) auf, die zum Erzeugen des Configure-Skripts benötigt werden. Dieses Skript kann dann zum Generieren des Makefiles verwendet werden. Die möglichen Optionen sind in Tabelle 9.2 beschrieben. Es ist auch möglich, sowohl die Unterstützung für HTTPS als auch für SMTPS zu aktivieren.

–enable-https Aktiviert die Unterstützung für HTTP(S). –enable-smtps Aktiviert die Unterstützung für SMTP(S). –enable-tproxy Ermöglicht die Nutzung des TPROXY-Kernel-Patches. –enable-rcvd-via Wird der Proxy für HTTP(S) verwendet, so fügt er die IP-Adresse des Clients mit dem X-TLS-Proxy-received-via Header in die Pakete ein. –enable-debug Ermöglicht das Aktivieren von Debug-Ausgaben. –enable-thrlog Fügt den Log-Meldungen die Thread-ID des verursachenden Threads hinzu.

Tabelle 9.2: Beschreibung der möglichen Optionen für den Aufruf des Configure-Skripts

Mit Hilfe von make wird nun der Quelltext in ein lauffähiges Programm übersetzt. 9. Handbuch zur Systemintegration 100

9.1.2.2 Programmaufrufe

Nach dem korrekten Übersetzen liegen zwei ausführbare Programmdateien vor: • TLS-Proxy: Das Hauptprogramm mit Unterstützung für das HTTP(S)- oder SMTP(S)- Protokoll • CA: Die Zertifizierungsstelle zum Erzeugen der On-the-fly-Zertifikate Die Tabellen 9.3 und 9.4 zeigen die Kommandozeilenparameter für die Programme. Es ist nur möglich den Proxy für genau ein Protokoll zu starten. Werden mehrere Protokolle benötigt, muss für jedes Protokoll jeweils ein Programm gestartet werden.

-P SMTPS Das Programm startet als Proxy für SMTPS -P HTTPS Das Programm startet als Proxy für HTTPS -P NONE Das Programm startet ohne Protokollunterstützung (z. B. zum Testen der Konfiguration) -c path Spezifiziert den Pfad der Konfigurationsdatei (Standardwert: /etc/tlsproxy/proxy.conf).

Tabelle 9.3: Kommandozeilenparameter des TLS-Proxys

-h, –help Das Programm zeigt die möglichen Kommandozeilenparameter an und beendet sich. -c path Spezifiziert den Pfad der Konfigurationsdatei (Standardwert: /etc/tlsproxy/ca. conf).

Tabelle 9.4: Kommandozeilenparameter für CA.

9.1.3 Statisches Linken der OpenSSL-Bibliotheken

In manchen Fällen ist es nötig, für den TLS-Proxy eine andere Version der OpenSSL- Bibliotheken zu verwenden als für den Rest des Systems. Das ist zum Beispiel dann der Fall, wenn die verwendete Linux-Distribution zu alte, zu neue, oder gar keine Versionen von OpenSSL anbietet. Für den TLS-Proxy muss OpenSSL mit den Befehlen in Listing 9.2 konfiguriert, über- setzt und installiert werden. Dadurch wird die Verwendung von OpenSSL in Multithreaded- Programmen ermöglicht, und es werden die statischen Bibliotheken in den angegeben Pfad kopiert. Damit bestimmt werden kann, welche OpenSSL-Bibliotheken statisch zum TLS-Proxy gelinkt werden, müssen einige Änderungen an den Konfigurationsdateien der autotools vorge- nommen werden: 9. Handbuch zur Systemintegration 101

1 ./config threads --prefix=/usr/src/openssl-tlsproxy 2 make 3 make install Listing 9.2: Übersetzen der statischen OpenSSL-Bibliotheken

Um die Abhängigkeit zu systemweiten OpenSSL-Bibilotheken zu entfernen und das Linken mit eventuell vorhandenen Bibliotheken zu vermeiden, müssen die Zeilen aus Listing 9.3 aus der Datei configure.ac entfernt oder auskommentiert werden.

1 AC_CHECK_LIB([crypto], BIO_new) 2 AC_CHECK_LIB([ssl], SSL_do_handshake)

Listing 9.3: Änderungen in Datei configure.ac

Für das statische Linken der Bibliotheken zum TLS-Proxy, müssen die Zeilen aus Listing 9.4 mit dem korrekten Pfad zu den Bibliotheken zur Datei src/Makefile.am hinzugefügt werden.

1 INCLUDES= -I /usr/src/openssl-tlsproxy/include 2 TLSProxy_LDADD+= /usr/src/openssl-tlsproxy/lib/libssl.a /usr/src/openssl-tlsproxy/lib/ libcrypto.a

Listing 9.4: Änderungen in Datei src/Makefile.am

Analog dazu, müssen die Zeilen aus Listing 9.5 mit dem korrekten Pfad zu den Bibliotheken zur Datei src/ca/Makefile.am hinzugefügt werden, um die Bibliotheken statisch zur CA zu linken.

1 INCLUDES= -I /usr/src/openssl-tlsproxy/include 2 CA_LDADD= /usr/src/openssl-tlsproxy/lib/libssl.a /usr/src/openssl-tlsproxy/lib/libcrypto.a

Listing 9.5: Änderungen in Datei src/ca/Makefile.am

9.1.4 Grundkonfiguration

Die Standardwerte der Konfigurationsoptionen aus Kapitel 7 sind zwar großteils für den Betrieb des TLS-Proxys ausreichend, einige Optionen müssen aber angepasst werden. Ansonsten ist die Grundkonfiguration ausreichend, um den TLS-Proxy sowohl als Forward- als auch als Reverse-Proxy zu betreiben. Kommunikation mit SMTP wird genauso unterstützt wie das „Verbindungs-Upgrade“ mit STARTTLS. Dabei werden die passenden Zertifikate on-the-fly erzeugt. Erweiterte Szenarien finden sich in Abschnitt 9.2.

9.1.4.1 Firewall-Konfiguration

Da der TLS-Proxy normalerweise auf einer Firewall betrieben wird, muss diese auch konfiguriert werden, um ankommende SMTP-Pakete umzuleiten. Die in Listing 9.6 (aus [Zie03, Seite 318]) 9. Handbuch zur Systemintegration 102 dargestellte, allgemeine Form einer IPTABLES4-REDIRECT-Regel kann für diesen Zweck angepasst werden.

1 iptables -t nat -A PREROUTING -i ... \ 2 -j REDIRECT [--to-ports [-]] Listing 9.6: Allgemeine Form für IPTABLES-REDIRECT

In der folgenden Grundkonfiguration wird von einer Firewall mit einem internen sowie einem externen Netzwerk-Interface ausgegangen. Der SMTP-Datentransfer soll aus beiden Richtungen über den Proxy geleitet werden. Jener Teil der IPTABLES-Regel5 aus Listing 9.7, der festlegt, auf welche Pakete der REDIRECT angewendet werden soll, muss deshalb das interne und das externe Interface berücksichtigen. Zusätzlich ist eine Überprüfung erforderlich, ob der Zielport dem SMTP-Port (25) entspricht.

1 iptables -t nat -A PREROUTING -p tcp --dport 25 -i -j REDIRECT --to- ports 2 iptables -t nat -A PREROUTING -p tcp --dport 25 -i -j REDIRECT --to- ports Listing 9.7: IPTABLES-REDIRECT-Regeln für die Umleitung des SMTP-Datenverkehrs

9.1.4.2 Dateisystemrechte und Pfade

Der TLS-Proxy benötigt nur für den Start Root-Rechte und kann, nachdem er mit posix6 capabilities[54] die für den Betrieb benötigten Rechte erhalten hat, die Root-Rechte ablegen und die mit USER und GROUP spezifizierten Rechte annehmen. Aus diesem Grund ist es nötig, alle Pfade für diesen User oder diese Gruppe lesbar und beschreibbar zu machen. • PID_FILE • CA_SOCKET • IP_WHITELIST • IP_BLACKLIST • HOST_WHITELIST • HOST_BLACKLIST • CA_VERIFY_FILE • CA_VERIFY_PATH • CA_CERT_FILE • CA_KEY_FILE • PROXY_KEYS_FILE 4siehe [34] 5Kommandozeilenprogramm zur Konfiguration des Paketfilters des Linux 2.4.x bzw. Linux 2.6.x Kernels (IPTABLES) 6Portable Interface (POSIX) 9. Handbuch zur Systemintegration 103

• SMTP_IP_LOCAL_LIST • CERT_DEPOSIT_PATH) Weiters müssen die Pfade auch im Filesystem existieren.

9.1.4.3 Einrichten von ProxSMTP als Middle-Proxy

Um die Mail-Nachrichten nach Viren und Spam zu untersuchen, verlässt sich der TLS-Proxy auf einen Middle-Proxy für die Anbindung der Scanner. Die Schnittstelle ist allgemein gehalten und verwendet SMTP, um möglichst alle SMTP-Proxys zu unterstützen. Getestet wurde jedoch nur ProxSMTP[43] als Middle-Proxy.

1 Listen: 127.0.0.1:20025 # Port für eingehende Verbindungen 2 OutAddress: 4001 # Port für ausgehende Verbindungen 3 TransparentProxy: off # kein Betrieb als transparenter Proxy 4 MaxConnections: 64 # Maximale Anzahl gleichzeitiger Verbindungen 5 KeepAlives: 30 # Senden von NOOP alle 30 Sekunden 6 FilterCommand: spamassassin.sh # Mails werden durch dieses Script gefiltert 7 FilterType: pipe # Mail werden per Pipe an das Skript übergeben 8 FilterTimeout: 1200 # maximale Laufzeit des Filterskripts Listing 9.8: Konfigurationsdatei für den Einsatz ProxSMTP als Middle-Proxy

Aus Zeile 1 ergeben sich folgenden Einstellungen für den TLS-Proxy, damit dieser den Middle- Proxy auf der Adresse 127.0.0.1:20025 erreichen kann: • MID_PROXY_ADDR = 127.0.0.1 • MID_PROXY_PORT = 20025. Da der TLS-Proxy auf PORT+1 auf TCP-Verbindungen des Middle-Proxys wartet, muss im Falle der Standardeinstellung (PORT = 4000) die Einstellung OutAddress des ProxSMTP auf 4001 gesetzt werden. Der TLS-Proxy sorgt selbst für die transparente Annahme der TCP- Verbindungen, deshalb darf der ProxSMTP nicht mehr als transparenter Proxy konfiguriert werden. Auch die Anzahl der gleichzeitigen Verbindungen und die Timeouts müssen im TLS-Proxy und im ProxSMTP aneinander angepasst werden. Die Option „KeepAlives: 30“ sendet alle 30 Sekunden ein NOOP-Kommando an den Server, um die SMTP-Verbindung aufrechtzuerhalten, während der Inhalt der Nachricht überprüft wird. Als FilterCommand können beliebige Content-Filter (z. B. Virenscanner, Spamfilter) verwendet werden. ProxSMTP unterstützt die Anbindung, indem der Mail-Inhalt per Pipe an den Filter übergeben oder in eine temporäre Datei geschrieben wird. Als Beispiel für die Anbindung dient spamassassin.sh aus Listing 9.9. Das Skript basiert auf einem von ProxSMTP mitgelieferten Skript.

1 #!/bin/sh 2 # Pipe mail through this command 3 spamassassin -e 9. Handbuch zur Systemintegration 104

4 # Now check return value 5 if [ $? -ne 0 ]; then 6 # The last line of output to stderr will be used 7 # as an error message when the filter fails 8 echo "550 Content Rejected: We don't like spam" >&2 9 # Cause the filter to fail, email will be rejected 10 exit 1 11 fi 12 # Filter success 13 exit 0

Listing 9.9: spamassassin.sh als Beispiel für die Anbindung eines Content-Filters

Andere Content-Filter, wie Virenscanner, können auf ähnliche Weise angebunden werden. Virenscanner sind jedoch meist auf das Überprüfen von Dateien ausgelegt und können keine Daten verarbeiten, die per Pipe übergeben werden. Für diesen Fall unterstützt der ProxSMTP die Option „FilterType: file“, mit der er den Inhalt der Nachricht in eine Datei speichert und den Namen (und den Pfad) der Datei in der Umgebungsvariablen EMAIL an den Content-Filter übergibt.

9.2 Konfiguration der Szenarien

Dieser Abschnitt beschreibt die Konfiguration der in Abschnitt 5.2 vorgestellten Einsatzszenari- en sowie die Abbildung im SMTPS-Proxy. Die verwendeten IP-Adressen sind entweder private Adressen laut RFC 1918[RMK+96] oder Adressen, die speziell zu Dokumentationszwecken oder für Beispiele reserviert sind (siehe RFC 5737[ACV10]). Die Grundkonfiguration aus Abschnitt 9.1.4 wird wie folgt konkretisiert.

9.2.1 Anpassen der Grundkonfiguration

Netzwerkkonfiguration des SMTPS-Proxy: • Internes Interface: eth0 10.0.0.1/24 • Externes Interface: eth1 198.51.100.10/24

1 iptables -t nat -A PREROUTING -p tcp --dport 25 -i eth0 -j REDIRECT --to-ports 4000 2 iptables -t nat -A PREROUTING -p tcp --dport 25 -i eth1 -j REDIRECT --to-ports 4000

Listing 9.10: IPTABLES-REDIRECT-Regeln für den SMTPS-Proxy

1 10.0.0.0/24

Listing 9.11: Inhalt der Datei SMTP_IP_LOCAL_LIST 9. Handbuch zur Systemintegration 105

internes Subnetz Internet 10.0.0.0/24

10.0.0.1 198.51.100.10

SMTPS-Proxy

Unternehmensgenze

Abbildung 9.1: Interne Clients verwenden beliebige externe Mailserver.

9.2.2 Interne Clients verwenden beliebige externe Mailserver

In diesem Szenario kann der Proxy einfach in der angepassten Grundkonfiguration betrieben werden. Soll zusätzlich eine Verschlüsselung erzwungen werden, gibt es folgende Möglichkeiten:

9.2.2.1 Vollständig erzwungene Verschlüsselung

In dieser Konfiguration erzwingt der Proxy sowohl auf Server-Seite als auch auf Client-Seite die Verwendung von STARTTLS. Konfiguration: • SMTP_FORCE_CLIENT_TLS_EXT = yes • SMTP_FORCE_SERVER_TLS_EXT = yes Wenn keine internen SMTP-Server vorhanden sind, ist es nicht nötig, die SMTP_IP_LOCAL- _LIST zu konfigurieren. Ohne diese Liste behandelt der Proxy alle Adressen, als wären sie extern. Aus diesem Grund ist es auch ausreichend, die FORCE-Optionen für extern zu setzen.

9.2.2.2 Einseitig erzwungene Verschlüsselung

Wenn ältere Client-Systeme ohne Unterstützung für STARTTLS zum Einsatz kommen, ist es möglich, die Verschlüsselung nur auf Server-Seite zu erzwingen. In diesem Fall ist der Weg vom Client bis zur Firewall unverschlüsselt und ab dort bis zum Server verschlüsselt. Clients merken davon nichts, können jedoch (falls sie es unterstützen) trotzdem eine STARTTLS-Session zur Firewall aufbauen. 9. Handbuch zur Systemintegration 106

Konfiguration: • SMTP_FORCE_CLIENT_TLS_EXT = no • SMTP_FORCE_SERVER_TLS_EXT = yes

9.2.3 Interne Mailserver empfangen Mails von externen Servern

internes Subnetz Internet 10.0.0.0/24

10.0.0.1 198.51.100.10

SMTPS-Proxy

Unternehmensgrenze

Abbildung 9.2: Interne Server empfangen Mails von externen Servern.

Zwar ist auch in diesem Szenario die Grundkonfiguration ausreichend, es kann jedoch sinnvoll sein, die Zertifikat der internen Server zu hinterlegen und zumindest auf dem Weg vom Proxy zum Server TLS zu erzwingen7.

9.2.3.1 Hinterlegung eines Zertifikates mit erzwungener interner Verschlüsse- lung

Das Generieren von Zertifikaten on-the-fly ist zwar für externe Server nötig, doch bei ei- nem internen Server ist es sinnvoller, dessen Zertifikat (und den Private-Key) am Proxy zu hinterlegen. Um den Empfang von externen Servern nicht zu behindern, wird in dieser Konfiguration TLS extern nicht erzwungen. Eine TLS-Session vom internen Server zu einem externen ist nur möglich, wenn dies auch der externe Server unterstützt. Konfiguration:

7Option: SMTP_FORCE_SERVER_TLS_INT = yes 9. Handbuch zur Systemintegration 107

•SMTP_FORCE_SERVER_TLS_INT = yes TLS zu internen Servern wird erzwungen •SMTP_FORCE_CLIENT_TLS_INT = no TLS von internen Clients ist optional •SMTP_FORCE_SERVER_TLS_EXT = no TLS zu externen Servern ist optional •SMTP_FORCE_CLIENT_TLS_EXT = no TLS von externen Clients ist optional

Der Proxy benutzt die in der in SMTP_IP_LOCAL_LIST festgelegten Datei enthaltenen IP-Adressen und Subnetze, um festzustellen, welche der SMTP_FORCE_... Regeln bei einer konkreten SMTP-Verbindung angewandt werden sollen (siehe Listing 9.11). In dieser Konfiguration muss zumindest die Adresse des internen Servers darin enthalten sein. Weiters muss sich in dem in CERT_DEPOSIT_PATH festgelegten Verzeichnis eine Datei mit dem Zertifikat und dem Private-Key befinden (Aufbau siehe Abschnitt 7.3, Beispiel siehe Listing 6.10). Die Hinterlegung des Private-Key ist nötig, um den TLS-Handshake mit dem hinterlegten Zertifikat durchführen zu können. Durch das Hinterlegen des Zertifikates überprüft der Proxy auch, ob das hinterlegte Zertifikat mit dem vom Server im TLS-Handshake präsentierten Zertifikat übereinstimmt. Ist dies nicht der Fall, wird die SMTP-Verbindung abgebrochen, um Man-in-the-middle-Attacken zu verhindern.

9.2.4 Interne Clients verbinden sich zum internen Server über den Proxy

Unternehmensgrenze

internes Subnetz Internet 10.0.0.0/24 SMTPS-Proxy

10.0.0.1

192.0.2.10

DMZ 192.0.2.20

198.51.100.20

Mailserver

Abbildung 9.3: Interne Clients verbinden sich über Proxy zum internen Server.

In diesem Szenario verwenden die internen Client keine externen Server, um Mails zu senden, sondern verbinden sich über den SMTPS-Proxy zu einem internen Server. Dazu ist 9. Handbuch zur Systemintegration 108 der Mailserver mit einem weiteren Interface des SMTPS-Proxy verbunden und befindet sich zum Beispiel in einer DMZ, wie es in Abbildung 9.3 ersichtlich ist: • Interface am SMTPS-Proxy: 192.0.2.10/24 • internes Interface des Mailservers: 192.0.2.20/24 • externes Interface des Mailservers: 198.51.100.20/24 Zusätzlich zur Konfiguration aus dem vorherigen Abschnitt (9.2.3.1) muss noch folgender Eintrag gesetzt werden, damit TLS von internen Clients erzwungen wird. Konfiguration: • SMTP_FORCE_CLIENT_TLS_INT = yes Der Rest der Konfiguration kann direkt übernommen werden. Dadurch ist es auch nicht mehr möglich, eine SMTP-Verbindung zu internen SMTP-Servern aufzubauen, die kein STARTTLS unterstützen. Das ist jedoch üblicherweise auch so gewünscht.

9.2.5 Zentraler SMTP-Relay-Server

Unternehmensgrenze

internes Subnetz Internet 10.0.0.0/24 SMTPS-Proxy

198.51.100.10 10.0.0.1

192.0.2.10

192.0.2.30

198.51.100.30 10.0.0.2

SMTP-Relay

Abbildung 9.4: Verwendung eines zentralen SMTP-Relays

Anstatt die Mails am Proxy nach Spam und Viren zu untersuchen, haben viele Firmen einen zentralen Relay-Server für diese Aufgabe eingerichtet. Das SMTP-Relay ist an ein Interface des SMTPS-Proxys angeschlossen, und stellt Mails direkt an externe oder interne Mailserver zu. Dadurch werden alle Mails die das Unternehmen verlassen, mithilfe des SMTPS-Proxy durch den Realy-Server geleitet. Eine besondere Konfiguration der Clients ist dazu nicht notwendig. 9. Handbuch zur Systemintegration 109

• Interface am SMTPS-Proxy: 192.0.2.10/24 • Proxy-Interface des SMTP-Relay: 192.0.2.30/24 • internes Interface des SMTP-Relay: 198.51.100.30 • externes Interface des SMTP-Relay: 10.0.0.2/24

9.2.5.1 Weiterleitung an zentralen Relay-Host

Um jenen SMTP-Datentransfer, der durch den Proxy geleitet wird, auf einen Relay-Host umzuleiten, ist folgende Konfiguration ausreichend: • SMTP_RELAY_ADDR = 192.0.2.30 • SMTP_RELAY_PORT = 25 Diese Konfiguration ermöglicht dem Client, zusätzlich eine TLS-Session bis zum Proxy aufzu- bauen. Dieser generiert, basierend auf dem Zertifikat des originalen Zielservers, ein On-the-fly- Zertifikat. Dazu muss der Proxy zu Beginn eine zusätzliche SMTP-Verbindung zum Zielserver aufbauen und einen TLS-Handshake (mit Hilfe von STARTTLS) beginnen. Da dies ausreicht, um das On-the-fly-Zertifikat zu erzeugen, wird die Verbindung zum Server wieder terminiert.

9.2.5.2 Erzwungene clientseitige Verschlüsselung

Die vorherige Konfiguration ermöglicht zwar eine TLS-Session des Clients, erzwingt sie aber nicht. Dies kann jedoch einfach durch folgende Konfigurationsoption aktiviert werden (zusätzlich zu den Optionen aus dem vorherigen Abschnitt). • SMTP_FORCE_CLIENT_TLS_INT = yes Die Datei SMTP_IP_LOCAL_LIST aus Listing 9.11 ist hier ebenfalls zu verwenden. Kapitel 10

Zusammenfassung und Ausblick

10.1 Zusammenfassung

Basierend auf theoretischen Grundlagen zu SMTP und SMTP-Proxys, wurden Möglichkeiten untersucht, um Email-Übertragungen an zentraler Stelle zu analysieren. Bestehende Lösungen sollten aber nicht nur die Analyse der Emails beherrschen, sondern auch trotz verschlüsselter Übertragung funktionieren. Diese Fähigkeit war, wenn überhaupt, nur eingeschränkt vorhanden. Aus diesem Grund wurde die Entscheidung für eine Eigenentwicklung getroffen. Als Basis für die Entwicklung eines SMTPS-Proxys diente die TLSProxy-Engine der Firma Underground_81, die Roman Aspetsberger im Rahmen seiner Masterarbeit [Asp09] erstellt hat. Der TLS-Proxy wurde für das Firewall-Produkt MF Security Gateway entwickelt, um die Analyse von HTTPS zu ermöglichen. Nachdem keine der bestehenden Lösungen die Anforderungen erfüllt, wurde der TLS-Proxy erweitert, um auch SMTP verwenden zu können. Zur Anbindung an die Content-Filter gegen Spam und Viren wurde eine bereits bestehende Lösung in einer Proxy-Chain verwendet. Der Entwurf sieht außerdem vor, die für den TLS-Proxy benötigte Zertifizierungsstelle auszulagern und als eigenständigen Dienst allen TLS-Proxys zur Verfügung zu stellen. Als Erweiterung wurden Möglichkeiten eingebaut, um die Verschlüsselung nicht nur zu ermöglichen, sondern bei Bedarf auch zu erzwingen. Viele Firmen verwenden einen Anti- Spam- oder Anti-Viren-Proxy, um ihren Mailserver abzuschirmen. In diesem Fall ist es vorteilhaft, das Zertifikat des Mailservers am Proxy zu hinterlegen, anstatt Zertifikate von der Zertifizierungsstelle erzeugen zu lassen. Die hier vorgestellte Implementierung unterstützt auch dieses Szenario. Das korrekte Verhalten des Proxys in Fehlerfällen und bei der Verwendung der Möglichkeiten zum Erzwingen der Verschlüsselung wurde sorgfältig überprüft. Diese Tests sind in Kapitel 8 dokumentiert. Ein weiteres Ergebnis dieser Arbeit ist ein Handbuch, das es Systemadministratoren

1http://www.underground8.com

110 10. Zusammenfassung und Ausblick 111 ermöglichen soll, den SMTPS-Proxy in ihre Systeme zu integrieren. Dazu gehört, neben der Dokumentation der Konfigurationsparameter, auch eine Beschreibung von möglichen Einsatzszenarien. Durch diese Arbeit wurde die Funktionalität eines Firewall-Produkts erweitert. Zusätzlich ist dadurch auch ein eigenständiger Betrieb als Proxy für verschlüsselte und unverschlüsselte SMTP-Verbindungen möglich.

10.2 Ausblick

Die Protokolle HTTP und SMTP sind natürlich nicht die einzigen, für die eine Untersuchung nach Spam oder Viren sinnvoll ist. Gerade weitere Protokolle aus dem Email-Umfeld, wie POP32 und IMAP3, sind hier interessant. Nachdem Emails nicht nur durch SMTP in das Netzwerk kommen, sollten auch andere Eintrittswege analysiert werden. Der TLS-Proxy bietet die Möglichkeit, eine Unterstützung für diese Protokolle hinzuzufügen, wobei auch hier besonders auf das Timing geachtet werden muss. Auch die Einbettung der Zertifizierungsstelle in vorhandene Zertifikatsstrukturen ist ein mögliches Thema für weitere Untersuchungen. Die verwendeten OpenSSL-Bibliotheken bieten zwar eine Unterstützung für die Protokoll- versionen SSLv2, SSLv3 und TLSv1, jedoch nicht für die Versionen TLSv1.1 oder TSL1.2. Eine Portierung auf eine andere Bibliothek, die neuere TLS-Versionen unterstützt4, kann deshalb sinnvoll sein.

2Post Office Protocol (Version 3) (POP3) 3Internet Message Access Protocol (IMAP) 4z. B. GnuTLS [25] Glossar

A Address Ressource Record im DNS ABNF Augmented Backus Naur Form

BNF Backus Naur Form

CDT C/C++ Development Tooling CR Carriage-Return

Daemon Dienst im Hintergrund DER Distinguished Encoding Rules DMZ De-militarisierte Zone DNS Domain Name System DoS Denial of Service DSN Delivery Status Notification

EGD Entropy Gathering Daemon EOM End Of Mail ESMTP Extended Simple Mail-Transfer-Protocol

FQDN Fully Qualified Domain Name = der vollständige Name einer Domain

GNU Ein rekursives Akronym für „GNU’s Not Unix!“ GPL GNU Public License

HAVP HTTP Anti Virus Proxy HT Horizontal Tabulator HTTP Hypertext Transfer Protocol

112 HTTPS Die verschlüsselte Variante des Hypertext Transfer Protocols

IDE Integrated Development Environment IMAP Internet Message Access Protocol IP Internet Protocol IPTABLES Kommandozeilenprogramm zur Konfiguration des Paketfilters des Linux 2.4.x bzw. Linux 2.6.x Kernels ITEISA Internet Telecomunicaciones e Ingeniería de Santander

LF Line-Feed LSB Least Significant Bit = niederwertigstes Bit

MDN Message Delivery Notification MIME Multipurpose Internet Mail Extensions MSB Most Significant Bit = höchstwertiges Bit MTAs Mail Transfer Agents MUAs Mail User Agents MX Mail eXchange Ressource Record im DNS

OTF On the Fly

PID Process ID POP3 Post Office Protocol (Version 3) POSIX Portable Operating System Interface rDNS Reverse DNS

SHA1 Secure Hash Algorithm, Version 1 SMTP Simple Mail Transfer Protocol SMTPS Die verschlüsselte Variante des Simple Mail Transfer Protocols SPF Sender Policy Framework SRS Sender Rewriting Scheme SSL Secure Sockets Layer STARTTLS Ermöglicht das Aushandeln von TLS-Verschlüsselung auf Klartextverbin- dungen

113 stderr Standard Filehandle für die Fehlerausgabe

TCP Transmission Control Protocol TLS Transport Layer Security TPROXY Transparent Proxy

URI Uniform Resource Identifier

114 Tabellenverzeichnis

2.1 Vorschläge für Mindestwerte von SMTP-Timeouts aus [Kle08]...... 16 2.2 Gemessene SMTP-Server-Timeout-Werte...... 17

3.1 SMTP-Proxy-Lösungen ...... 25

4.1 Zertifikat-Verifikationslevel im TLS-Proxy...... 34

5.1 Protokoll zur Kommunikation mit der Zertifizierungsstelle ...... 42

7.1 Syslog Message Severities. Aus [Ger09]...... 76

9.1 Software-Voraussetzungen für den TLS-Proxy ...... 99 9.2 Beschreibung der möglichen Optionen für den Aufruf des Configure-Skripts . . 99 9.3 Kommandozeilenparameter des TLS-Proxys ...... 100 9.4 Kommandozeilenparameter für CA...... 100

115 Abbildungsverzeichnis

2.1 Aufbau von Mail-Objects, die mit SMTP transportiert werden ...... 4

4.1 TLS-Verbindungsaufbau und Vertrauensverhältnisse ohne Proxy ...... 31 4.2 TLS-Verbindungsaufbau und Vertrauensverhältnisse mit (TLS-)Proxy . . . . . 32 4.3 Zertfikatserstellung im TLS-Proxy (privater Schlüssel: rot, öffentlicher Schlüssel: grün)[Asp09, Abbildung 4.3]...... 33

6.1 Klassenhierarchie der Protokoll-Handler ...... 47 6.2 SMTP-Verbindungsablauf ...... 49 6.3 Klassendiagramme ThreadPool, Proxy und PIO ...... 50 6.4 Klassendiagramme ConnectionTracker CertificateAuthority CATHread . . . . . 52 6.5 Ablauf: Übertragung der Connection-ID ...... 53 6.6 Kommunikationsstruktur ...... 61 6.7 Struktur des SMTP-Handlers ...... 61 6.8 Klassen zur Verwaltung von hinterlegten Zertifikaten ...... 71

8.1 Aufbau der Testumgebung ...... 86

9.1 Interne Clients verwenden beliebige externe Mailserver...... 105 9.2 Interne Server empfangen Mails von externen Servern...... 106 9.3 Interne Clients verbinden sich über Proxy zum internen Server...... 107 9.4 Verwendung eines zentralen SMTP-Relays ...... 108

116 Quellcodeverzeichnis

2.1 SMTP-Client identifiziert sich mit dem HELO-Kommando ...... 7 2.2 SMTP-Client identifiziert sich mit dem EHLO-Kommando ...... 7 2.3 Spezifikation des Absenders mit dem MAIL-Kommando ...... 7 2.4 Spezifikation der Absender mit dem RCPT-Kommando ...... 8 2.5 Einleitung der Mail-Daten-Übertragung mit dem DATA-Kommando ...... 8 2.6 Abbruch der Transaktion mit dem RSET-Kommando ...... 8 2.7 Absenden eines Kommandos, das sich nicht auf die Transaktion auswirkt: NOOP 9 2.8 Beenden der SMTP-Sitzung mit dem QUIT-Kommando ...... 9 2.9 Überprüfung mit dem VRFY-Kommando, ob ein User oder eine Mailbox auf dem Server existieren ...... 9 2.10 Mögliche Antwort auf das EHLO-Kommando ...... 10 2.11 Begrüßung des Servers nach dem TCP-Verbindungsaufbau ...... 10 2.12 Antwort auf das DATA-Kommando ...... 11 2.13 Antwort des Servers, wenn nicht genug Speicherplatz zur Verfügung steht . . . 11 2.14 Antwort des Servers, wenn ihm ein Kommando zwar bekannt ist, aber nicht unterstützt wird...... 11 2.15 Antwort des Servers, wenn ein zu langes Kommando empfangen wurde . . . . . 11 2.16 Antwort des Servers auf das HELP-Kommando ...... 11 2.17 Antwort des Servers auf das QUIT-Kommando ...... 12 2.18 Antwort des Servers auf das VRFY-Kommando ...... 12 2.19 Beispiel für den Ablauf einer SMTP-Sitzung ...... 12 2.20 Beispielablauf einer abgebrochenen SMTP-Sitzung ...... 13 2.21 Beispiel für MX- und A-Einträge im DNS für mehrere DNS-Server ...... 14 2.22 Beispiel für einen Mail-Header ...... 15 2.23 Grobe Messung der SMTP-Server-Timeouts ...... 16 4.1 Setzen der OpenSSL Callbacks, für die Verwendung in Multi-Threaded-Umgebungen. 28 4.2 Locking-Callback-Funktionen für OpenSSL ...... 28 6.1 Auslesen der originalen Zieladresse aus der Netfilter-Tabelle ...... 51 6.2 Aufbau des Zertifikatsspeichers ...... 55 6.3 Installieren eines Signal-Handlers ...... 56

117 6.4 Blockieren aller Signale an einen Thread ...... 57 6.5 Versetzen eines Sockets in den Blocking- oder Non-Blocking-Modus ...... 60 6.6 Multiplex-I/O mit waitOnEvent ...... 62 6.7 Warten auf Beendigung des serverseitigen TLS-Handshake mit Pthread-Conditions 67 6.8 Tunneln von TCP-Verbindungen durch den Proxy ...... 68 6.9 Definition der CertEntry-Map ...... 71 6.10 Beispiel für eine Zertifikatsdatei ...... 72 6.11 Vergleichen der Zertifikate und Erzeugen eines neuen SSL-Client-Context . . . 73 7.1 Beispiel für eine Whitelist-Datei: white.ip ...... 78 7.2 Beispiel für eine Blacklist-Datei: black.ip ...... 78 7.3 Beispiel für eine Whitelist-Datei: white.host ...... 80 7.4 Beispiel für eine Blacklist-Datei: black.host ...... 80 7.5 Beispiel für die Datei: local.ip ...... 82 7.6 Aufbau einer Datei des Zertifikatsspeichers ...... 82 8.1 Senden einer Testnachricht mit swaks ...... 88 8.2 Überprüfung, welche ESMTP-Features der Proxy erlaubt ...... 89 8.3 Senden einer Nachricht unter Verwendung von STARTTLS mit swaks . . . . . 90 8.4 Überprüfung des Zertifikats mit OpenSSL ...... 90 8.5 Testen der Reaktion beim Senden von STARTTLS bei Servern ohne STARTTLS- Unterstützung ...... 91 8.6 Test, ob das hinterlegte Zertifikat verwendet wird ...... 92 8.7 Erkennen von gefälschten Zertifikaten ...... 92 8.8 Testen der Relay-Funktionalität mit und ohne STARTTLS ...... 93 9.1 Übersetzen des Quelltextes ...... 99 9.2 Übersetzen der statischen OpenSSL-Bibliotheken ...... 101 9.3 Änderungen in Datei configure.ac ...... 101 9.4 Änderungen in Datei src/Makefile.am ...... 101 9.5 Änderungen in Datei src/ca/Makefile.am ...... 101 9.6 Allgemeine Form für IPTABLES-REDIRECT ...... 102 9.7 IPTABLES-REDIRECT-Regeln für die Umleitung des SMTP-Datenverkehrs . 102 9.8 Konfigurationsdatei für den Einsatz ProxSMTP als Middle-Proxy ...... 103 9.9 spamassassin.sh als Beispiel für die Anbindung eines Content-Filters ...... 103 9.10 IPTABLES-REDIRECT-Regeln für den SMTPS-Proxy ...... 104 9.11 Inhalt der Datei SMTP_IP_LOCAL_LIST ...... 104

118 Literaturverzeichnis

[ACD+07] Allman, E., J. Callas, M. Delany, M. Libbey, J. Fenton und M. Thomas: Domain- Keys Identified Mail (DKIM) Signatures. RFC 4871 (Proposed Standard), Mai 2007. http://www.ietf.org/rfc/rfc4871.txt, Updated by RFC 5672.

[ACV10] Arkko, J., M. Cotton und L. Vegoda: IPv4 Address Blocks Reserved for Documenta- tion. RFC 5737 (Informational), Januar 2010. http://www.ietf.org/rfc/rfc5737.txt.

[Asp09] Aspetsberger, Roman: Trusted Person in the Middle: TLS-Proxy. Masterarbeit, Johannes Kepler Universität Linz, 2009.

[Bra89] Braden, R.: Requirements for Internet Hosts - Application and Support. RFC 1123 (Standard), Oktober 1989. http://www.ietf.org/rfc/rfc1123.txt, Updated by RFCs 1349, 2181, 5321, 5966.

[CB94] Cheswick, William R. und Steven M. Bellovin: Firewalls and Internet Security: Repelling The Wily Hacker. Addison-Wesley Professional, 1994, ISBN 0201633574.

[CDF+07] Callas, J., L. Donnerhacke, H. Finney, D. Shaw und R. Thayer: OpenPGP Message Format. RFC 4880 (Proposed Standard), November 2007. http://www.ietf.org/rfc/ rfc4880.txt, Updated by RFC 5581.

[Cer69] Cerf, V.G.: ASCII format for network interchange. RFC 20, Oktober 1969. http: //www.ietf.org/rfc/rfc20.txt.

[CO08] Crocker, D. und P. Overell: Augmented BNF for Syntax Specifications: ABNF. RFC 5234 (Standard), Januar 2008. http://www.ietf.org/rfc/rfc5234.txt.

[Cro82] Crocker, D.: STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES. RFC 822 (Standard), August 1982. http://www.ietf.org/rfc/rfc822.txt, Obsoleted by RFC 2822, updated by RFCs 1123, 2156, 1327, 1138, 1148.

[CSF+08] Cooper, D., S. Santesson, S. Farrell, S. Boeyen, R. Housley und W. Polk: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. RFC 5280 (Proposed Standard), Mai 2008. http://www.ietf.org/rfc/rfc5280. txt.

119 [DR08] Dierks, T. und E. Rescorla: The Transport Layer Security (TLS) Protocol Version 1.2. RFC 5246 (Proposed Standard), August 2008. http://www.ietf.org/rfc/rfc5246. txt, Updated by RFCs 5746, 5878, 6176.

[Fre00] Freed, N.: SMTP Service Extension for Command Pipelining. RFC 2920 (Standard), September 2000. http://www.ietf.org/rfc/rfc2920.txt.

[Ger09] Gerhards, R.: The Syslog Protocol. RFC 5424 (Proposed Standard), März 2009. http://www.ietf.org/rfc/rfc5424.txt.

[Hof02] Hoffman, P.: SMTP Service Extension for Secure SMTP over Transport Layer Security. RFC 3207 (Proposed Standard), Februar 2002. http://www.ietf.org/rfc/ rfc3207.txt.

[Hun02] Hunt, Craig: TCP/IP Network Administration. O’Reilly Media, 3. Auflage, 2002, ISBN 0596002971.

[HV04] Hansen, T. und G. Vaudreuil: Message Disposition Notification. RFC 3798 (Draft Standard), Mai 2004. http://www.ietf.org/rfc/rfc3798.txt, Updated by RFC 5337.

[IG04] IEEE, The und The Open Group: The open group base specifications, issue 6, 2004.

[KFRC11] Klensin, J., N. Freed, M. Rose und D. Crocker: SMTP Service Extension for 8-bit MIME Transport. RFC 6152 (Standard), März 2011. http://www.ietf.org/rfc/ rfc6152.txt.

[Kle08] Klensin, J.: Simple Mail Transfer Protocol. RFC 5321 (Draft Standard), Oktober 2008. http://www.ietf.org/rfc/rfc5321.txt.

[Moc87] Mockapetris, P.V.: Domain names - implementation and specification. RFC 1035 (Standard), November 1987. http://www.ietf.org/rfc/rfc1035.txt, Updated by RFCs 1101, 1183, 1348, 1876, 1982, 1995, 1996, 2065, 2136, 2181, 2137, 2308, 2535, 2845, 3425, 3658, 4033, 4034, 4035, 4343, 5936, 5966.

[Moo03] Moore, K.: Simple Mail Transfer Protocol (SMTP) Service Extension for Delivery Status Notifications (DSNs). RFC 3461 (Draft Standard), Januar 2003. http: //www.ietf.org/rfc/rfc3461.txt, Updated by RFCs 3798, 3885, 5337.

[MV03] Moore, K. und G. Vaudreuil: An Extensible Message Format for Delivery Status Notifications. RFC 3464 (Draft Standard), Januar 2003. http://www.ietf.org/rfc/ rfc3464.txt, Updated by RFCs 4865, 5337.

120 [Nat08] National Institute of Standards and Technology (NIST): Federal information processing standards publication 180-3: Secure hash standard (SHS), 2008. http: //csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.

[Par86] Partridge, C.: Mail routing and the domain system. RFC 974 (Historic), Januar 1986. http://www.ietf.org/rfc/rfc974.txt, Obsoleted by RFC 2821.

[Poh01] Pohlmann, Norbert: Firewall Systems. mitp, 2001, ISBN 9783826607547.

[Pos82] Postel, J.: Simple Mail Transfer Protocol. RFC 821 (Standard), August 1982. http://www.ietf.org/rfc/rfc821.txt, Obsoleted by RFC 2821.

[Ram04] Ramsdell, B.: Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.1 Message Specification. RFC 3851 (Proposed Standard), Juli 2004. http: //www.ietf.org/rfc/rfc3851.txt, Obsoleted by RFC 5751.

[Res00] Rescorla, E.: HTTP Over TLS. RFC 2818 (Informational), Mai 2000. http: //www.ietf.org/rfc/rfc2818.txt, Updated by RFC 5785.

[Res01] Rescorla, E.: SSL and TLS : designing and building secure systems. Addison-Wesley, Boston, 2001, ISBN 0201615983.

[Res08] Resnick, P.: Internet Message Format. RFC 5322 (Draft Standard), Oktober 2008. http://www.ietf.org/rfc/rfc5322.txt.

[RMK+96] Rekhter, Y., B. Moskowitz, D. Karrenberg, G. J. de Groot und E. Lear: Address Allocation for Private Internets. RFC 1918 (Best Current Practice), Februar 1996. http://www.ietf.org/rfc/rfc1918.txt.

[Sch06] Schneier, Bruce: Angewandte Kryptographie - Der Klassiker. Protokolle, Algorith- men und Sourcecode in C. Pearson Studium, 2006, ISBN 3827372283.

[SM07] Siemborski, R. und A. Melnikov: SMTP Service Extension for Authentication. RFC 4954 (Proposed Standard), Juli 2007. http://www.ietf.org/rfc/rfc4954.txt, Updated by RFC 5248.

[Ste92] Stevens, William Richard: Programmieren von UNIX-Netzen : Grundla- gen, Programmierung, Anwendung. Hanser [u.a.], München [u.a.], 1992, ISBN 9783446163188.

[Ste94] Stevens, William Richard: TCP/IP Illustrated, Volume 1 The Protocols. Addison- Wesley Professional, 1994, ISBN 0201633469.

[Ste95] Stevens, William Richard: Programmierung in der UNIX-Umgebung: die Referenz für Fortgeschrittene. Addison-Wesley, 1995, ISBN 3-89319-814-8.

121 [Tan98] Tanenbaum, Andrew S.: Computernetzwerke. Prentice Hall, 3. Auflage, 1998, ISBN 3-8272-9568-8.

[Won03] Wong, Meng Weng: Sender rewriting scheme, 2003. http://www.openspf.org/svn/ project/specs/drafts/draft-mengwong-sender-rewrite-01.txt.

[WS06] Wong, M. und W. Schlitt: Sender Policy Framework (SPF) for Authorizing Use of Domains in E-Mail, Version 1. RFC 4408 (Experimental), April 2006. http: //www.ietf.org/rfc/rfc4408.txt.

[Zie03] Ziegler, Robert L.: Linux-Firewalls. Markt und Technik, 2. Auflage, 2003, ISBN 9783827267030.

122 Internetquellen

[1] The project. http://spamassassin.apache.org/, besucht: 29.12.2010.

[2] ASSP - Anti-Spam SMTP Proxy. http://assp.sf.net/, besucht: 19.12.2010.

[3] ASSP PenaltyBox. http://sourceforge.net/apps/mediawiki/assp/index.php?title=Penalty_ Box, besucht: 29.12.2010.

[4] avast! Linux / Unix Edition. http://www.avast.com/de-de/linux-unix-edition, besucht: 2.1.2011.

[5] Backscatter (e-mail) - Wikipedia, the free encyclopedia. http://en.wikipedia.org/wiki/ Backscatter_(e-mail), besucht: 12.6.2011.

[6] Barricade MX smtpf/2.3 An SMTP Filtering Proxy. http://www.snertsoft.com/smtp/ smtpf/, besucht: 19.12.2010.

[7] Bayesian spam filtering. http://en.wikipedia.org/wiki/Bayesian_spam_filtering, besucht: 29.12.2010.

[8] Boost C++ Libraries. http://www.boost.org/, besucht: 4.6.2011.

[9] Clam AntiVirus. http://www.clamav.net/lang/en/download/sources/, besucht: 2.1.2011.

[10] ClamSMTP: An SMTP Virus Filter. http://thewalter.net/stef/software/clamsmtp/, be- sucht: 15.1.2011.

[11] Eclipse - The Eclipse Foundation open source community website. http://www.eclipse.org, besucht: 19.2.2011.

[12] Eclipse CDT. http://www.eclipse.org/cdt/, besucht: 19.2.2011.

[13] Exim Internet Mailer. http://www.exim.org/, besucht: 9.1.2011.

[14] GCC, GNU compiler collection. http://gcc.gnu.org/mirrors.html, besucht: 19.9.2010.

[15] Git Fast Version Control System. http://git-scm.com/, besucht: 16.4.2011.

123 [16] git.develooper.com – plugins/tls/. http://git.develooper.com/?p=qpsmtpd.git;a=blob;f= plugins/tls, besucht: 15.1.2011.

[17] git.develooper.com – plugins/virus/. http://git.develooper.com/?p=qpsmtpd.git;a=tree;f= plugins/virus;hb=HEAD, besucht: 10.1.2011.

[18] glibc, GNU C library. http://ftp.gnu.org/gnu/glibc/, besucht: 19.9.2010.

[19] GNU autoconf. http://ftp.gnu.org/gnu/autoconf/, besucht: 19.9.2010.

[20] GNU automake. http://ftp.gnu.org/gnu/automake/, besucht: 19.9.2010.

[21] GNU binutils. http://ftp.gnu.org/gnu/binutils/, besucht: 19.9.2010.

[22] The GNU Bourne-Again Shell. http://tiswww.case.edu/php/chet/bash/bashtop.html, be- sucht: 23.1.2011.

[23] GNU libtool. http://ftp.gnu.org/gnu/libtool/, besucht: 19.9.2010.

[24] GNU make. http://ftp.gnu.org/gnu/make/, besucht: 19.9.2010.

[25] The GNU Transport Layer Security Library. http://www.gnu.org/software/gnutls/, besucht: 23.10.2011.

[26] Greylisting whitepaper. http://www.greylisting.org/articles/whitepaper.shtml, besucht: 29.12.2010.

[27] HAVP - HTTP Anti Virus Proxy - the web antivirus solution. http://www.server-side.de/, besucht: 3.10.2010.

[28] Hermes Antispam Proxy. http://www.hermes-project.com, besucht: 19.12.2010.

[29] Information technology – ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER). http: //www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf, besucht: 17.5.2012.

[30] ITEISA Desarrollo web Cantabria. http://www.iteisa.com, besucht: 30.12.2010.

[31] LFS Project Homepage. http://www.linuxfromscratch.org/lfs/, besucht: 23.1.2011.

[32] linux kernel v2.4. http://www.kernel.org/pub/linux/kernel/v2.4/, besucht: 19.9.2010.

[33] milter.org, an interactive catalog of sendmail mail filters. milter.org, besucht: 10.1.2011.

[34] netfilter/iptables project. http://www.netfilter.org/projects/iptables/index.html, besucht: 25.9.2010.

124 [35] Open Source Initiative OSI - The MIT License:Licensing. http://www.opensource.org/ licenses/mit-license.php, besucht: 9.1.2011.

[36] OpenSSL: Documents, bio_read(3)). http://www.openssl.org/docs/crypto/BIO_read.html, besucht: 7.5.2011.

[37] OpenSSL: Documents, s_client(1). http://www.openssl.org/docs/apps/s_client.html, be- sucht: 26.6.2011.

[38] OpenSSL: Documents, threads(3)). http://www.openssl.org/docs/crypto/threads.html, besucht: 17.10.2010.

[39] OpenSSL toolkit. http://www.openssl.org/source, besucht: 19.9.2010.

[40] The Perl programming language. http://www.perl.org/, besucht: 29.12.2010.

[41] POSIX draft capabilities. http://www.kernel.org/pub/linux/libs/security/linux-privs/ libcap1/, besucht: 19.9.2010.

[42] Products Overview - F-PROT Antivirus Products. http://www.f-prot.com/products/ corporate_users/unix/, besucht: 2.1.2011.

[43] ProxSMTP: an SMTP Filter. http://memberwebs.com/stef/software/proxsmtp/, besucht: 3.10.2010.

[44] qmail: the Internet’s MTA of choice. http://cr.yp.to/qmail.html, besucht: 9.1.2011.

[45] qpsmtpd. http://smtpd.develooper.com/, besucht: 2.1.2011.

[46] SnertSoft We Server Your Server. http://www.snertsoft.com/about.php, besucht: 2.1.2011.

[47] Sophos Documentation - Anti-Virus for Linux. http://www.sophos.com/support/docs/ Sophos_Anti_Virus-Linux.html, besucht: 2.1.2011.

[48] squid: Optimising web delivery. http://www.squid-cache.org, besucht: 3.10.2010.

[49] SquidGuard. http://www.squidguard.org, besucht: 3.10.2010.

[50] Stunnel – Universal SSL Wrapper. http://www.stunnel.org, besucht: 17.1.2011.

[51] The Postfix Home Page. http://www.postfix.org/start.html, besucht: 9.1.2011.

[52] TPROXY - Portable Transparent Proxy Solution. http://www.balabit.com/support/ community/products/tproxy, besucht: 13.6.2011.

[53] TPROXY patches. http://www.balabit.com/downloads/files/tproxy/, besucht: 19.9.2010.

125 [54] Hallyn, Serge E.: POSIX file capabilities: Parceling the power of root. http://www.ibm. com/developerworks/library/l-posixcap.html, besucht: 19.9.2010.

[55] Jetmore, John: swaks - Swiss Army Knife SMTP. http://www.jetmore.org/john/code/ swaks/, besucht: 26.6.2011.

[56] McAfee Labs: McAfee Threats Report: Second Quarter 2011. http://www.mcafee.com/us/ resources/reports/rp-quarterly-threat-q2-2011.pdf, besucht: 16.10.2011.

[57] Thorpe, Geoff: Re: Clarification questions on OpenSSL thread-safe support. http://www. mail-archive.com/[email protected]/msg52127.html, besucht: 13.6.2011.

126 Michael Grundmann Bakk.techn. Geboren 1983 in Linz

Ausbildung 1997–2002 Matura (mit gutem Erfolg), HTBLA-Leonding Abteilung EDV und Organisation, Leonding. 2002–2004 BSc Computing Science, Universtity of Derby in Austria (UDA). 2006–2008 Bakk.techn. Informatik, Johannes Kepler Universität, Linz. seit 2008 Netzwerke und Sicherheit, Johannes Kepler Universität, Linz. Berufserfahrung 2002–2006 System und Netzwerkadministrator, HTBLA-Leonding. { Betreuung von ca. 25 Servern und 300 Workstations in einem heterogenen Umfeld (Linux, Windows, div. Unix Systeme, Novell). { darunter Mailserver, Samba Domain Controller, Nameserver, DHCP, div andere Dienste. { Netzwerkadministration: Cisco, HP und SMC Switches, Cisco PIX Firewall. { Datenbankadministration: Oracle, MySQL { Technischer Support für Verwaltung, Lehrer und Schüler sowie bei Veranstaltungen 2005–2006 Zivildiener, Arbeiter-Samariterbund Österreich Gruppe Bad Ischl, Dienststelle Traun. { Fahrer/Begleiter bei Schülertransporten und Transporten für Menschen mit Beeinträchtigungen. 2006–2010 Lehrer, HTBLA-Leonding. Werkstättenlabor Computer (WLA) { Hardwarenahe Computergrundlagen { Elektronik Grundlagen { Praxis Windows und Linux 2007–2008 Systemadministrator, Dr. Gerhard Mitter. { Betreuung des EDV-Systems der Ordination { Umzug der gesamten EDV-Infrastruktur der Aidshilfe Oberösterreich in ein neues Büro 2008–2011 Systemadministrator, Österreichische HochschülerInnenschaft and der Johannes Kepler Universität, Linz. { Domain Controller: Linux (Samba) { Clients: Windows, Linux { Mailserver, Webserver: FreeBSD seit 2010 Systemadministrator, Institut Hartheim, Alkoven. { Betreuung der EDV-Infrastruktur am Hauptstandort und 18 Aussenstellen { Betreute Systeme: Windows, Linux, Solaris, OpenBSD { darunter Mailserver (Groupwise, Postfix), Domain Controller (Server 2008 R2), Virtualisierung (VMWare, Hyper-V), Terminalserver, Citrix { IP-Telefonie { Netzwerkadministration: Cisco { Datenbankadministration: MS-SQLServer, MySQL { Technischer Support für ca 700 Mitarbeiter { Durchführung von IT-Projekten Erklärung

Ich erkläre an Eides statt, dass ich die vorliegende Masterarbeit selbstständig und ohne fremde Hilfe verfasst, andere als die angegebenen Quellen und Hilfsmittel nicht benutzt bzw. die wörtlich oder sinngemäß entnommenen Stellen als solche kenntlich gemacht habe. Die vorliegende Masterarbeit ist mit dem elektronisch übermittelten Textdokument identisch.