jens.hatlak.de / Über mich  
Atari   PHP  
Dreamweaver Manual   Linux  
Akronyme   Mozilla  
  SciTE  
  FASTA-Parser  
  Ich spreche...  

Ich spreche... Internetprotokolle

Ich selbst spreche eigentlich nur Deutsch und Englisch, aber das nur nebenbei.

Einige der am weitesten verbreiteten und am häufigsten genutzten Internetprotokolle sind absichtlich syntaktisch so einfach gestrickt, dass sie für Menschen lesbar sind. Aber nicht nur das — wir können solche "Sprachen" auch schreiben. Im Zusammenhang mit Echtzeitkommunikation über eine offene Verbindung könnte man auch sagen: "sprechen".

Das "Gesprochene" wird auf der Gegenseite jedoch von einer Maschine gelesen. Diese versteht nur klar und eindeutig formulierte, syntaktisch korrekte Kommandos. Daher ist die strikte Einhaltung der Syntax unabdingbar. Die kleinste Abweichung führt fast immer dazu, dass das gesamte Kommando nicht verstanden wird.

Die genaue Syntax ist in sogenannten RFCs festgelegt. Diese sind im Allgemeinen jedoch sehr umfangreich. Ihr eigentlicher Zweck ist es, als Referenz für standardkonforme Implementierung des jeweiligen Protokolls zu dienen. Sie sind daher oft so detailliert, dass es schwer fällt die Grundregeln der Kommunikation daraus zu extrahieren. Diese Seite soll hier Abhilfe schaffen.

Mein Ziel ist keine eine umfassende Einführung. Vielmehr sollen nur die absoluten Grundlagen für eine funktionierende Kommunikation mit einem Server aufgezeigt werden. Wer hierzu weitere Informationen beisteueren kann, ist herzlich eingeladen, mich per Mail zu kontaktieren!

Protokolle

Die folgenden Internetprotokolle erfreuen sich großer Beliebtheit. Ich selbst habe mit jedem einzelnen davon schon viel gearbeitet — meistens aber mit Hilfe eines passenden Clients.

Will man nun zu Testzwecken oder aus Neugier einmal selbst mit einem Server reden, muss man zunächst nur zwei Dinge kennen: den Servernamen und den Zielport. Mit diesen Informationen kann man dann mittels des Kommandozeilenprogramms telnet direkt eine Verbindung aufbauen:

telnet <host> <port>

Im Falle von HTTP könnte das also jeder beliebige Webserver sein, zusammen mit der Portnummer 80.

Protokoll Standardport RFCs
FTP 21 959
SCP 22 -
SMTP 25 821, 2821
HTTP 80 1945, 2616
POP3 110 1939
IMAP 143 2060, 3501

In RFC 822 (Standard for the Format of ARPA Internet Text Messages) bzw. RFC 2822 (Internet Message Format) ist außerdem beschrieben, wie die in Protokollen wie HTTP benutzten Header typischerweise aufgebaut sind.

Im Folgenden bedeutet ein > eine Ausgabe des Servers und ein < eine Benutzereingabe, wobei jede Eingabe durch Drücken der Return-Taste abgeschlossen wird.

FTP (Port 21)

Das File Transfer Protocol trennt zwischen Kontroll- und Datenverbindung. Über die Kontrollverbindung werden die Kommandos abgesetzt; für die eigentlichen Daten wird dann aber eine eigene Verbindung benötigt. Standardmäßig geht der Server davon aus, dass er den Client auf einem beliebigen unprivilegierten Port erreichen kann. Das stimmt aber in Zeiten von NAT schon lange nicht mehr. Deshalb gibt es den Passive Mode, bei dem der Server einen Port öffnet.

> 220 remoteServerName
< USER myUser
> 331 Password required for myUser.
< PASS myPassword
> 230 User myUser logged in.
< PWD
> 257 "/some/path" is current directory.
< TYPE A
> 200 Type set to A
< PASV
> 227 Entering Passive Mode (w,x,y,z,a,b)
< LIST

IP und Port sind in der Form w,x,y,z,a,b angegeben, wobei w,x,y,z sich einfach zur IP-Adresse w.x.y.z wandeln lässt und a,b den Port in High- und Low-Bytes angibt. Beispiel: 237,206 ist EDCE hexadezimal, was Port 60878 entspricht.

Kontaktiert man den Server nun auf diesem Port, bekommt man das Ergebnis der Anfrage. Bei der Kontrollverbindung führt das dann zu folgender Ausgabe:

> 150 Opening ASCII mode data connection for file list
> 226 Transfer complete.

SCP - scponly

