Hitchhiker's Guide to the Internet

Ingo Blechschmidt



1 Einleitung

In diesem Dokument werden die verschiedenen Internetprotokolle (sowohl Low-Level als auch Application-Level) vorgestellt, so dass man nach Studieren dieser Datei (welche man im Übrigen auch in einem beliebigen ASCII-Viewer betrachten kann) in der Lage ist, nur via Telnet zu surfen, Mails zu verschicken und empfangen, usw.

Geschrieben wurde diese Version (2787) mit MyBook (programmiert vom Autor).

Über jegliche Kommentare und Ergänzungen würde ich mich, Ingo Blechschmidt, iblech@web.de, sehr freuen.

1.1 Bezugsquellen

Die aktuellste Version dieses Buches ist auf http://linide.sf.net/theguide2/ zu finden. Interessant könnte auch die Projektseite auf Freshmeat sein.

1.2 Schreibkonventionen

Einzelne Befehle oder Programme werden im Fließtext gesperrt gedruckt.

Längere Listings hingegen bekommen immer einen extra Absatz:

Ein Dialog, etwa zwischen Server und Client, wird wiefolgt dargestellt:

Werden im Fließtext Programme genannt, werden sie gesperrt gedruckt (Beispiel: telnet erwartet als Parameter...). Wenn aber das Konzept oder die Idee hinter dem Programm gemeint ist, wird es normal gedruckt und passt sich auch der Groß-/Kleinschreibung an (Beispiel: Die Idee hinter Telnet...).

Aus Platzgründen müssen in Listings oft einige Details weggelassen werden.

1.3 Wishlist

Ich kann auch noch andere Protokolle hier erläutern, einfach mir eine Mail schicken und ich arbeite daran...

2 Grundlagen

In diesem Kapitel werden die unteren Schichten des Internets, also die Basis, auf der alle folgenden Kapitel aufbauen werden, vermittelt.

2.1 Das OSI-Schichtenmodell

Man untergliedert die Protokolle des Internets in verschiedene Schichten, definiert schon 1982 durch das OSI-("Open System Interconnection")-Schichtenmodell. Vereinfacht dargestellt, gliedert es alle Protokolle in drei Schichten1:

digraph osi {
	"Application Level" ->
	"Transport Level" [ label="baut auf" ]
	"Transport Level" ->
	"Physical Level" [ label="baut auf" ]
}

Je weiter "oben" ein Protokoll liegt, so abstrakter ist es. Mit diesen Protokollen werden wir uns am meisten beschäftigen. "Unten" liegt zum Beispiel die physikalische Schicht: Das entspräche praktisch dem Netzwerkkabel. Da uns aber nur die Software interessiert, wird hier darauf nicht eingegangen werden.

Auf der Transportschicht ist das Protokoll IP, "Internet Protocol", angesiedelt. IP ist für die grundlegende Kommunikation aller Rechner im Internet zuständig. Eine Schicht höher (nicht abgebildet) liegt TCP, das Transport Control Protocol. Dieses Protokoll sorgt dafür, dass die mit IP versendeten Pakete am Ziel auch ankommen, da IP selbst nicht für die Lieferung der Pakete garantiert. Auf der Anwendungsebene schließlich sind alle "hohen" Protokolle angesiedelt, namentlich SMTP, POP3, HTTP, NNTP und viele andere, denen je ein einzelnes Kapitel gewidment ist.

2.2 IP

Heute sorgt für die Kommunikationsfähigkeit aller Knoten des Internets die Version 4 des IP.

Sendedaten unterteilt IP in kleinere Pakete, die dann verschickt werden können. Dabei werden Absender und Empfänger durch eine IP-Adresse bestimmt.

Alle IP-Adressen sind vier Byte lang (ein "Word"), untergliedert in vier Zahlen mit je einem Byte. Was sich hier etwas kompliziert anhört ist ganz einfach: 80.81.9.177 ist zum Beispiel eine gültige IP-Adresse. Jede Zahl darf (wegen der 1-Byte-pro-Zahl-Grenze) maximal 255 (die 0 wird mit einbezogen) betragen.

Besondere IP-Adressen sind solche, die

2.3 Routing

Aber wie kommen die Pakete von einem Rechner A zu B? Da gäbe es jetzt zwei Möglichkeiten:

2.3.1 Time to Live

Durch z.B. fehlerhafte Routing-Tabellen können nun aber auch Endlosschleifen entstehen: Meint z.B. ein Rechner P, er müsse alle Pakete an Q schicken, und Q meint, alle Pakete sollen an P weitergeleitet werden, so wird das Paeket ewig zwischen den beiden Rechnern weitergeleitet werden.

Eine naive Lösung dieses Problems wäre es, einfach festzulegen: "Schicke niemals ein Paket zu dem Rechner zurück, der es dir zugeschickt hat."

Aber auch dadurch wird das Problem nicht vollständig gelöst, nämlich dann, wenn noch ein weiterer Rechner "in der Schleife festsitzt":

digraph endlosschleife {
	P -> Q -> R;
	R -> P [ weight = 2 ];
}

