Untersuchung von verschlüsselter E-Mail- Kommunikation

Transcription

Untersuchung von verschlüsselter E-Mail- Kommunikation
JOHANNES KEPLER
UNIVERSITÄT LINZ
Technisch-Naturwissenschaftliche
Fakultät
Untersuchung von verschlüsselter E-MailKommunikation 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ür Informationsverarbeitung und Mikroprozessortechnik
Beurteilung:
O.Univ.-Prof. Dr. Jörg R. Mühlbacher
Assoz.Prof. Mag. iur. Dipl.-Ing. Dr. Michael Sonntag
Mitwirkung:
Dipl.-Ing. Dr. Rudolf Hörmanseder
Linz, September 2012
JKU
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üsselung 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 .
1
http://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 Ausgangslage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Gliederung der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 Das Simple Mail Transfer Protocol
2.1 Aufbau des Simple Mail Transfer Protocol . . . . . .
2.1.1 Ablauf einer SMTP-Session . . . . . . . . . .
2.1.2 Ende einer SMTP-Session . . . . . . . . . . .
2.1.3 Behandlung des end of mail-Indikators . . . .
2.1.4 SMTP-Kommandos . . . . . . . . . . . . . .
2.1.5 SMTP Return Codes . . . . . . . . . . . . . .
2.1.6 Bespiele für den Ablauf von SMTP-Sitzungen
2.1.7 Verlässlichkeit . . . . . . . . . . . . . . . . . .
2.1.8 Mail-Routing . . . . . . . . . . . . . . . . . .
2.1.9 Timeouts . . . . . . . . . . . . . . . . . . . .
2.2 SMTP-Proxy . . . . . . . . . . . . . . . . . . . . . .
2.3 Proxy-Unterstützung für (E-)SMTP-Funktionalität .
2.4 SMTP-Proxy vs. Relay . . . . . . . . . . . . . . . . .
2.4.1 Regelung des Zugriffs . . . . . . . . . . . . .
2.4.2 Verantwortlichkeit für Mail-Nachrichten . . .
2.4.3 Verwaltung einer Warteschlange . . . . . . .
2.5 STARTTLS-Erweiterung . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
4
5
6
6
10
12
13
14
16
17
18
18
18
19
19
19
3 Vorhandene SMTP-Proxy-Lösungen
3.1 ProxSMTP/ClamSMTP . . . . . . . . .
3.2 Anti-Spam-SMTP-Proxy-Server (ASSP)
3.3 Hermes . . . . . . . . . . . . . . . . . .
3.4 BarricadeMX . . . . . . . . . . . . . . .
3.5 qpsmtpd . . . . . . . . . . . . . . . . . .
3.6 Evaluation . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
22
22
22
23
23
24
25
4 TLS-Proxy-Engine von Underground_8
4.1 Aufbau des TLS-Proxy . . . . . . . . . .
4.1.1 Multithreading . . . . . . . . . .
4.1.2 Anbindung der Content-Filter . .
4.1.3 Verbindungsablauf . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
27
27
30
30
iv
Inhaltsverzeichnis
4.2
4.1.4 Zertifikate . . . . . . . . . . . . . . . . . .
4.1.5 Erweiterbarkeit für weitere Protokolle . .
4.1.6 Der TPROXY-Patch . . . . . . . . . . . .
Erweiterung des TLS-Proxy . . . . . . . . . . . .
4.2.1 RFC-konforme Fehlermeldungen . . . . .
4.2.2 Gemeinsam genutzte Zertifizierungsstelle
4.2.3 Relay . . . . . . . . . . . . . . . . . . . .
4.2.4 Erzwingen von TLS . . . . . . . . . . . .
4.2.5 Hinterlegen von Zertifikaten . . . . . . . .
v
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
33
34
35
35
35
36
36
36
37
5 Entwurf
5.1 Aufgabenstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Einsatzszenarien . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.1 Interne Clients verwenden beliebige externe Mailserver . . .
5.2.2 Interne Mailserver empfangen Mails von externen Servern .
5.2.3 TLS-Sessions trotz fehlender TLS-Unterstützung am Server
5.2.4 Zentraler SMTP-Relay-Server . . . . . . . . . . . . . . . . .
5.3 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.1 Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.2 Zertifizierungsstelle . . . . . . . . . . . . . . . . . . . . . . .
5.3.3 Anbindung der Content-Filter . . . . . . . . . . . . . . . . .
5.3.4 TLS-Funktionalität . . . . . . . . . . . . . . . . . . . . . . .
5.3.5 Relay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.6 Black-/Whitelists . . . . . . . . . . . . . . . . . . . . . . . .
5.3.7 Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . .
5.3.8 Behandlung von Timeouts . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
38
38
39
39
40
40
40
41
41
41
41
43
44
44
44
45
6 Implementierung
6.1 Entwicklungsumgebung . . . . . . . . . . . . . . . .
6.2 Verwendete Bibliotheken . . . . . . . . . . . . . . . .
6.3 Einbindung der SMTP-Funktionalität . . . . . . . .
6.4 Verbindungsablauf im TLS-Proxy . . . . . . . . . . .
6.4.1 Verwaltung von Sockets und TLS-Session . .
6.4.2 Threads . . . . . . . . . . . . . . . . . . . . .
6.4.3 Proxy-Objekte . . . . . . . . . . . . . . . . .
6.4.4 Connection Tracking . . . . . . . . . . . . . .
6.5 Ausgelagerte Zertifizierungsstelle . . . . . . . . . . .
6.5.1 Kernfunktionalität der Zertifizierungsstelle .
6.5.2 Initialisierung . . . . . . . . . . . . . . . . . .
6.5.3 Signalbehandlung . . . . . . . . . . . . . . . .
6.5.4 Threadverwaltung in der Zertifizierungsstelle
6.6 Blocking vs. Non-Blocking I/O . . . . . . . . . . . .
6.6.1 Multiplexing-I/O mit select . . . . . . . . .
6.6.2 OpenSSL und Non-Blocking-Sockets . . . . .
6.6.3 Verwendung im TLS-Proxy . . . . . . . . . .
6.7 Protokollhandler für SMTP . . . . . . . . . . . . . .
6.7.1 Struktur des SMTP-Handlers . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
46
46
46
47
48
48
49
50
51
53
54
55
56
57
58
59
59
60
61
61
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Inhaltsverzeichnis
6.8
vi
6.7.2 SMTP-Data und SMTP-Dialog . . . . .
6.7.3 Multiplex-I/O . . . . . . . . . . . . . . .
6.7.4 Limits . . . . . . . . . . . . . . . . . . .
6.7.5 Behandlung von Verbindungsabbrüchen
6.7.6 Behandlung von STARTTLS . . . . . .
6.7.7 Relay . . . . . . . . . . . . . . . . . . .
6.7.8 Weiterleitung ohne Untersuchung . . . .
6.7.9 Behandlung sonstiger Kommandos . . .
Hinterlegung von Zertifikaten . . . . . . . . . .
6.8.1 Verwaltung der hinterlegten Zertifikate .
6.8.2 Aufbau einer Zertifikatsdatei . . . . . .
6.8.3 Verwendung . . . . . . . . . . . . . . . .
7 Konfigurationsoptionen
7.1 Allgemeine Optionen . . . . . . . . .
7.2 SSL/TLS-Optionen . . . . . . . . . .
7.3 SMTP Optionen . . . . . . . . . . .
7.4 Optionen für die Zertifizierungsstelle
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
62
62
63
63
64
67
68
69
70
70
71
72
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
75
75
78
81
83
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
85
85
85
85
86
87
87
88
89
89
90
90
91
91
91
92
93
93
93
94
94
94
94
95
95
96
8 Tests
8.1 Testwerkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.1 swaks . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.2 OpenSSL s_client . . . . . . . . . . . . . . . . . . . . . .
8.2 Testumgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.3 Non-TLS-Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.3.1 Grundlegender Test des Mail-Versands . . . . . . . . . . .
8.3.2 Filtern von SMTP-Kommandos und Antworten . . . . . .
8.4 TLS-Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.4.1 Grundlegender TLS-Test . . . . . . . . . . . . . . . . . .
8.4.2 STARTTLS mit On-The-Fly-Zertifikat . . . . . . . . . . .
8.4.3 Server kündigt keine STARTTLS-Unterstützung an . . . .
8.4.4 Server präsentiert ungültiges oder abgelaufenes Zertifikat
8.4.5 CA ist nicht erreichbar . . . . . . . . . . . . . . . . . . . .
8.4.6 STARTTLS mit hinterlegtem Zertifikat . . . . . . . . . .
8.4.7 Relay zu mailrelay.test.underground8.com . . . . . . . . .
8.5 Pass-Through . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.5.1 Konfigurationsparameter . . . . . . . . . . . . . . . . . . .
8.5.2 Erwartete Funktionalität . . . . . . . . . . . . . . . . . .
8.5.3 IP in Whitelist . . . . . . . . . . . . . . . . . . . . . . . .
8.5.4 Hostname in Whitelist . . . . . . . . . . . . . . . . . . . .
8.5.5 Client-Zertifikate . . . . . . . . . . . . . . . . . . . . . . .
8.6 Forced-TLS-Tests . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.6.1 Konfigurationsparameter . . . . . . . . . . . . . . . . . . .
8.6.2 Serverseitiges Erzwingen von TLS . . . . . . . . . . . . .
8.6.3 Clientseitiges Erzwingen von TLS . . . . . . . . . . . . .
9 Handbuch zur Systemintegration
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
98
Inhaltsverzeichnis
9.1
9.2
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.1.1 Softwareabhängigkeiten . . . . . . . . . . . . . . . . . . . . . . . .
9.1.2 Installation auf einem Linux-System . . . . . . . . . . . . . . . . .
9.1.3 Statisches Linken der OpenSSL-Bibliotheken . . . . . . . . . . . .
9.1.4 Grundkonfiguration . . . . . . . . . . . . . . . . . . . . . . . . . .
Konfiguration der Szenarien . . . . . . . . . . . . . . . . . . . . . . . . . .
9.2.1 Anpassen der Grundkonfiguration . . . . . . . . . . . . . . . . . .
9.2.2 Interne Clients verwenden beliebige externe Mailserver . . . . . . .
9.2.3 Interne Mailserver empfangen Mails von externen Servern . . . . .
9.2.4 Interne Clients verbinden sich zum internen Server über den Proxy
9.2.5 Zentraler SMTP-Relay-Server . . . . . . . . . . . . . . . . . . . . .
vii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
98
98
98
100
101
104
104
105
106
107
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 Verschlü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: TLSProxy“ [Asp09] einen Lösungsansatz vor, der von der Firma Underground_8 als TLS-ProxyLö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
1
Ermö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 SMTPProtokolls, 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 SMTPUnterstü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 Entwicklungswerkzeuge 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 Verhalten 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 SMTPSProxy und zur Integration in konkrete Einsatzszenarien.
2
Die 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 Statusinformationen 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:
To:
Date:
Subject:
Header
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 Verarbeitung 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 CarriageReturn (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 Software 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
1
Eine Mailbox wird in der Form local-part@domain angegeben.
Transmission Control Protocol (TCP)
3
Diese Informationen können aber auch für mögliche Angreifer von Vorteil sein und sind deshalb mit Vorsicht
zu verwenden.
2
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 TCPVerbindung.
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 ClientKommando 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 korrekte 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 Benachrichtigung (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 „<CRLF>.<CRLF>“ 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
4
Das ist eine Form des Character Stuffing oder Zeichenstopfens, wie es z. B. in [Tan98, Seite 203 ff.]
beschrieben wird.
5
z. 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 vorhergehende 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:<[email protected]>
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 MAILKommando 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:“ ( “<Postmaster@“ Domain “>“
/ “<Postmaster>“ / Forward-path )
[SP Rcpt-parameters] CRLF
1 RCPT TO:<[email protected]>
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-MailIndikator (<CRLF>.<CRLF>) 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
2.1.4.7
9
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 VRFYFunktionalitä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
6
z. B. um Spammern das Sammeln von Adressen nicht zu erleichtern.
2. Das Simple Mail Transfer Protocol
2.1.5
10
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 =
Reply-line =
Reply-code =
1*(%d09 / %d32-126) ; Horizontal Tabulator (HT), SP, Printable US-ASCII
*( Reply-code “-“ [ textstring ] CRLF )
Reply-code [ SP textstring ] CRLF
%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
2.1.5.3
11
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 <CRLF>.<CRLF>
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 angeforderte 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
2.1.5.8
12
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
220 mail.example.net Service ready
1
2 EHLO mail.example.com
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
250-mail.example.net
250-STARTTLS
250 SIZE 0
HELP
214 Visit http://www.example.net for help
VRFY john
252 Cannot VRFY, send some mail and i try my best
MAIL FROM:<[email protected]>
250 OK
RCPT TO:<[email protected]>
550 No such user here
RCPT TO:<[email protected]>
250 OK
DATA
354 Start mail input; end with <CRLF>.<CRLF>
Date: 1.10.2011 10:21:00 +0100
Subject: Hello
From: Jack <[email protected]>
To: Joe <[email protected]>
22
23 Hello Joe
24 Whats up?
25 .
26
250 OK
27 QUIT
2. Das Simple Mail Transfer Protocol
13
221 mail.example.net Service closing transmission channel
28
Listing 2.19: Beispiel für den Ablauf einer SMTP-Sitzung
220 mail.example.net Service ready
1
2 EHLO mail.example.com
3
4
5
6
7
8
9
10
11
12
13
14
15
16
250-mail.example.net
250 SIZE 0
STARTTLS
502 Command not implemented
MAIL FROM:<[email protected]>
250 OK
RCPT TO:<[email protected]>
250 OK
DATA
354 Start mail input; end with <CRLF>.<CRLF>
Date: 1.10.2011 10:21:00 +0100
Subject: Hello
From: Jack <[email protected]>
To: Joe <[email protected]>
17
18 Hello Joe
19 Whats up?
20 .
21
22
23
24
25
452 Temporary problem, insufficient system storage
RSET
250 OK
QUIT
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
2.1.8
14
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 DNSQuery 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
2 mx02.example.com
3 example.com
4 example.com
IN
IN
IN
IN
A
A
MX
MX
5
10
203.0.113.1
203.0.113.2
mx01.example.com
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).
7
Mail eXchange Ressource Record im DNS (MX)
Address Ressource Record im DNS (A)
9
Wobei der Eintrag mit dem niedrigsten Preference-Wert die höchste Priorität hat.
10
Den er z. B. per MX-Eintrag im DNS ermittelt hat
11
Genaueres zu SMTP-AUTH-Funktionalität in [SM07]
8
2. Das Simple Mail Transfer Protocol
2.1.8.2
15
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) enthalten 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 „ReturnPath“-Header eingefügt, so darf er gelöscht und aus dem Kommando MAIL neu erstellt werden.
1 From: User1 <[email protected]>
2 Date: Thu, 16 Aug 2012 23:17:42 +0200
3 To: [email protected]
4 Return-Path: <[email protected]>
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 <[email protected]>, uid
7
8
9
10
201) with qmail; 16 Aug 2012 21:17:51 -0000
Received: from unknown (HELO mail.example.net) (198.51.100.2) by 0 with SMTP; 16 Aug 2012
21:17:44 -0000
Received: (qmail 31227 invoked by uid 0); 16 Aug 2012 21:17:43 -0000
Received: from 198.51.100.3 by webmail.example.net with HTTP; Thu, 16 Aug 2012 23:17:42
+0200 (CEST)
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
2.1.9
16
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 Transaktion, ist nicht zulässig. Die genauen Werte der Timeouts sind nicht vorgegeben, jedoch sollen
die Vorschläge aus Tabelle 2.1 eingehalten werden.
Aktion
Client Timeouts
Vom erfolgreichen Aufbau der TCP-Verbindung bis zur 220Willkommensnachricht
Abarbeitung des Kommandos MAIL
Abarbeitung des Kommandos RCPT
Vom Absenden des Kommandos DATA bis zum Empfang der Antwort 354
Erfolgreiches Abschließen eines TCP-Send-Befehls beim Übertragen des
Mail-Content
Vom Senden des End-Of-Mail-Indikators bis zum Empfang der abschließenden Antwort 250
Server Timeouts
Wartezeit bis zum nächsten Kommando des Clients
Timeout
300 Sekunden
300
300
120
180
Sekunden
Sekunden
Sekunden
Sekunden
600 Sekunden
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 <ip address of the mailserver> <port>
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 (Exim
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
SMTP-Server
Minimum laut RFC
mx1.gmx.net
mx-ha01-web.de
email.aon.at
lmail1.ris.at
mx0.inode.at
mail3.edvz.uni-linz.ac.at
mail.krru.at
gmail-smtp-in.l.google.com
mail.messaging.microsoft.com
mail.cloud9.net
hera.kernel.org
mail-relay.telekom.at
Relevantes Minimum
17
SMTP-Software
n/a
n/a
n/a
XMail 1.25
n/a
n/a
netqmail 1.06
n/a
n/a
Postfix
Sendmail 8.14.4/8.14.3
Exim 4.63
Timeout in Sekunden
300
60
30
60
93
31
66
40
600
60
25
3600
n/a
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
12
Dies 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 durchzulassen 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
2.4.2
19
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 Warteschlange 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 Zustellversuch 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
13
Denial 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
14
Eine 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 Perl[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]
• Sender Policy Framework (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 Funktionalitä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üßungsnachricht 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 ESMTPFunktionalitä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 RFCKonformitä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 AntiVirus[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 MITLicense[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] angebunden 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,
1
2
Reverse DNS (rDNS)
Uniform 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änkung 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
Prox/ClamSMTP
ASSP
Hermes
BarricadeMX
qpsmtpd
1
Art
Proxy
Proxy
Proxy
Relay
Relay
SMTPS
Nein
Ja
Ja
Nein
Ja
STARTTLS
Nein
Nein
Ja
Nein
Ja
OTF1-Zertifikate
Nein
Nein
Nein
Nein
Nein
SpamAssassin
Ja
Nein
Nein
Ja
Ja
Virenscanner
Ja
Ja (ClamAV)
Nein
Ja
Ja
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 SpamAssassin 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 Sicherheitswarnung zu erzeugen, muss ein Zertifikat verwendet werden, das von einer Zertifizierungsstelle
3
Dies 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.
4
Dieses 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 SMTPServers 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
4.1.1
Aufbau des TLS-Proxy
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 TCPVerbindungsanforderungen 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.
1
2
Die Anzahl ist mit den Konfigurationseinstellungen NUM_THREADS (siehe Abschnitt 7.1) einstellbar.
Bis 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 ProxyObjekt 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.
/∗ callback function for unique thread id ∗/
CRYPTO_set_id_callback(openssl_thread_id);
1
2
3
/∗ callback lock function ∗/
CRYPTO_set_locking_callback(openssl_mutex_lock);
4
5
6
/∗ callbacks for creating dynlock structures ∗/
CRYPTO_set_dynlock_create_callback(openssl_dl_create);
CRYPTO_set_dynlock_destroy_callback(openssl_dl_destroy);
CRYPTO_set_dynlock_lock_callback(openssl_dl_lock);
7
8
9
10
Listing 4.1: Setzen der OpenSSL Callbacks, für die Verwendung in Multi-ThreadedUmgebungen.
Werden diese Callbacks jedoch definiert, legt sich OpenSSL nicht auf eine Thread-Implementierung 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. Exemplarisch 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
4
5
6
7
8
9
10
if (mode & CRYPTO_LOCK) // lock or unlock?
{
pthread_mutex_lock( &(openssl_mutex[n])); //lock mutex for thread n
}
else
{
pthread_mutex_unlock( &(openssl_mutex[n])); //unlock mutex for thread n
}
4. TLS-Proxy-Engine von Underground_8
29
11 }
12
13 /**
14
15
16
17
18
19
20
21
22
* Creates a new dynlock structure (is used as callback function).
* @param
*file
Source file, from which the call is executed (usefull for debugging).
* @param
line Source line in file, where call is executed (usefull for debugging).
* @return Returns a pointer to a new CRYPTO_dynlock_value structure.
*/
struct CRYPTO_dynlock_value *openssl_dl_create(const char *file, int line)
{
int st;
struct CRYPTO_dynlock_value *dl;
23
/* allocate memory */
dl = (CRYPTO_dynlock_value *)malloc(sizeof(pthread_mutex_t));
if (dl != NULL)
{
/* init mutex */
st = pthread_mutex_init( &dl->mutex, NULL);
if (st != 0) /* error? */
{
free(dl);
dl = NULL;
}
}
return (dl ); /* return new dynlock structure */
24
25
26
27
28
29
30
31
32
33
34
35
36
37 }
38
39 /**
40
41
42
43
44
45
46
47
48
49
50
* If a dynlock isn't necessary anymore, this function will destroy it.
* @param
*dl
pointer to the dynlock structure, which should be destroyed.
* @param
*file
Source file, from which the call is executed (usefull for debugging).
* @param
line
Source line in file, where call is executed (usefull for debugging).
*/
void openssl_dl_destroy(struct CRYPTO_dynlock_value *dl, const char *file,
int line)
{
pthread_mutex_destroy( &dl->mutex);
free(dl);
}
51
52 /**
53
54
55
56
57
*
*
*
*
*
Locks or
@param
@param
@param
@param
unlocks the given dynlock structure (is used as callback).
mode Value indicating, if lock (CRYPTO_LOCK) or unlock should be done.
*dl
dynlock structure, which should be locked/unlocked.
*file
Source file, from which the call is executed (usefull for debugging).
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,
const char *file, int line)
60
61 {
if (mode & CRYPTO_LOCK) /* lock or unlock? */
pthread_mutex_lock( &dl->mutex);
else
pthread_mutex_unlock( &dl->mutex);
62
63
64
65
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 vorgesehen. 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 verknü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.
3
Bei 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 Zertifizierungsstelle 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 TLSProxy 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 SMTPVerbindung 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 HTTPHandler), 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
4.1.4.1
34
Verifikation der Zertifikate
Die Verwendung des TLS-Proxy macht es möglich, die Liste der vertrauenswürdigen Zertifizierungsstellen 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
1
2
3
Verhalten des TLS-Proxy
Selbst wenn die Zertifikatsverifikation fehlschlägt, wird dem Client immer ein gültiges Zertifikat präsentiert.
Fehler, die während der Verifikation auftreten, werden auch in
das Zertifikat an den Client eingebaut und so weitergegeben.
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 wiederverwendet 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
4.1.6
35
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 vollständig transparenten Proxy zu bieten. Dadurch ist sichergestellt, dass die Pakete der TCPVerbindungen den TLS-Proxy in beiden Richtungen passieren, auch wenn dies durch asymmetrisches 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 TLSProxy 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 gesendet. 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 SMTPReturncodes 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önnen prinzipiell wie bei HTTP an den Client weitergeleitet werden, müssen jedoch eventuell
ausgewertet, verändert oder unterdrückt werden4 .
4
z. 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 Verbindungen 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
4.2.5
37
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-middleAttacken 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-Verbindungsaufbau 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 protokollspezifischen 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 angenommen 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]-BuildUmgebung eingebettet werden.
5.2
Einsatzszenarien
Dieser Abschnitt beschreibt mögliche Einsatzszenarien des SMTPS-Proxy. Die genaue Abbildung 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
5.2.2
40
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 SMTPVerbindungen 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ünschenswert 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.
1
Das Hinterlegen des Private-Keys ist in diesem Fall für das Erzwingen von STARTTLS unbedingt erforderlich.
2
De-militarisierte Zone (DMZ)
3
Terminierung der TLS-Session auf dem Proxy, um z. B. den Server zu entlasten.
4
Eine Ausnahme gibt es bei der Verwendung der Funktion SMTP_RELAY_HOST (Siehe Abschnitt 9.2.5)
5. Entwurf
5.3
5.3.1
41
Design
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 Unix Domain Sockets[Ste92,
Abschnitt 6.3 ff.] wird unter Verwendung des in Tabelle 5.1 beschriebenen Protokolls implementiert.
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 Zertifizierungsstelle) 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] <LEN>CRLF
Weist die Zertifizierungsstelle an, ein Zertifikat
<Zertifikat im DER Format>
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 <LEN>CRLF
Signalisiert die erfolgreiche Erzeugung des Zertifikats
<Zertifikat im DER Format>
und übergibt es im DER-Format.
Parameter LEN
-ERR GENCRT [Fehlermeldung] CRLF
Parameter Fehlermeldung
1
2
Länge der DER-Daten des Zertifikats in Bytes.
Signalisiert einen Fehler.
Enthält eine Beschreibung des aufgetretenen Fehlers.
Schlüsselwörter bzw. Parameter in eckigen Klammern ’[]’ sind optional.
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 weiterentwickelt 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 Erweiterungen 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 Funktionalitä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 Vorhandensein 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 sicherheitskritischen 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 Zertifizierungsstelle (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 Zertifizierungsstellen, 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
5.3.5
44
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 Zertifikat 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 erforderlich. Neben einem sinnvollen Logging ist es wichtig, auch für den Client verständliche
Fehlermeldungen zu senden. Dazu werden zur aktuellen Fehlersituation passende SMTPResponses 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
5
Die 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.
6
Wird 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 Programmierschnittstelle, 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
1
Aktuell ist dies bei OpenSSL der Fall.
Aktuell mit 4.6.2011 ist die Version 1.0.0d.
3
Aktuell mit 4.6.2011 ist die Version 0.9.8r.
2
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
# proxy
- serverPid
- mutex
- serverThreadRunning
- working
+
+
+
+
+
#
#
#
EmptyHandler
+ EmptyHandler()
+ ~EmptyHandler()
- handleClientSide()
- handleServerSide()
- handleError()
ProtocolHandler()
runClientThread()
runServerThread()
handleError()
~ProtocolHandler()
connectMiddleProxy()
handleClientSide()
handleServerSide()
HTTPHandler
- mutex
- connection
- version
+ HTTPHandler()
+ handleError()
+ ~HTTPHandler()
- handleBody()
- handleRequestBody()
- createRequestHeader()
- handleResponse()
- handleClientSide()
- handleServerSide()
SMTPHandler
-
proxy_mutex
server_tls_mutex
relay_mutex
server_tls_cond
relay_cond
connection
version
serverGreeting
first250
serverSupportsSTARTTLS
serverTLSdone
forceClient
forceServer
relay
passThrough
serverTLSresult
clientEHLO
count250ResponseServer
count250ResponseClient
midProxyClientSide
midProxyServerSide
smtpCommandTimeout
+ SMTPHandler()
+ handleError()
+ ~SMTPHandler()
- handleClientSide()
- handleServerSide()
- resetHandler()
- getResponseCode()
- 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 Basisklasse 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 Subklassen) 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 Programmlogik 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 BIOStruktur 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).
4
Im Normalfall ist dies eine TLS-Session zwischen Client und TLS-Proxy und eine weitere zwischen TLS-Proxy
und Server.
5
readLine 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:<[email protected]>
MAIL FROM:<[email protected]>
250 OK
250 OK
RCPT TO:<[email protected]>
RCPT TO:<[email protected]>
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öglicht, 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 anzunehmen6 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.
6
Der ThreadPool clientSide wartet hierbei auf Verbindungen vom Client, während der ThreadPool serverSide
auf Verbindungen des MidProxy wartet.
6. Implementierung
50
Proxy
ThreadPool
-
minNumThreads
maxNumThreads
listenSock
waiting
name
workQueue
workMutex
aliveMutex
push
workerEnd
threadSet
dispatcherTid
workerMethod
running
-
client
server
serverSideCtx
clientSideCtx
originalClientCtx
createdCert
originalCert
caSock
clientSock
mutex
depositedCert
+ ThreadPool()
+ start()
+ isRunning()
+ getWork()
+ getListenSocket()
+ thrLog()
+ addWork()
+ exitThread()
+ stop()
+ ~ThreadPool()
- startWorker()
+ Proxy()
+ start()
+ startTLS()
+ startServerTLS()
+ startClientTLS()
+ getDepositedCert()
+ tunnelTCP()
+ getClientPIO()
+ getServerPIO()
+ getClientIP()
+ getServerIP()
+ getCertificate()
+ getSSLContext()
+ setSSLContext()
+ restartServer()
+ disconnect()
+ disconnectClient()
+ disconnectServer()
+ ~Proxy()
- connectServer()
- createOTFCert()
(a) Klassendiagramm
ThreadPool
(b)
Klassendiagramm
Proxy
PIO
-
bio
buffer
sslChain
nullBio
mutex
+ PIO()
+ connect()
+ waitOnEvent()
+ insertSSL()
+ getSSL()
+ getIP()
+ getSocket()
+ isUP()
+ read()
+ write()
+ readLine()
+ writeString()
+ passOnTo()
+ passOnToChunked()
+ disconnect()
+ ~PIO()
(c) Klassendiagramm PIO
Abbildung 6.3: Klassendiagramme ThreadPool, Proxy und PIO
Die Workerthreads beider Pools versuchen mit getWork eine Verbindung aus der WorkQueue 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 SMTPVerbindung 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 Beendigung (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 MiddleProxy 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.
7
In diesem Fall werden die Methoden startServerTLS und startClientTLS getrennt aufgerufen.
6. Implementierung
52
CertificateAuthority
ConnectionTracker
- nextId
- connectionMap
- mutex
-
caCert
caPrivateKey
proxyPublicKey
serialNumber
mutex
certificates
file
validPeriod
+ ConnectionTracker()
+ getNextConnectionId()
+ removeConnection()
+ getConnectionById()
+ ~ConnectionTracker()
+ CertificateAuthority()
+ createCertificate()
+ ~CertificateAuthority()
+ loadFromFile()
+ startUp()
+ cleanUp()
- getCertInfo()
- save()
(a) Klassendiagramm ConnectionTracker
(b) Klassendiagramm CertificateAuthority
CAThread
+ threadId
- clientSocketfd
- clientPIO
- ca
+ CAThread()
+ ~CAThread()
+ getClientSocketfd()
+ run()
+ threadCleanUp()
- readLine()
- sendResponse()
(c) Klassendiagramm CAThread
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 Synchronisationsmechanismen 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 ProtocolHandlerObjekt 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 übertragen 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 hergestellt hat, wird folgendes Kommando übertragen: „NOOP ConnID=<ConnectionID>“.
6. Implementierung
53
SMTPS−Proxy Clientseite
Middle−Proxy
SMTPS−Proxy Serverseite
Verbindungsaufbau
Verbindungsaufbau
NOOP ConnID=<ConnectionID>
NOOP ConnID=<ConnectionID>
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=<ConnectionID>, 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 TLSProxy-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ültigkeitszeitraum 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
8
Dabei 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 Seriennummer 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 Zertifizierungsstelle 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 <Nächste freie Seriennummer>
2 <Seriennummer 1> <gültig von> <gültig bis> <Original-Hash>
3 <Seriennummer 2> <gültig von> <gültig bis> <Original-Hash>
4 <Seriennummer 3> <gültig von> <gültig bis> <Original-Hash>
5 ...
Listing 6.2: Aufbau des Zertifikatsspeichers
6.5.2
Initialisierung
Bei der Initialisierung der Zertifizierungsstelle müssen folgende Aufgaben erledigt werden:
9
Konfigurationsparameter: 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 Konfigurationsdatei 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
10
11
In diesem Fall sind dies SIGINT oder SIGTERM. SIGKILL kann nicht abgefangen werden.
Bei 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 CAThreadObjekts 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ückgesendet („-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
<len>“ 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 SignalHandler 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 BlockingModus. 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 werden 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 Operationen 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, Schreiben 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 Dokumentation von OpenSSL explizit den Einsatz von Non-Blocking-Sockets vor:
12
Zu 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
4
5
6
7
8
9
10
11
12
int flags = fcntl(socket, F_GETFL, 0); // get current flags of socket
if (nb) //set non blocking
{
flags |= O_NONBLOCK; // set nonblocking bit
}
else //set blocking
{
flags &= (~O_NONBLOCK); // clear nonblocking bit
}
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
clientConnection
handleClientSide
handleServerSide
serverConnection
Server
Client
midProxy
Connection
Midproxy
midProxy
Connection
Abbildung 6.6: Kommunikationsstruktur
6.7
6.7.1
Protokollhandler für SMTP
Struktur des SMTP-Handlers
handleClientSide
handleServerSide
waitOnEvent
waitOnEvent
handleClientCommand
handleMidProxyResponse
handleMidProxyCommand
disconnect
handleServerResponse
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 SMTPKommandos 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 handleServerSide 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 Kommunikationspartner 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 MiddleProxy) 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 EndOf-Mail-Indikator (<CRLF>.<CRLF>) 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
5
6
7
8
9
10
11
12
13
14
15
16
...
if (timeoutSec > 0) // timeout is set, create timeout struct
{
timeout = new timeval;
timeout->tv_sec = timeoutSec;
timeout->tv_usec = 0;
}
...
/*
first parameter specifies socket count in sockets struct +1
wait until on of the sockets has data to read
*/
result = select(max(socket1, socket2) + 1, &sockets, NULL, NULL, timeout);
if (result > 0)
6. Implementierung
17
{
if (FD_ISSET(socket1,&sockets)) // first socket has data to read
{
result = 1;
}
else if (FD_ISSET(socket2,&sockets)) // second socket has data to read
{
result = 2;
}
else // error no socket has data to read but select still returned
{
result = -1
}
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
63
}
...
else //result is 0 -> timeout
{
result = PIO_TIMEOUT
}
...
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 SMTPAntwort (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 SMTPProxys (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
13
ProxSMTP sendet beim Empfang des STARTTLS-Kommandos folgende Antwort: 502 Command not implemented.
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 unterstü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 SMTPVerbindung abbrechen14 , da er kein TLS erzwingen kann.
Schlägt der TLS-Handshake mit dem Server fehl oder akzeptiert der Server das STARTTLSKommando 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 IPAdressen 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.
14
Dazu wird folgende Antwort an den Client gesendet: „421 Server does not support STARTTLS but it is
forced by config. Shutting down Connection.“
15
RFC3207 schlägt dazu folgende Antwort vor: „530 Must issue a STARTTLS command first“.
6. Implementierung
6.7.7
67
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 TCPVerbindung 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 Willkommensnachricht16 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 {
pthread_cond_wait(&server_tls_cond,&server_tls_mutex); // wait until condition notify
//mutex is locked after this
4
5
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 PthreadConditions
16
In diesem Fall jene des SMTP-Relay.
6. Implementierung
6.7.8
68
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 {
log(LOG_WARNING,"PASS THROUGH: connection from %s to %s",proxy->getClientIP().c_str(),
proxy->getServerIP().c_str());
8
9 }
10 if (proxy->tunnelTCP()!= NO_ERR) // tunnel any traffic between without inspection
11 {
log(LOG_WARNING,"PASS THROUGH ERROR: connection from %s to %s",proxy->getClientIP().
c_str(),proxy->getServerIP().c_str());
12
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 SMTPStandards zu unterstützen und zusätzlich die STARTTLS-Erweiterung zu ermöglichen. Normalerweise sind SMTP-Erweiterungen unproblematisch, da sie der Proxy einfach an den Server
durchreichen kann (z. B. AUTH[SM07] oder 8BITMIME[KFRC11]). Es kann jedoch vorkommen, 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 Erweiterung 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 TLSHandshake 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
+ passPhrase
+ CertList()
+ getCertFromDeposit()
+ loadCertsFromDir()
+ ~CertList()
- loadEntryFromFile()
(a) Klassendiagramm CertList
+ getPassPhrase()
+ CertEntry()
+ ~CertEntry()
(b) Klassendiagramm CertEntry
Abbildung 6.8: Klassen zur Verwaltung von hinterlegten Zertifikaten
CertEntry neben Zertifikat und Private-Key auch die zugehörige Passphrase. Um die CertEntryObjekte 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 TLSProxy ausreichend für jedes Subject nur ein Zertifikat zu verwalten.
1 map <unsigned long, CertEntry *> *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: <Passphrase>
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
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
log(LOG_WARNING,"Certificates differ, return code: %d",compareResult);
ret=CERT_VERIFY_ERR;
}
else
{
debug("Certificates match!");
SSL_CTX *oldClientContext=proxy->getSSLContext(true);
SSL_CTX *newClientContext=SSL_CTX_new(SSLv23_server_method()); //create new SSL Context
debug("Context has been created");
SSL_CTX_set_options(newClientContext,SSL_CTX_get_options(oldClientContext));
debug("Options from original context are set!");
SSL_CTX_set_mode(newClientContext,SSL_CTX_get_mode(oldClientContext));
debug("Mode from original context has been set");
if(SSL_CTX_set_cipher_list(newClientContext,config->getC("CIPHER_LIST"))!=1)
log(LOG_ERR,"Could not set even one cipher");
else
debug("Cipher list from config has been set");
if (config->getInt("PERMIT_DEFAULT_CA_VERIFY_PATH"))
{
if(SSL_CTX_set_default_verify_paths(newClientContext)!=1)
log(LOG_WARNING,"Could not set default verify paths");
else
debug("Default verify paths have been enabled");
}
if (config->getInt("PERMIT_CA_VERIFY_LOCATIONS"))
{
if(SSL_CTX_load_verify_locations(newClientContext,config->getC("CA_VERIFY_FILE"),config
->getC("CA_VERIFY_PATH"))!=1)
log(LOG_WARNING,"Could not load verify locations from config");
else
debug("Verify locations have been loaded from config");
}
SSL_CTX_set_session_cache_mode(newClientContext,SSL_SESS_CACHE_OFF |
SSL_SESS_CACHE_NO_INTERNAL);
debug("Session cache mode has been set to off");
if(SSL_CTX_use_PrivateKey(newClientContext,depCert->privateKey)!=1)
{
log(LOG_WARNING,"Could not set private key for context");
ret=CERT_CREATE_ERR;
}
else
debug("Private key from deposit has been set");
6. Implementierung
45
46
47
48
49
50
51
52
53
54
if(SSL_CTX_use_certificate(newClientContext,depCert->cert)!=1)
{
log(LOG_WARNING,"Could not set Certificate for context");
ret=CERT_CREATE_ERR;
}
else
debug("Certificate from deposit has been set");
proxy->setSSLContext(newClientContext,true);
debug("Original Context has been replaced by the created one");
}
Listing 6.11: Vergleichen der Zertifikate und Erzeugen eines neuen SSL-Client-Context
74
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
Code
0
1
2
3
4
5
6
7
Severity
Emergency: system is unusable
Alert: action must be taken immediately
Critical: critical conditions
Error: error conditions
Warning: warning conditions
Notice: normal but significant condition
Informational: informational messages
Debug: debug-level messages
Tabelle 7.1: Syslog Message Severities. Aus [Ger09].
LOGNAME
Alle Meldungen werden unter diesem Namen geloggt.
Standardwert: TLSProxy
1
z. 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
2
http://netfilter.org/projects/iptables/index.html
http://www.squid-cache.org/
4
http://memberwebs.com/stef/software/proxsmtp/
3
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 terminiert.
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 ausgestellten 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 TLSHandshake 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 TLSHandshake 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 dazugehö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 SMTPDialog 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 / postfix)
exchange.underground8.com
Haupt-Firewall
fw.underground8.com
Firewall mit TLS Proxy
Externer Server
(Gentoo / qmail)
client.test.underground8.com
external.example.com
Lokale Arbeitsstation
fw.test.underground8.com
Mail-Relay
Andere externe
Server
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.
1
In 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
8.3.1
Non-TLS-Tests
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
--protocol ESMTP
[email protected] --protocol SMTP
[email protected] --protocol ESMTP
[email protected] --protocol SMTP
[email protected] --protocol ESMTP
2 swaks -t [email protected]
3 swaks -t
4 swaks -t
5 swaks -t
6 swaks -t
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)
2
z. B. PIPELINING oder spezifische Features für Microsoft Exchange
8. Tests
8.3.2.1
89
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
2
3
swaks -t [email protected] -protocol ESMTP -q EHLO
swaks -t [email protected] -protocol ESMTP -q EHLO
swaks -t [email protected] -protocol ESMTP -q EHLO
Listing 8.2: Überprüfung, welche ESMTP-Features der Proxy erlaubt
8.4
8.4.1
TLS-Tests
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 TLSSession 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
--protocol ESMTPS -q EHLO
--protocol ESMTPS -q EHLO
2 swaks -t [email protected]
3 swaks -t [email protected]
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 Mailserver 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 STARTTLSUnterstü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 Konfigurationsparameter 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 Warnung 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 hinterlegtes 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
8.4.6.1
92
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-themiddle-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
8.4.7.1
93
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 <client IP> to <server IP>“ 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öglichkeiten:
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 TCPVerbindung 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 EHLOAntworten 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
3
Dazu 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 Kommando 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 SMTPVerbindung 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
8.6.2.2
96
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 Kommandos.
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
8.6.3.2
97
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 verwendet werden. Serverseitiges Erzwingen bewirkt einen TLS-Handshake nach erfolgtem EHLO,
clientseitiges Erzwingen verhindert eine weitere Kommunikation ohne TLS-Session auf ClientSeite.
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 Konfigurationsoptionen.
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 LinuxDistributionen (z. B. Debian,Ubuntu, etc.) ist es außerdem nötig, zusätzlich die passenden
-dev-Pakete zu installieren.
9.1.2
9.1.2.1
Installation auf einem Linux-System
Ü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
1
MF Security Gateway
Ein rekursives Akronym für „GNU’s Not Unix!“ (GNU)
3
Auch bekannt als ”autotools”
2
98
9. Handbuch zur Systemintegration
Name
glibc
gcc
libtool
libcap
binutils
openssl
autoconf
automake
make
iptables
linux-kernel
tproxy patch
Version
2.3.3
3.3.3
1.5.6
1.10
2.15.90.0.3
>=0.9.8o <1.0.0
2.59
1.9.6
3.80
1.4.0
>=2.4.36.7 <2.6.28
TPROXY2 nicht TPROXY4
99
Quelle
gnu.org[18]
gnu.org[14]
gnu.org[23]
kernel.org[41]
gnu.org[21]
openssl.org[39]
gnu.org[19]
gnu.org[20]
gnu.org[24]
netfilter.org[34]
kernel.org[32]
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
–enable-smtps
–enable-tproxy
–enable-rcvd-via
–enable-debug
–enable-thrlog
Aktiviert die Unterstützung für HTTP(S).
Aktiviert die Unterstützung für SMTP(S).
Ermöglicht die Nutzung des TPROXY-Kernel-Patches.
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.
Ermöglicht das Aktivieren von Debug-Ausgaben.
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
9.1.2.2
100
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
-P HTTPS
-P NONE
-c path
Das Programm startet als Proxy für SMTPS
Das Programm startet als Proxy für HTTPS
Das Programm startet ohne Protokollunterstützung (z. B. zum Testen der
Konfiguration)
Spezifiziert den Pfad der Konfigurationsdatei
(Standardwert: /etc/tlsproxy/proxy.conf).
Tabelle 9.3: Kommandozeilenparameter des TLS-Proxys
-h, –help
-c path
Das Programm zeigt die möglichen Kommandozeilenparameter an und beendet
sich.
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 OpenSSLBibliotheken 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, übersetzt und installiert werden. Dadurch wird die Verwendung von OpenSSL in MultithreadedProgrammen 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 vorgenommen 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 <ankommendes Interface> ... \
-j REDIRECT [--to-ports <Port>[-<Port>]]
2
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 <internes Interface>
-j REDIRECT --to-
ports <PORT des TLS-Proxy>
2 iptables -t nat -A PREROUTING -p tcp --dport 25 -i <externes Interface>
-j REDIRECT --to-
ports <PORT des TLS-Proxy>
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
4
siehe [34]
Kommandozeilenprogramm zur Konfiguration des Paketfilters des Linux 2.4.x bzw. Linux 2.6.x Kernels
(IPTABLES)
6
Portable Operating System Interface (POSIX)
5
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
2
3
4
5
6
7
8
Listen: 127.0.0.1:20025
OutAddress: 4001
TransparentProxy: off
MaxConnections: 64
KeepAlives: 30
FilterCommand: spamassassin.sh
FilterType: pipe
FilterTimeout: 1200
#
#
#
#
#
#
#
#
Port für eingehende Verbindungen
Port für ausgehende Verbindungen
kein Betrieb als transparenter Proxy
Maximale Anzahl gleichzeitiger Verbindungen
Senden von NOOP alle 30 Sekunden
Mails werden durch dieses Script gefiltert
Mail werden per Pipe an das Skript übergeben
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 MiddleProxy 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 TCPVerbindungen, 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
# The last line of output to stderr will be used
# as an error message when the filter fails
echo "550 Content Rejected: We don't like spam" >&2
# Cause the filter to fail, email will be rejected
exit 1
6
7
8
9
10
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 Einsatzszenarien 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
10.0.0.0/24
Internet
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
10.0.0.0/24
Internet
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üsselung
Das Generieren von Zertifikaten on-the-fly ist zwar für externe Server nötig, doch bei einem 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:
7
Option: 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
10.0.0.0/24
Internet
SMTPS-Proxy
10.0.0.1
192.0.2.10
192.0.2.20
DMZ
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
10.0.0.0/24
Internet
SMTPS-Proxy
10.0.0.1
198.51.100.10
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 aufzubauen. Dieser generiert, basierend auf dem Zertifikat des originalen Zielservers, ein On-the-flyZertifikat. 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 AntiSpam- 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
1
http://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 Protokollversionen 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.
2
Post Office Protocol (Version 3) (POP3)
Internet Message Access Protocol (IMAP)
4
z. B. GnuTLS [25]
3
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 Klartextverbindungen
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].
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
. . . . . . . . . . . . . . . . . . . . . . 76
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.
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
. . . . . . . . . . . . . 105
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
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
. . . . . . . . . . . . . . . . . . . . . . . . . . 62
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 STARTTLSUnterstü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
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
. . . . . . . . . . . 93
. . . . . . . . . . . . . 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: DomainKeys 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 Documentation. 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, Algorithmen 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 : Grundlagen, Programmierung, Anwendung.
Hanser [u.a.], München [u.a.], 1992,
ISBN 9783446163188.
[Ste94]
Stevens, William Richard: TCP/IP Illustrated, Volume 1 The Protocols. AddisonWesley 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.
ISBN 9783827267030.
122
Markt und Technik, 2. Auflage, 2003,
Internetquellen
[1] The apache spamassassin 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/, besucht: 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, besucht: 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, besucht: 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
2002–2004
2006–2008
seit 2008
Matura (mit gutem Erfolg), HTBLA-Leonding Abteilung EDV und Organisation, Leonding.
BSc Computing Science, Universtity of Derby in Austria (UDA).
Bakk.techn. Informatik, Johannes Kepler Universität, Linz.
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.