Für Secure Copy gibt es kein RFC, insofern ist es schwierig hier Informationen zum Ablauf zum finden. Da für das Protokoll zudem normalerweise ein SSH-Server benötigt wird, und die Verbindung zu diesem verschlüsselt ist, macht ein Telnet-Verbindungsversuch auf Port 22 entsprechend wenig Sinn.

Mit Programmen wie scponly kann man jedoch Benutzeraccounts so einschränken, dass lediglich SCP erlaubt ist. In diesem Fall kann man scponly auf dem Server manuell starten und dann unverschlüsselt so agieren, als hätte z.B. WinSCP eine Verbindung aufgebaut.

SCP arbeitet dabei im Prinzip einfach normale Shell-Kommandos wie ls, cd oder echo ab. Um zu erkennen, wann ein Kommando fertig ist, muss dabei die Zeile, mit der sich der Server identifiziert, nach jeder Ausfürung ausgegeben werden.

> This is the server's ID line
< myCommand ; echo "This is the server's ID line"

WinSCP-Beispiel:

> WinSCP: this is end-of-file:0
< ls -la --full-time ; echo "WinSCP: this is end-of-file:0"

SMTP (Port 25)

Das Simple Mail Transfer Protocol dient dem Versenden von E-Mails. Um eine Mail zu verschicken, muss man sich als Absender identifizieren und mindestens einen Empfänger angeben.

> 220 serverURI SMTP dateString
< HELO someString
> 250 serverName Hello someString [clientIP]
< MAIL FROM:<senderEmail>
> 250 OK
< RCPT TO:<receiverEmail>
> 250 Accepted
< DATA
> someUsageAdvice
< arbitraryNumberOfLinesOfMailContents
< .
> 250 OK id=someString
< QUIT

Lehnt der Server den Absender ab (Relaying not allowed), muss man sich gegenüber dem Server authentifizieren. SMTP selbst sieht dazu kein Verfahren vor; üblicherweise werden hier dann Mechanismen wie SMTP after POP (temporäre Freischaltung der IP-Adresse nach POP-Login) eingesetzt.

Bei ESMTP (RFC 1869) gibt es die Erweiterung SMTP-Auth. Hier meldet man sich statt HELO mit EHLO, bekommt dann als Antwort die Liste unterstützter Authentifizierungsverfahren (Challenge-Response, Plain etc.), sucht sich eines aus und verwendet dieses im Zusammenhang mit dem Kommando AUTH. Alles außer PLAIN hat dann die Chance als Authentisierung akzeptiert zu werden.

Im Folgenden wird beispielhaft das Einloggen mittels der Methode LOGIN (Base64-Kodierung, keine Verschlüsselung!) beschrieben:

> 220 serverURI ESMTP dateString
< EHLO serverURI
> 250 AUTH CRAM-MD5 LOGIN PLAIN
< AUTH LOGIN
> 334 aBase64EncodedString
< myBase64EncodedUsername
> 334 anotherBase64EncodedString
< myBase64EncodedPassword
> 235 OK
< MAIL FROM: <senderEmail>
... as above

HTTP (Port 80)

Das Protokoll für die Kommunikation mit Webservern ist zustandslos, d.h. jede einzelne Anfrage ist völlig unabhängig von anderen.

Eine Anfrage kann in einem der Formate der Versionen 0.9, 1.0 oder 1.1 erfolgen. Angegeben sind hier jeweils die Minimalanforderungen für eine gültige Anfrage, vor dem abschließenden Return können aber weitere Headerzeilen angegeben werden. Das Ergebnis ist in jedem Fall die HTML-Seite (oder sonstige Daten), angeführt von den Antwortheadern des Servers.

HTTP 0.9

< GET /
< 

HTTP 1.0

< GET / HTTP/1.0
< 

HTTP 1.1

< GET / HTTP/1.1
< Host: www.server.com
< 

Im Unterschied zu den Versionen 1.0 und 1.1 gibt es für HTTP 0.9 kein RFC. Wie man sieht, wird hierbei die Version auch gar nicht angegeben. Eine explizite Angabe ist also nur für Versionen ab 1.0 vorgesehen. Dann legt diese Angabe jedoch auch fest, in welcher Protokollversion die Antwort des Servers erfolgen darf. Auf eine HTTP 1.0-Anfrage darf der Server nur mit Version 1.0 antworten; bei einer HTTP 1.1-Anfrage kann er mit 1.1 oder 1.0 antworten.