Deswegen kommt hier ein intelligenteres Verfahren zum Zug: Jedes Paket gibt in seinem Header nicht nur über Absender und Empfänger auskunft, sondern auch über die sogenannte Time to Live, abgekürzt TTL. Die TTL ist eine ein Byte breite Zahl (mögliche Werte zwischen 0 und 255). Wenn das Paket beim Absender generiert wird, erhält es einen bestimmten Startwert, der sich bei den meisten Betriebssystemen voneinander unterscheidet. Jedesmal, wenn das Paket einen Router passiert, wird dieser Wert um eins dekrementiert. Ist die TTL 0, wird das Paket verworfen und an den Absender wird eine Fehlermeldung über das Protokoll ICMP zugestellt.

2.3.2 Traceroute

Mit Hilfe der TTL kann man auch herausfinden, wie viele Router ein Paket passieren musste, ehe es sein Ziel erreichte. Dabei sendet man zuerst ein Paket zum Empfänger mit einer Start-TTL von 1. Erhält man keine Fehlermeldung, so besteht eine direkte Leitung zum Empfänger. Andernfalls war die TTL zu niedrig und man sendet erneut ein Paket, aber diesmal mit einer TTL von 2. Dieses Spiel führt man so lange fort, bis man bis zum Ziel durchkommt.

Möchte man diesen Vorgang automatisieren, benutzt man den Shellbefehl traceroute (oder tracert auf schlechten Betriebssystemen), den man als root ausführen muss:

Traceroute ist oft als Diagnoseprogramm sinnvoll, wenn man eine Fehlermeldung der Art "Time to Live exceeded" zu Gesicht bekommt2. Sind einige Router "leicht fehlerhaft" konfiguriert, kann die Ausgabe z.B. so aussehen:

traceroute verschickt standardmäßig UDP-Pakete, kann aber auch mit der Option -I ICMP-Echo-Request-Pakete verschicken. Mit dem exzellenten tcptraceroute von Michael Toren können auch TCP-Pakete verschickt werden.

2.3.3 OS-Fingerprinting mittels der TTL

Wie weiter oben schon kurz angesprochen nehmen viele Betriebssysteme einen anderen Startwert für die TTL her. Umgekehrt bedeutet dies: Kennt man die Start-TTL eines Paketes, kann man auch mit einiger Gewissheit sagen, welches Betriebssystem der Absender benutzt. Dieser Vorgang ist ein Teil des sogenannten "OS-Fingerprintings", dem Identifizieren des eingesetzten Betriebssystems (und evtl. seiner Version).

Bei der praktischen Umsetzung dieser Idee gibt es jedoch noch ein Problem: Über (z.B.) einen Ping erfährt man nur den Wert der TTL am Ende der Reise des Pakets, der Startwert bleibt unbekannt. Aber dank Traceroute kann man ja auch die Anzahl der Hops, die Anzahl der Router, die Pakete auf dem Weg zum Ziel passieren mussten, bestimmen. Addiert man nun also die TTL des Paketes am Ende seiner Reise und die Anzahl der Hops, so erhält man die Start-TTL. Diese kann man dann in Tabellen nachschlagen.

Als Beispiel vergleichen wir die Start-TTLs von www.debian.de und www.suse.de. Wir gehen davon aus, dass sie beide eine ähnliche Version von Linux installiert haben, also müssten ihre Start-TTLs miteinander übereinstimmen.

Die Start-TTLs stimmen miteinander überein, unsere Vermutung, dass www.suse.de und www.debian.de das gleiche Betriebssystem einsetzen, war also korrekt. Wir könnten jetzt auch noch in Tabellen nachschlagen, welches Betriebssystem normalerweise Pakete mit einer TTL von 64 sendet, aber im Fall von Debian und SuSE ist das ziemlich klar... ;-).

2.4 TCP

Ein gravierender Nachteil von IP ist allerdings die mangelnde Fehlertoleranz: Ist Netzlast hoch, kommen viele Pakete nicht am Ziel an. Deswegen wurde ein weiteres Protokoll entworfen, TCP, das Transmission Control Protocol. TCP sorgt dafür, dass die via "normalem" IP versendeten Pakete auch wirklich am Ziel ankommen.

Dies erreicht TCP vereinfacht gesagt dadurch, dass es die Pakete nummeriert. Empfängt der Zielrechner z.B. die Pakete mit den Nummern 42, 43, 45 und 46, so weiß er, dass Paket 44 fehlt und kann es neu anfordern.

Auch ergänzt TCP IP um sogenannte Ports: Auf jedem der insgesammt 2^{16}216 Ports (0 bis 655353) kann ein eigener Dienst (HTTP, SMTP, POP3, IMAP, DNS, etc.) "lauschen". Dadurch erst wird die Dienstevielfalt des Internets möglich.

2.4.1 Telnet

Um zu einem TCP-Port eines Hosts zu connecten, benutzt man unter guten System (Linux, Hurd) den Shellbefehl telnet. Um z.B. eine Verbindung mit dem Rechner mars auf Port 22 herzustellen, benutzt man:

Um eine Verbindung vorzeitig abzubrechen, kann man die Tastenkombination Strg+AltGr+] benutzen. Daraufhin nimmt telnet Befehle entgegen. Mit quit (abkürzbar auf q) kann man die Verbindung schließen.

"Aber Telnet ist doch unsicher!1 Telnet sollte nicht verwendet werden!"

Diese Aussage, für die Google immerhin über 3000 Ergebnisse liefert, ist nur bedingt richtig. Richtig ist, dass bei Telnet alle Daten im Klartext, also unverschlüsselt, übertragen werden. So kann, durch Abhören des Netzverkehrs ("Sniffen"), auch sensible Daten wie Passwörter mitgeschnitten werden. Möchte man Telnet also zur Fernadministration einsetzen, ist diese Aussage zweifellos richtig und man sollte lieber OpenSSH einsetzen. SSH verschlüsselt den Datenstrom bevor er über das Netz gesendet wird.

Aber bei allen anderen Einsatzgebieten von Telnet kann man nicht pauschal von einer Unsicherheit reden. Möchte man z.B. nur die aktuelle Zeit abfragen4, steht die Sicherheit5 im Hintergrund.

2.4.2 nmap

Möchte man eine Übersicht aller offenen Ports (Ports, an denen ein Dienst lauscht), verwendet man einen Portscanner.

Portscanner verbinden sich praktisch mit jedem möglichen Port des Zielsystems. Wird die Verbindung aufgebaut, ist der Port offen und wird angezeigt. Ein beliebter Portscanner unter Linux und anderen Unix-basierten Systemen ist nmap. nmap erwartet in seiner einfachsten Form nur die Namen der Hosts, die gescannt werden sollen:

Möchte man schon während dem Scan sehen, welche Ports als offen identifiziert wurden, kann man nmap mit der Option -v aufrufen:

2.5 UDP

UDP, das User Datagram Protocol, ergänzt IP lediglich um die schon von TCP bekannten Ports, nicht aber um die Fehlertoleranz. Pakete, die aus irgendeinem Grund nicht am Ziel ankommen, werden also nicht nochmal geschickt.

Dies ist z.B. bei der Übertragung von Audio- und Video-Streams sinnvoll, da dort eine evtl. häufige Neu-Übertragung von Paketen die verfügbare Bandbreite nur unnötig schmälern würde. Außerdem fallen einige nicht übertragene Pakete nicht ins Gewicht: Das nächste Paket, welches z.B. die nächste zehntel Sekunde eines Audio- oder Videostreams beschreibt, wird schon nach sehr kurzer Zeit abgesendet. Das Fehlen einen Frames wird quasi durch den nächsten "übertönt", es ist höchstens ein kurzes Knacken zu hören bzw. ein kurzer Hänger zu sehen.

Auch gibt es bei UDP nicht das Konzept einer Verbindung zwischen zwei Hosts: Es werden einfach Pakete verschickt und empfangen, aber es gibt keine Zugehörigkeit zu einer Verbindung. Ein Server kann auf ein UDP-Paket in dem Sinne auch nicht antworten, sondern schickt einfach ein neues Paket los.

2.5.1 Netcat

Möchte man manuell eine "Verbindung" zu einem UDP-Port herstellen, kann man Netcat verwenden, Telnet ist dazu nicht fähig.

Als Beispiel wollen wir ein Paket zum UDP-Port 13 von sombrero.cs.tu-berlin.de schicken:

Statt we be leet hätten wir auch nur eine Leerzeile oder etwas anderes schicken können: Der Server von sombrero.cs.tu-berlin.de, der auf dem UDP-Port 13 lauscht, ist so programmiert, dass er, immer, wenn er ein Paket empfängt, er ein Paket mit der aktuellen Zeit zurückschickt. Auch mussten wir nc mit Strg+C abbrechen: Da es bei UDP ja keine Verbindungen gibt, konnte der Server auch keine schließen, was für Netcat das Signal gewesen wäre, sich zu beenden. Aber dies ist UDP, nicht TCP, also mussten wir selbst das Programm beenden.

2.6 ICMP

ICMP, das Internet Control Message Protocol, wird, von einigen kryptographischen Zwecken einmal abgesehen, nur zur Statusübertragung für IP/TCP/UDP eingesetzt, zum Beispiel ob der Zielhost existiert, eine Route verfügbar ist usw. Dies haben wir weiter oben bei Traceroute ausgenutzt: Der Fehler, der Traceroute gemeldet wird (Time-to-Live exceeded), wird über ICMP übertragen.

Wichtig dabei ist, dass Fehler, die bei der Übertragung der Statusmeldungen auftreten, nicht nochmal gemeldet werden. Unter Umständen wäre eine endlose Überschwemmung des Netzes die Folge.

2.6.1 Ping

Von den verschiedenen Statusmeldungen, die über ICMP übertragen werden können, werden zwei besonders häufig genutzt: "Pings" und "Pongs" (ICMP-Echo-Requests und ICMP-Echo-Replies).