Wie man sieht, verlangt HTTP 1.1 die explizite Angabe des Servers, der befragt werden soll. Dieser Name muss nicht unbedingt mit dem DNS-Namen übereinstimmen, der für die Namensauflösung benutzt wurde (Stichwort Virtual Hosts). Ein weiterer wichtiger Unterschied zwischen den beiden Versionen ist, dass Clients, die eine HTTP 1.1-Anfrage stellen, die Transferkodierung "chunked" unterstützen müssen. Auf HTTP 1.0-Clientanfragen darf ein HTTP 1.1-Server hingegen nicht mit einer Angabe zur Transferkodierung antworten. Für einfache Skripte bietet es sich daher an, Anfragen grundsätzlich in der Version 1.0 zu stellen.

GET-Parameter

In der Anfrage-URL können Formulardaten wie folgt kodiert werden:

< GET /music/query.php?year=1968&name=The%20Beatles&submit=Search HTTP/1.0
< 

Der erste Parameter wird also durch ein Fragezeichen vom Skriptnamen getrennt, alle folgenden dann durch ein Kaufmannsund (&) und die Namen von den Werten durch ein Gleichheitszeichen (=). Leer- und andere Sonderzeichen müssen mittels des urlencoded-Formats (Prozentzeichen plus zwei Ziffern für die Position im ASCII-Zeichensatz) kodiert werden.

URLs können nicht beliebig lang werden, da einige relevante Clients Beschränkungen diesbezüglich aufweisen (IE: 2083 Zeichen). Für längere Anfragen, z.B. Binärdaten wie Dateien, muss daher POST statt GET verwendet werden.

POST-Request

< POST / HTTP/1.0
< Host: www.server.com
< Content-Length: 30
<
< This is a sample POST request.
< 

Bei einem POST-Request folgen auf die Request-Header eine Leerzeile und die POST-Daten. Wenn diese analog zu GET-Parametern Formulardaten widerspiegeln sollen, sollte man den Request-Header Content-Type: application/x-www-form-urlencoded benutzen. Um dem Server einen Hinweis zu geben, wieviele Bytes an POST-Daten dieser zu erwarten hat, sollte man diese Information im Content-Length-Header angeben.

Da GET-Parameter in der angeforderten URL kodiert und POST-Parameter im Request-Body angegeben werden, kann man beide Formularübermittlungstypen kombinieren.

Ein nützliches Werkzeug zum Erfassen von HTTP-Requests und -Reponses ist übrigens Live HTTP Headers, eine Erweiterung für Firefox/SeaMonkey.


POP3 (Port 110)

Das Post Office Protocol dient dem Abrufen von E-Mails aus dem eigenen Postfach auf dem Mailserver.

Nach dem Einloggen kann man sich eine Übersicht ausgeben lassen (STAT: Anzahl der Nachrichten und Gesamtgröße der Daten in Bytes) oder eine Liste der Nachrichten (LIST: Je eine Zeile pro Nachricht mit Nummer und Größe in Bytes, insgesamt abgeschlossen durch einen einzelnen Punkt).

> +OK Hello there.
< USER myUser
> +OK Password required.
< PASS myPassword
> +OK logged in.
< STAT
> +OK 4 3210
< LIST
> +OK someInfoString
> 1 750
> 2 1630
> 3 550
> 4 280
> .

Anschließend kann man mit Kommandos wie RETR (Nachricht abrufen) oder DELE (Nachricht löschen) Aktionen mit einzelnen E-Mails durchführen, wobei jeweils die Nummer der Nachricht (siehe LIST) anzugeben ist.


IMAP (Port 143)

Das Internet Mail Access Protokoll versucht die Schwächen von POP3 zu umgehen, das wenig geeignet ist, Nachrichten auf dem Server zu verwalten. Mit IMAP kann man neben der Inbox weitere Ordner anlegen, gemeinsam darauf zugreifen (Folder Sharing) und erweiterte Funktionen nutzen, wie z.B. eindeutige Nachrichten-IDs (UIDs) statt fortlaufender Nummern oder den neuen Status Ungesehen (UNSEEN).

> * OK serverName serverDescription server ready
< AUTH LOGIN myUser myPassword
> AUTH OK User logged in
< foo LIST . *
> foo OK Completed (0.000 secs 1 calls)
< foo EXAMINE myMailbox
> * FLAGS (someFlags)
> * OK [PERMANENTFLAGS ()]
> * 1 EXISTS
> * 0 RECENT
> * OK [UIDVALIDITY 1000000000]
> * OK [UIDNEXT 1234]
> foo OK [READ-ONLY] Completed
< foo STATUS myMailbox (MESSAGES)
> * STATUS Inbox (MESSAGES 1)
> foo OK Completed
< foo LOGOUT
> * BYE LOGOUT received
> foo OK Completed

myMailbox kann hier z.B. Inbox sein.

 

Valid HTML 4.0!
Jens Hatlak
9. März 2006