Erhält ein Rechner einen Ping, so sollte er einen Pong zurückschicken. Dies wird oft genutzt, um die Erreichbarkeit von Hosts zu testen.

Das Programm, das Pings versendet, heißt unerwarteterweise ping. Der Aufruf ist simpel, als Argument erwartet ping lediglich den Host, den es pingen soll:

Auf guten System pingt ping bis es manuell abgebrochen wird, auf schlechten Systemen (=MDollar) wird nur einige Male gepingt.

Ist ein Rechner nicht online, erhält man eine Ausgabe der Art

"Pings sind böse! Auf Pings darf man nicht antworten! Sonst weiß ein böser Hacker, dass man online ist!"

In der Tat kann man "Pings einfach blocken", also keine Antwort auf Pings verschicken. Aber sicherer vor "bösen Hackern" ist man deswegen nicht: Zum einen reagieren die meisten Provider auf einen Ping auf einen Rechner, der offline ist, mit einem ICMP-Destination-Unreachable-Paket. Konfiguriert man nun seine Firewall so, dass keine Pongs verschickt werden, weiß ein Angreifer, dass der online ist: Wäre er es nicht, würde vom Provider ja das besagte ICMP-Destination-Unreachable-Paket kommen.

Zum anderen gibt es noch andere Methoden, um festzustellen, ob ein Rechner online ist: Zum Beispiel könnte man einfach zu irgendeinem (TCP-)Port des Rechners connecten. Schlägt der Versuch sofort fehl (nicht erst nachdem ein Timeout abgelaufen ist), ist klar, dass der Rechner on ist: Sonst hätte er den Versuch eines Verbindungsaufbau ja nicht zurückweisen können.

Besser ist es, die Dienste, die man anbietet, abzusichern, und nicht "Pings zu blocken" und darauf zu hoffen, dass man dann sicher ist.

2.7 Abschluss

Besonders den Umgang mit telnet sollte man beherrschen, um die Beispiele der nächsten Kapitel auch selbst ausprobieren zu können.

3 E-Mails

Oft wird dazu geraten, Spam-Mails ("Unerwünschte Werbe-Mails") einer sogenannten Header-Analyse zu unterziehen.

Dabei ist der Ausdruck insbesondere beim Umgang mit Mails nicht ganz korrekt: Bei E-Mails gibt es zwei Header-Typen, einmal den SMTP-"Header" (mehr dazu im Kapitel über SMTP) und dann den Mail-Header, um den es in diesem Kapitel geht.

3.1 Format

Schaut man sich einmal den vollständigen Quelltext einer Mail an, so stellt man fest, dass die Mail in zwei Abschnitte gegliedert ist.

Zuerst kommt der Header, der Auskunft über Absender, Empfänger, etc. gibt. Die einzelnen Headerfelder werden von den Feldinhalten mit einem (Doppelpunkt Leerzeichen) voneinander getrennt.

Dann folgt, getrennt durch eine Leerzeile, der Nachrichteninhalt. Eine optionale Signatur wird durch --  (Bindestrich Bindestrich Leerzeichen) vom Text getrennt.

3.2 Typische Header

Die meisten Header sind in RFC 2076 standardisiert. Die mit X- beginnenden Header können frei verwendet werden, auch wenn sich einige X-Header auch schon als de-facto Standard durchgesetzt haben:

HeaderBedeutung
ReceivedSMTP-Server-Stempel
DateZeitpunkt des Versendens
FromAbsender6
Reply-ToAdresse, an die Rückantworten gehen sollen
Message-IDWeltweit eindeutige ID, oft bestehend aus einem festen und einem zufälligen Teil. Die Eindeutigkeit der Message-ID ist besonders bei NNTP sehr wichtig.
In-Reply-ToMessage-ID, auf die geantwortet wurde
To, CcEmpfänger
SubjectBetreff
Organization7Organisation, Firma, etc.
Content-TypeMIME-Typ
User-Agent, X-MailerVerwendeter MUA (Mailprogramm)
X-Operating-SystemZum Verfassen der Mail verwendetes Betriebssystem (Linux, Hurd, ...)
X-GnuPG-KeyID des öffentlichen GnuPG/PGP-Schlüssels

3.3 SMTP-Server-Stempel

Mails werden, wie im nächsten Kapitel beschrieben, bei SMTP über viele Server geleitet. Jeder Server fügt beim Weiterleiten seinen eigenen Received-Header möglichst weit unten (aber vor den "normalen" Headern wie From usw.) an, zum Beispiel:

Hier hat also der Server localhost vom Server iblech.dyndns.org eine Mail via dem Protokoll ESMTP erhalten.

So lassen sich manchmal Spam-Versender zurückverfolgen, auch wenn sie ihre Absenderadresse fälschen: Es ist ein leichtes, den From-Header zu fälschen. Aber der (nicht so einfach modifizierbare) erste Received-Header lässt den der Ursprung der Mail trotzdem erkennen.

3.4 MIME-Typen

Ein anderer wichtiger Header ist Content-Type. Dieses Feld gibt den MIME-Typ ("Multipurpose Internet Mail Extensions") des Inhalts der Mail an. Nur so weiß der Mailreader, welches Format die Mail hat ("Enthält die Mail ausschließlich Text? Oder ist sie vielleicht in HTML verfasst?").

MIME-Typen sind untergliedert in Kategorien:

digraph mimetypes {
	"MIME"  -> { "text"  "image" };
	"text"  -> { "plain" "html" };
	"image" -> { "png"   "xpm" };

	"plain" [ label = "text/plain:\nNur-Text-Dokument" ];
	"html"  [ label = "text/html:\nHTML-Seite" ];

	"png" [ label = "image/png:\nPNG-Bild" ];
	"xpm" [ label = "image/xpm:\nXPM-Bild" ];
}

MIME-Typen werden heute auch bei HTTP eingesetzt, damit der Browser auch ohne die eher von altmodischen Betriebssystemen (sic) bekannte Dateinamenserweiterung über den Typ einer Datei bescheid weiß.

3.5 Abschluss

Über den Header kann man also einige wichtige Informationen erhalten. Peinlich ist es natürlich für Firmen, die für ein bestimmtes Produkt per Mail werben, und dann selbst das Konkurrenzprodukt einsetzen (z.B. Werbung für MDollar, geschrieben in Mutt, einem Linux-Mailclient)...

Wer sich noch genauer mit dem Format von Mails beschäftigen möchte, sollte sich den RFC 2076 ansehen (der erste RFC zum Thema war RFC 822, der 1982 eingereicht wurde).

4 SMTP

Der Mail-Header ist jetzt erklärt, doch eine Frage wurde bisher nur verdrängt: Wie kommen die Mails eigentlich beim Empfänger an?

Diesen Part übernimmt das Send Mail Transport Protocol, SMTP, eines der ersten Protokolle, die es im Internet8, gab. Der erste RFC, der SMTP definierte, RFC 821, wurde bereits 1982 eingereicht.

Um einen Nutzer im Internet eindeutig zu adressieren, entwickelte man ein neues Adressierungsmuster: Man benutzt den Rechner, auf dem der Nutzer meistens anzutreffen ist (also eingeloggt ist), und seinen Login-Namen auf diesem als E-Mail-Adresse. Als Trenner fungiert das @-Zeichen.

Für's Verschicken und Empfangen sind zwei unterschiedliche Protokolle zuständig, beide in der Anwendungsschicht des OSI-Schichtenmodells angesiedelt: SMTP zum Versenden und POP3) zum Empfangen von Mails. Dieses Kapitel erklärt nur SMTP, nicht POP3.

4.1 Grundlagen

E-Mails wandern bei SMTP i.A. über viele Server ehe sie ihr Ziel erreichen. Dies kommt noch aus der Zeit der vielen Mailboxnetze, wo viele Internetverbindungen nicht permanent aktiv waren und so häufig andere Routen für die Mail-Übertragung genommen werden mussten.

digraph smtp_netzwerk {
  C1 [ label="Client" ];
  C2 [ label="Client" ];
  S1 [ label="Server" ];
  S2 [ label="Server" ];

  C1 -> S1 [ label="\nLokal\nSMTP" ];
  S1 -> S2 [ label="SMTP" ];
  S2 -> C2 [ label="\nPOP3\nIMAP4" ];

  rankdir=LR;
}

SMTP ist ein sehr einfaches, ASCII-basiertes Protokoll, das heißt, auch Menschen können zum Beispiel mit dem telnet-Befehl das Protokoll nutzen, obwohl in der Praxis Mail-Server diese Aufgabe übernehmen.

4.2 Envelope-Header

Damit jeder Server weiß, wohin er eine eingegangene Mail weiterleiten soll, muss dieser in den sogenannten Envelope-Header schauen.

Dieser Header hat noch nichts mit der Mail selbst zu tun! Der Server interessiert sich nicht für den Mail-Header wie aus dem vorherigen Kapitel, nur der Envelope-Header ist entscheidend für das Ziel der Mail.

Dies ist vergleichbar mit "traditioneller" Post: Der Briefträger schaut nur auf den Umschlag, nicht aber in den Brief9. Somit kann in dem Brief ein ganz anderer Empfänger angegeben sein, ohne das der Postbote davon erfährt:

#FIG 3.2
Landscape
Center
Metric
A4      
100.00
Single
-2
1200 2
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
	 0 0 4950 0 4950 3150 0 3150 0 0
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
	 1350 900 4950 900 4950 3150 1350 3150 1350 900
4 0 0 50 -1 16 14 0.0000 4 210 3495 450 450 Echtes Ziel: foobar@ACompany.com\001
4 0 0 50 -1 16 14 0.0000 4 210 2835 1800 1575 Hallo blabla@BCompany.com,\001
4 0 0 50 -1 16 14 0.0000 4 30 135 1800 1905 ...\001
4 0 0 50 -1 16 14 0.0000 4 210 1680 5400 540 Envelope-Header\001
4 0 0 50 -1 16 14 0.0000 4 165 1185 5400 2070 Mail-Header\001

4.3 Typischer Ablauf

Nun zu etwas Praxis: Wir werden eine Mail, die ein foo@A.org geschrieben hat, an bar@B.org weiterleiten. Dabei spielen wir den Mail-Server von A.org.

Also verbinden wir uns zuerst mit dem Standard-Port von SMTP, TCP-Port 25, von Rechner B.org:

Dann authentifizieren wir uns bei B.org mit dem Kommando HELO10:

Die 250 am Anfang der Antwort stellt dabei den Statuscode dar. 250C bedeutet dabei "alles in Ordnung", wie man an der englischen Antwort daneben auch erkennen kann.

Als nächstes erwartet B.org den Absender der E-Mail, und zwar den Envelope-Sender.

Damit B.org weiß, an wen er die Mail zustellen soll, kommt jetzt das Kommando RCPT (Abkürzung für Recipient):

Dieser Befehl kann auch mehrmals angewendet werden, um eine identische Mail an viele Empfänger zu schicken, ohne dass man jedesmal den Inhalt der Mail neu übertragen muss. Dies nutzen leider auch Spammer aus...

Nun erst wird mit der Übertragung der eigentlichen Mail begonnen:

Ab dem eingegebenen DATA kommt die eigentliche Mail, im Format wie im vorhergehenden Kapitel erläutert. Diese Mail-Header können hier beliebig gesetzt werden, ohne dass das irgendeine Software überprüft. Und ja, sie müssen nicht zwingend mit den Envelope-Headern übereinstimmen.

Theoretisch kann der Mail-Header sogar fehlen; Die Mail kommt trotzdem an, dafür sorgt ja der Envelope-Header.

Das Ende der Mail markiert ein einzelner Punkt auf einer Zeile11. Zum Schluss muss die Sitzung dann nur noch geschlossen werden:

In einem kleinem Schema zusammengefasst sieht eine typische SMTP-Sitzung also so aus:

digraph smtp_sitzung {
  A1 [ label="A.org" ]; B1 [ label="B.org" ];
  A2 [ label="A.org" ]; B2 [ label="B.org" ];
  A3 [ label="A.org" ]; B3 [ label="B.org" ];
  A4 [ label="A.org" ]; B4 [ label="B.org" ];
  A5 [ label="A.org" ]; B5 [ label="B.org" ];
  A6 [ label="A.org" ]; B6 [ label="B.org" ];
  A7 [ label="A.org" ]; B7 [ label="B.org" ];
  A8 [ label="A.org" ]; B8 [ label="B.org" ];
  A9 [ label="A.org" ]; B9 [ label="B.org" ];
  AA [ label="A.org" ]; BA [ label="B.org" ];
  AB [ label="A.org" ]; BB [ label="B.org" ];
  AC [ label="A.org" ]; BC [ label="B.org" ];

  AC -> BC [ label="\nTCP-Port 25" ];
  AB -> BB [ label="Banner:\n220 Ready.", dir=back ];
  AA -> BA [ label="Authentifikation:\nHELO hostname" ];
  A9 -> B9 [ label="Bestätigung:\n250 Ok.", dir=back ]
  A8 -> B8 [ label="Absender:\nMAIL FROM: <absender@hostname>" ];
  A7 -> B7 [ label="Bestätigung:\n250 Ok.", dir=back ]
  A6 -> B6 [ label="Empfänger:\nRCPT TO: <empfänger@ziel>" ];
  A5 -> B5 [ label="Bestätigung:\n250 Ok.", dir=back ]
  A4 -> B4 [ label="Mailheader und -body:\nDATA" ];
  A3 -> B3 [ label="Bestätigung:\n250 Ok.", dir=back ]
  A2 -> B2 [ label="Schließen der\nVerbindung:\nQUIT" ];
  A1 -> B1 [ label="Bestätigung:\n221 Good bye.", dir=back ]

  rankdir=LR;
}

4.4 Beispiel

Nun wollen wir die Theorie in die Praxis umsetzen:

Wir wollen eine E-Mail an iblech-ml@gmx.de im Namen von billg@gates.gat12 schicken.

Es gibt zwei Möglichkeiten, zu welchem Mailserver wir connecten: Entweder, wir verbinden uns mit einem sogenannten Open Relay. Ein Open-Relay ist ein SMTP-Server, der jede Mail annimmt und dann entsprechend weiterleitet. Solche Open-Relays waren früher sehr beliebt und legitim, da ein Internetzugang noch sehr viel gekostet hat und so jemand anderes die Mails weiter verschickt hat (zum Beispiel ein Server einer Universität). Es kümmert sich also das Open Relay um den weiteren Transport der Nachricht. Da heutzutage aber auch Spammer Open Relays für ihre Zwecke missbrauchen, sind viele Relays in Blacklists eingetragen weshalb diese Möglichkeit wegfällt.

Aber wir können uns auch gleich mit dem SMTP-Server des Empfängers verbinden, diese Möglichkeit funktioniert immer. Nichts anderes machen nämlich die Mailserver der ISPs. Wie man diesen Server herausfindet, ist im Kapitel über DNS, im Abschnitt über MX-Records beschrieben. Für jetzt soll es einfach genügen, wenn ich sage, dass der SMTP-Server von GMX mx0.gmx.de ist.

Sobald die Verbindung aufgebaut ist, werden wir uns als localhost identifizieren.

Bei der Eingabe des Envelope-Senders ist nun zu beachten, dass viele Mailserver die Syntax des Absenders überprüfen. Als Envelope-Sender ginge also zum Beispiel hallo@-@dd nicht durch. Deswegen müssen wir eine gültig aussehende E-Mail-Adresse als Absender wählen. Welcher Absender im Mail-Header dann steht, ist, wie schon erwähnt, vollkommen egal.

Also geben wir ein:

Wenn ich nun in mein Postfach schaue, werde ich eine Mail von The Imperor <billg@gates.gat> $$$ an You! Yes, you! <html> in meinem Postfach finden.

Wenn sich Mails also so einfach fälschen lassen -- wie stellt man dann trotzdem eine sichere Kommunikation her? Man muss jede ausgehende Mail digital verschlüsseln und signieren. In Mailclients integrierbare Programme wie GnuPG übernehmen diese Aufgabe. Eine sehr gute Einführung zu GnuPG gibt ein Bericht von Pro-Linux.

4.5 Befehlsübersicht

BefehlWirkung
HELO hostnameAuthentifizierung (SMTP)
EHLO hostnameAuthentifizierung (ESMTP)
MAIL FROM: <sender@host>Envelope-Sender
RCPT TO: <empfaenger@host>Envelope-Empfänger
DATABeginn der Mail
.Ende der Mail
QUITTerminierung der Verbindung

5 POP3

Das Personal Office Protocol, POP3, definiert in RFC 1939, ist praktisch das Gegenstück zu SMTP. Auch auf ASCII basierend, holt es die Mails vom Server ab anstatt sie zu versenden.

Auf Extended POP3, EPOP3, wird hier nicht eingegangen, da es im Wesentlichen nur neue Authentifizierungsmöglichkeiten unterstützt. Es gibt keine fundamentalen Unterschiede zwischen POP3 und EPOP3.

5.1 Grundlagen

Bei POP3 werden die Mails, welche zuvor via SMTP versendet wurden, auf dem Server so lange gespeichert, bis sie vom Client gelöscht werden13.

Ohne POP3 (oder einem ähnlichen Protokoll) müsste der Client permanent online sein, um E-Mails zu erhalten, was besonders früher wegen der hohen Onlinekosten wirklich nicht erwünscht war...

5.2 Typische POP3-Sitzung

POP3 ist eines der einfachsten Protokolle. Im Gegensatz zu SMTP, wo es Hunderte von Statuscodes gibt, findet man bei POP3 nur +OK und -ERR vor. Auch gibt es bei POP3 im Gegensatz zu zum Beispiel IMAP wenig Interaktivität; Der Client verlangt etwas (Liste der auf dem Server gespeicherten Mails oder eine gewünschte Mail), und der Server antwortet sofort.

Als Beispiel dient das einfache Abrufen samt anschließendem Löschen der Mails ohne einem Mail User Agent (MUA, z.B. mutt, mailx oder kmail).

Zuerst verbinden wir uns deshalb mit dem POP3-Server, der unsere Mails speichert, auf TCP-Port 110. Da wir meine Mails abholen wollen, ist der entsprechende POP3-Server pop3.web.de:

WEB.DE POP3-Server ist dabei der sogenannte Banner. In der Banner-Zeile wird oft auch die eingesetze Version des POP3-Servers übertragen.

Dann loggen wir uns ein:

Nun können wir eine Liste der auf dem Server gespeicherten Messages abrufen:

Um jetzt z.B. die zweite Mail herunterzuladen, geben wir ein:

Man erhält also den schon von SMTP bekannten Mail-Header samt Body (wieder mit einer Leerzeile getrennt), als Terminierung wird ein einzelner Punkt auf einer Zeile (.) benutzt.

Jetzt, wo der Client, also wir, die Mail erhalten hat, können wir die Mail löschen:

Um dann die Verbindung zu schließen tippen wir:

5.3 Protokollablauf

digraph pop3_sitzung {
  A1 [ label="Client" ]; B1 [ label="Server" ];
  A2 [ label="Client" ]; B2 [ label="Server" ];
  A3 [ label="Client" ]; B3 [ label="Server" ];
  A4 [ label="Client" ]; B4 [ label="Server" ];
  A5 [ label="Client" ]; B5 [ label="Server" ];
  A6 [ label="Client" ]; B6 [ label="Server" ];
  A7 [ label="Client" ]; B7 [ label="Server" ];
  A8 [ label="Client" ]; B8 [ label="Server" ];
  A9 [ label="Client" ]; B9 [ label="Server" ];
  AA [ label="Client" ]; BA [ label="Server" ];
  AB [ label="Client" ]; BB [ label="Server" ];
  AC [ label="Client" ]; BC [ label="Server" ];

  AC -> BC [ label="\nTCP-Port 110" ];
  AB -> BB [ label="Banner:\n+OK WEB.DE POP3-Server", dir=back ];
  AA -> BA [ label="Authentifikation:\nUSER username\nPASS passwort" ];
  A9 -> B9 [ label="Bestätigung:\n+OK", dir=back ]
  A8 -> B8 [ label="Liste gespeicherter Mails:\nLIST" ];
  A7 -> B7 [ label="Bestätigung:\n+OK", dir=back ]
  A6 -> B6 [ label="Anzeiger einer Mail:\nRETR id" ];
  A5 -> B5 [ label="Bestätigung:\n+OK", dir=back ]
  A4 -> B4 [ label="Löschen einer Mail:\nDELE id" ];
  A3 -> B3 [ label="Bestätigung:\n+OK", dir=back ]
  A2 -> B2 [ label="Schließen der\nVerbindung:\nQUIT" ];
  A1 -> B1 [ label="Bestätigung:\n+OK", dir=back ]

  rankdir=LR;
}

Das war's auch schon. So kann man auch ohne installierten MUA seine Mails abrufen und löschen, zum Beispiel wenn eine 100 MeB große Mail auf dem Server ist und man gerade keine Lust hat, wegen ISDN 243 Minuten zu warten.

5.4 Befehlsübersicht

BefehlWirkung
USER benutzernameLogin mit Benutzername...
PASS P455w0r7...und Passwort
LISTListe aller auf dem Server gespeicherten Mails
STATAnzahl der gespeicherten Mails samt ihrer Größe in Bytes
RETR idHolt eine Mail
DELE idLöscht eine Mail
QUITBeendet die Verbindung

6 IMAP4

Wie POP3 dient das Internet Message Access Protocol, IMAP, definiert in RFC 1730 dazu, die auf dem Server gespeicherten Mails abzurufen. Allerdings bleiben bei IMAP die Mails auch üblicherweise auf dem Server, das heißt der Server übernimmt die permanente Speicherung der Mails.

Dies ist besonders für Nutzer, die oft an verschiedenen Computern arbeiten, nützlich, da sie nun auf alle ihrer Mails von jedem Computer aus Zugriff haben.

Auch gibt es bei IMAP (server-seitige) Ordner, ein Fremdwort für POP3.

6.1 Technische Implementierung

Direkt nach dem Verbinden auf den Standardport 143 (TCP) des IMAP4-Servers (im Beispiel imap.web.de) empfängt man eine Bannermeldung:

Als nächstes loggen wir uns ein:

Da bei IMAP theoretisch mehrere Befehle gleichzeitig ausgeführt werden können, bedient man sich von IDs, die jedem Befehl voranstehen müssen (hier A001). Die ID kann mehr oder weniger frei gewählt werden, es dürfen nur keine Leerzeichen oder andere Sonderzeichen in der ID enthalten sein. Auch muss die nächste ID nicht unbedingt "höher" (zum Beispiel A002) sein.

Nun können wir einen Ordner auswählen:

inbox ist der Standard-Ordner, "Posteingang". Aus der Antwort können wir sehen, dass eine Nachricht noch neu ist (UNSEEN 1).

Bevor wir allerdings die Nachricht herunterladen, können wir schauen, wie groß die Mail (wie bei POP3 angegeben in Octets, also Bytes) ist:

Nun können wir die Übertragung des Headers der Mail einleiten:

Hier wird das Ende, nicht wie bei SMTP, POP3 oder NNTP mit einem Punkt, sondernmit ) (runde Klammer zu) markiert.

Auch der Body der Mail ist schnell geholt:

Hätten wir die gesamte Mail auf einmal holen wollen, hätten wir auch

benutzen können.

Nun kann die Mail gelöscht (obwohl das bei IMAP, wie oben erwähnt, eher unüblich ist) werden:

Mit diesem Befehl setzen wir den Status der Mail auf "zum Löschen bereit". Mit

wird die Mail dann endgültig gelöscht. Nachdem die Mail gelöscht ist, verschieben sich auch die Nummern der Mails nach vorne, das heißt Nachricht Nummer 2 ist nach der Löschaktion die erste Nachricht.

Mit LOGOUT beenden wir die Verbindung:

6.2 Befehlsübersicht

BefehlWirkung
LOGIN "name" "pass"Login
SELECT "ordner"In Ordner wechseln
FETCH nummer RFC822.SIZEMailgröße anzeigen
FETCH nummer RFC822.HEADERMailheader anzeigen
FETCH nummer BODY.PEEK[TEXT]Mailbody anzeigen
FETCH nummer RFC822Gesamte Mail anzeigen
STORE nummer +FLAGS (\Deleted)Mail zum Löschen markieren
EXPUNGEAlle als gelöscht markierten Mails löschen
LOGOUTVerbindung schließen

6.3 Abschluss

Mit IMAP steht Telnettern nun ein weiteres Protokoll zum Abholen von Mails zur Verfügung. Zur Übersicht nochmal eine komplette Beispielsitzung: