zurück zum Artikel

Ausweichmanöver

| Hagen Paul Pfeifer

TCP und UDP begründen als dominierende Internet-Protokolle eine solide, laufend an neue Herausforderungen angepasste Infrastruktur.

DCCP-Kommunikationsabfolge

Das Internet ist bekanntlich kein für die Ewigkeit entworfener, allen Widrigkeiten trotzender Rechnerverbund. Über Jahrzehnte weiterentwickelte Algorithmen bilden ein stabiles Fundament aus eng miteinander verzahnten Teilen. Dem Internet-Protokoll (IP [1]) liegt das Prinzip des verbindungslosen Paketdienstes zu Grunde, also der Datentransport mittels Routing [2]. IP transportiert aber auch Steuerungsinformationen. Die Transportschicht baut auf Funktionen der Netzwerkschicht auf und erweitert sie um Eigenschaften wie verbindungsorientierte, byteorientierte, vollduplexfähige Datenübertragung (TCP) oder dessen verbindungsloses Pendant (UDP).

Das Verhältnis von verbindungsorientiertem zu verbindungslosem Verkehr hat eine grundlegende Bedeutung. TCP enthält eine Stauerkennung (Congestion Control), UDP nicht. Würde ein Großteil der Daten über UDP transportiert, würde das Internet zusammenbrechen (RFC 3714 [3], wie alle RFCs unter anderem zu finden via www.ietf.org/rfc.html [4]): Router [5] wären hoffnungslos überlastet, könnten dies aber nicht anzeigen, weil UDP es nicht vorsieht.

Ein Stau entsteht bei der Überlastung eines Routers; sein Paketpuffer ist erschöpft. Um Abhilfe zu schaffen, verwirft er im einfachsten Fall Pakete aus der Warteschlange (Drop Tail). Die beteiligten TCP-Instanzen reagieren im weiteren Verlauf mit einem Algorithmus, der die Senderate minimiert. Das gleichzeitige Verwerfen von Paketen aus der Queue führt zu einem neuen Problem, der "globalen Synchronisation": Alle betroffenen TCP-Instanzen gehen zum selben Zeitpunkt in "Fast Recovery" mit der Folge, dass auf eine Zeitspanne mit wenig Auslastung eine gebündelte Datenübertragung (Burst [6]) folgt. Random Early Detection (RED) erweitert diesen Ansatz. Es versucht drohende Staus früh zu erkennen und verwirft einzelne Pakete vorzeitig unter Zuhilfenahme eines Schwellenwertes.

Auf diesem Algorithmus baut die Explicit Congestion Notification (ECN) auf ­ mit einem kleinen, aber entscheidenden Unterschied. Anstatt Pakete zu verwerfen, markiert sie Pakete bei Staugefahr und fordert den Sender damit auf, die Übertragung zu bremsen. Der Vorteil liegt auf der Hand: Das erneute Übertragen verworfener Pakete entfällt. ECN nutzt zur Markierung zwei Bit im DiffServFeld (RFC 2474 [7], früher ToSByte) und zwei Bit im TCP-Header. Verständlicherweise muss der komplette Kommunikationspfad ECN-kompatibel sein. Es darf keinen Router oder Endknoten aus dem Takt bringen, wenn "mysteriöse" Bits gesetzt sind (http://urchin.earth.li/ecn/ [8] listet Soft- und Hardware auf, die damit Probleme haben). Linux ab Kernelversion 2.4 und Cisco IOS ab Version 12.2 unterstützen ECN.

Ein anderer Ansatz zum Anzeigen von Stausituationen besteht im Versenden von Nachrichten namens "ICMP [9] Source Quench" (RFC 792 [10]). Die Endsysteme erfahren auf diese Weise, dass Kapazitätsgrenzen erreicht sind. Bei einer akuten Überlastung zusätzlichen Verkehr zu erzeugen, erscheint jedoch wenig sinnvoll. Für die Motivation eines Streaming-Protokolls wie DCCP (Datagram Congestion Control Protocol), das als Transportprotokoll auf der gleichen Ebene wie TCP oder UDP arbeitet, ist ein Blick auf deren Eigenschaften hilfreich.

TCP, im RFC 793 [11] ursprünglich spezifiziert und durch zahlreiche Erweiterungen den Gegebenheiten und Technologieveränderungen angepasst, ist sozusagen die Mutter aller Protokolle. Es weist fünf charakteristische, im Folgenden genauer dargestellte Eigenschaften auf: Bytestrom- und Verbindungsorientierung, Flusskontrolle, Zuverlässigkeit und Vollduplex-Übertragung ­ zwei Kommunikationspartner können gleichzeitig sowohl Daten senden als auch empfangen.

Das Betriebssystem stellt Anwendungen eine Bytestrom-Schnittstelle zur Verfügung. Dank dieser Abstraktionsebene ist TCP so erfolgreich, da Anwendungsentwickler Netzverbindungen auf ebenso einfache Weise nutzen können wie Dateien. Verbindungsorientierte Eigenschaften ergeben sich aus der Tatsache, dass eine virtuelle Verbindung mit dem Kommunikationspartner den Datenaustausch einleitet (Dreiwege-Handshake).

Jede TCP-Instanz verfügt für die Speicherung von Daten über einen Puffer einer bestimmten initialen Größe. Wenn ihn die Anwendung nicht oder zu langsam ausliest, kann er überlaufen. Um das zu vermeiden, erhält der Kommunikationspartner bei jedem Datenaustausch Informationen über die aktuelle Größe des verbleibenden Puffers (Sliding-Window-Verfahren).

Mit jedem Byte im Datenstrom korrespondiert eine Sequenznummer. Der Empfänger muss empfangene Daten quittieren (Acknowledge). Dieses Verfahren gewährleistet, dass Datensegmente am Ende in die richtige Reihenfolge kommen. Bleiben Bestätigungen aus oder wiederholen sie sich, liegt ein Fehlverhalten vor. Die angemessene Reaktion kann etwa ein Bremsen der Übertragung sein. Die Prüfsumme im TCP-Header deckt außerdem Übertragungsfehler im Paketkopf sowie in den Nutzdaten auf.

Das User Datagram Protocol [12], der kleine, funktional beschnittene Bruder von TCP, ist nicht weniger wichtig im Internet-Protokollgespann. UDP arbeitet als minimalistisches Transportprotokoll (RFC 768 [13]) und erweitert IP nur minimal, unter anderem um eine Prüfsumme über die Anwendungsdaten und eine Adressierung der Anwendung (Quell- und Zielport). Es kennt keine Stauprävention oder ähnliche Korrekturmechanismen.

UDP eignet sich wegen seines geringen Overhead [14] im Vergleich zu TCP für Anwendungen wie DNS [15], die einen minimalen, kurzzeitigen Datenaustausch betreiben, und wenn die Zuverlässigkeit keine allzu wichtige Rolle spielt oder sich sogar nachteilig auswirken kann. Ein typisches Beispiel ist die Übertragung von Audiodaten, die den Verlust einzelner Pakete besser verkraftet als enorme Latenzen. Wiederholte Übertragungen von Datenpaketen würden zu einer akustischen Katastrophe führen. Aktuelle Entwicklungstrends erfordern differenziertere Protokolleigenschaften, als TCP und UDP sie definieren. Zu den Anwendungen, die eine minimale Verzögerung (Jitter) verlangen und der Zuverlässigkeit einen minderen Stellenwert einräumen, gehören IP-Telefonie, Streaming Radio oder Onlinespiele. Mit der Beliebtheit solcher Dienste, die langanhaltende Verbindungen aufbauen, Engpässe aber nicht erkennen können, wächst allmählich der Druck, dem entgegenzuwirken (RFC 3714 [16]).

Derzeit bildet in der Regel UDP die Protokollgrundlage für die neuen Dienste. Es bietet den großen Vorteil, dass ein Paketverlust den Datenstrom nicht unterbricht, als Nachteil erweist sich aber das Fehlen einer Stauvermeidung. Der Ansatz eines solchen Algorithmus auf Anwendungsebene ist aus mehreren Blickwinkeln negativ zu bewerten. Es können Sicherheitslücken entstehen, wenn unzureichend getestete Insellösungen zum Einsatz kommen. Außerdem gibt es Durchsatznachteile gegenüber einer Nutzung des Kernadressraums, und Inkompatibilitäten bei späteren Erweiterungen lassen sich nicht ausschließen.

Solch hohe Einstiegshürden für eine proprietäre Stauvermeidung auf Anwendungsebene verleiten Entwickler in der Regel dazu, einfach vollständig darauf zu verzichten. Das beliebte Session Initiation Protocol [17] (SIP, RFC 2543 [18]) sieht jedoch eine eigentlich unvollständige Staukontrolle auf Basis des "exponential backoff" bei der erneuten Übertragung und bei der Begrenzung von Paketen vor.

Mit dem RFC 4340 [19] liegt mittlerweile eine Protokollspezifikation vor, die sich den Beschränkungen von UDP annimmt: DCCP, ein neues Protokoll, das eine Stauvermeidung bei der Übertragung von unzuverlässigen Datagrammen ermöglicht. Vereinfacht ausgedrückt handelt es sich um UDP, angereichert mit Staukontrollalgorithmen und anderen technischen Ingredienzen aus der Protokollküche.

DCCP soll Designfehler anderer Protokolle von vornherein vermeiden. Den Autoren zufolge darf es keine anwendungsspezifischen Informationen enthalten, sondern vielmehr nur absolut notwendige Funktionen [20]. Aus den genannten Gründen ergeben sich die im Folgenden beschriebenen Eigenschaften:

DCCP verwendet CCIDs für die Auswahl des Staukontrollverfahrens. Derzeit sind zwei davon definiert: CCID 2 (Standard bei neu aufgebauten Verbindungen) und CCID 3. Soll ein alternativer Mechanismus zum Einsatz kommen, muss dies der Kommunikationspartner erfahren. Die AlgorithmusAuswahl erfolgt pro Richtung, die Teilverbindung A-B kann ein anderes Verfahren nutzen als die Teilverbindung B-A.

Im IETF-Draft als "TCP-like Congestion Control" bezeichnet, bildet DCCP die Eigenschaften von TCP in Bezug auf Stauvermeidung nach. Außerdem unterstützt es Ack-Vektoren, einen an selektive Acknowledgements (SACK) angelehnten Algorithmus. Im Unterschied zu "Vanilla TCP" findet die Staukontrolle auch bei Bestätigungspaketen [22] Anwendung. Das ergibt einen hohen Durchsatz, allerdings mit massivem Einbruch in Stausituationen, da sich wie bei TCP das Staukontrollfenster halbiert. CCID 2 eignet sich daher für Anwendungen, die ein Maximum an Durchsatz fordern und im Gegenzug von sich aus einen mehr oder minder konstanten Datenfluss gewährleisten, etwa durch kurzzeitiges Zwischenspeichern. Der Entwurf von CCID 2 liefert ausführliche und umfassende Informationen und sei ausdrücklich empfohlen.

CCID 3 (TFRC, TCP-friendly Rate Control) ergänzt CCID 2 und eignet sich für einen gleichmäßigen Datenstrom. Auf Änderungen der Übertragungskapazität reagiert es daher langsamer. Anwendungen, die diesem Verhalten den Vorzug geben, sollten auf CCID 3 zurückgreifen, müssen den Protokolleigenschaften aber durch eine möglichst gleichmäßige Übertragung und identische Paketgrößen entgegenkommen. Dazu gehören aktuelle VoIP [23]-Protokolle auf Anwendungsebene.

Im DCCP-Entwurf finden zahlreiche Sicherheitsaspekte Berücksichtigung. Dazu gehören PMTU Discovery, die zufällige Wahl der Sequenznummer und ein "Init Cookie", das die Speicherung von Zuständen vermeidet, bis der Dreiwege-Verbindungsaufbau abgeschlossen ist.

Außerdem verfügt DCCP über eine Vielzahl von Eigenschaften, die sich besonders gut für den Einsatz hinter Firewalls eignen – anders als verbindungslose Protokolle wie UDP. Es baut eine virtuelle Verbindung auf, eine ideale Grundlage für das Connection Tracking. Falls eine Anwendung nicht mit dem gewohnten Port kommuniziert, liefert das Servicefeld im Header zu-dem die Information, um welches Anwendungsprotokoll es sich dabei handelt. In Zeiten, da Administratoren ihr Teilnetz in ein enges Korsett schnüren, ein nicht zu vernachlässigender Aspekt.

Seit Kernelversion 2.6.13 unterstützt [24] Linux DCCP – zumindest in Teilen. Daher liegt eine Portierung bestehender Applikationen durchaus nahe. Aber Achtung: Zahlreiche Stellen im Kernel sind mit "FIXME" gekennzeichnet, und nicht jede Funktion ist bisher normgerecht, vollständig oder optimal implementiert. So sind die CCID-2-Funktionen noch nicht in den Kernel gewandert. Auch Feature Negotiation, also das Aushandeln der gewährten und zu benutzenden Funktionen, ist nicht vollständig integriert. Interessierte sollten dafür den Kernelzweig von David Miller via git nutzen. Derzeit existieren auch Patches für FreeBSD, Net- und OpenBSD sollen folgen (www.jp.nishida.org/dccp/ [25]).

Die Netfilter-Distribution enthält seit August 2005 ein Modul, das die Zusammenarbeit mit Firewalls erleichtert, indem es das Filtern nach DCCP-Diensten erlaubt.

Eine Connection-Tracking-Erweiterung, nötig für ein Firewall [26]-Regelwerk mit Zustandserkennung, befindet sich darüber hinaus in der Warteschlange und sollte bald das Licht der Öffentlichkeit erblicken. Aktueller Software mangelt es noch an Unterstützung für DCCP. Immerhin enthalten gängige Werkzeuge für die Netzwerkanalyse sie zumindest in den Betazweigen oder in Form von Patches. Dazu gehören iproute2, tcpdump, netcat und ethereal.

Wer sich intensiver mit DCCP befassen möchte, dem sei dafür der Linux-Kernel empfohlen. Er enthält nicht nur eine Draft-konforme Implementierung, sondern glänzt auch durch einen ästhetischen und sauberen Programmierstil.

DCCP löst viele Probleme, die mit der wachsenden Beliebtheit von Streaming Anwendungen einhergehen. Neue Übertragungsverfahren wie UMTS [27] und die Verlagerung der klassischen Telefonie zu VoIP verstärken diese Notwendigkeit. Die Anfangszeit von TCP/IP hat gezeigt, dass eine fehlende Stauvermeidung den Kollaps des Internet zur Folge haben kann. Entwickler können die Portierung von UDP zu DCCP in wenigen Stunden vollziehen ­ es besteht also eigentlich kein Grund, DCCP nicht zu verwenden.

Nahezu alle UDP-Anwendungen können Vorteile aus diesem potenten Protokoll ziehen. Eine Ausnahme bilden Multicasting sowie Protokolle, die kaum Daten austauschen und für die der Verbindungsaufbau einen unzumutbaren Overhead mit sich brächte. Darunter fällt unter anderem DNS.

Nun gilt es abzuwarten, ob und mit welcher Unterstützung die großen Firmen der Branche reagieren. In Ermangelung alternativer und proprietärer Ansätze könnten Netz- und Betriebssystemhersteller schon bald neue Produkte mit dem Etikett "DCCP-fähig" vermarkten. (rek [28])

DCCP-Kommunikationsabfolge

[29]DCCP-Kommunikationsabfolge

Das nebenstehende DCCP-Sequenzdiagramm zeigt den Verbindungsaufbau, den eigentlichen Datenversand und den Verbindungsabbau. Der Client sendet zunächst einen DCCP-Request und leitet damit den Verbindungsaufbau ein. In der Regel teilt er dem Server mit, welcher Staukontrollalgorithmus (CCID) zum Einsatz kommen soll. Als Erweiterung zu TCP, das eine Verbindung zur Anwendungssoftware über Ports impliziert, erweitert DCCP den generischen Paketkopf um ein Service-Code-Feld. Es liefert Informationen über das konkrete Anwendungsprotokoll ­ ein Vorteil für Firewalls und flexibler als das Konzept der "Wellknown Ports". Als Antwort sendet der Server ein DCCP-Response-Paket ­ die zweite Phase des DreiwegeVerbindungsaufbaus. Er bestätigt vom Client vorgeschlagene Optionen oder passt sie an und versendet selbst Optionen. Der Service-Code muss mit denen im DCCP-Request übereinstimmen. Sollte der Server den Verbindungswunsch ablehnen, würde er mit einem DCCP Reset antworten (siehe Grafik). Den Grund für die Ablehnung, zum Beispiel "Too Busy", kann er im Reset-Code kodieren. DCCP-Ack markiert das Ende des Verbindungsaufbaus. Der Client bewilligt Server-Optionen oder nimmt Anpassungen vor. Während des gesamten Verbindungsaufbaus lassen sich Anwendungsdaten übermitteln. Nun beginnt der Datenaustausch mit Paketen namens DCCP-Data/DCCP-DataAck, je nach dem gewählten Staukontrollalgorithmus bestätigt mit DCCP-Ack. Mit einem DCCP-CloseReq leitet der Server den Verbindungsabbau ein. Sollte der Client diesem Wunsch zuvorkommen, entfällt dieser Schritt, und der Client sendet unaufgefordert ein DCCP-Close, anderenfalls als Bestätigung der Close-Aufforderung. Zu guter Letzt kann ein DCCP-Reset, anders als dessen TCP-Pendant, einen Grund für den Verbindungsabbau angeben. Bei einem normalen Abbau gilt der Reset-Code 1. Für die "twice maximum segment lifetime" (2MSL, in diesem Fall vier Minuten) verbleibt der Client im TimewaitStatus. Auf diese Weise können Pakete, die sich längere Zeit im Netz befinden, eine neu aufgebaute Verbindung nicht beeinträchtigen.

[30]DCCP-Paketformate

Die Abbildung zeigt exemplarisch das Format des DCCPResponse-Paketes. Der Server sendet es als zweites Paket des Dreiwege-Verbindungsaufbaus an den Client.

CCVAL kodiert Informationen über den verwendeten Staukontroll-Mechanismus (CCID).

CsCOV spezifiziert jene Teile des Paketes, die eine Prüfsumme schützen soll. Paketkopf und dessen Optionen sind Pflicht, optional lassen sich darüber hinaus alle oder ein Teil der Anwendungsdaten schützen.

Das Feld Type spiegelt die Art des Paketes wider. TCP kennt die Flags SYN, ACK, RST, PSH, URG und FIN. DCCP erweitert dieses Modell, indem das Setzen eines Typs einen Sub-Header nach sich zieht, der zusätzliche Informationen kodiert. Beispielsweise kann der Sub-Header DCCP-Reset den Grund für einen Verbindungsabbau angeben, etwa eine Server-Überlastung.

Derzeit sind folgende Typen spezifiziert:

0 DCCP-Request

1 DCCP-Response

2 DCCP-Data

3 DCCP-Ack

4 DCCP-DataAck

5 DCCP-CloseReq

6 DCCP-Close

7 DCCP-Reset

8 DCCP-Sync

9 DCCP-SyncAck

Die Abbildung zeigt ein DCCP-Response-Paket, dessen Type-Feld mit der Kennung 1 belegt ist.

X: Dieses Bit verdeutlicht die Verwendung erweiterter Sequence-und Acknowledge- Nummern (48 Bit). Sonst finden 24 Bit Verwendung. DCCP-Data, DCCP-Ack und DCCP-DataAck können diese Auswahl treffen, alle anderen Typen müssen 48 Bit verwenden. Damit lässt sich bei schnellen Verbindungen im Falle längerer Verzögerungen ein Überlaufen vermeiden (TCP-Stichwort: Protection Against Wrapped Sequence Numbers, PAWS).

Sequence- und Acknowledgement-Nummern dienen der Identifizierung und Bestätigung. Anders als TCP inkrementiert DCCP die Sequenznummer pro Paket, nicht pro Byte, denn es ist kein Bytestromprotokoll. Auch Bestätigungspakete folgen einem alternativen Ansatz: Sie bestätigen immer die größte Sequenznummer. Für genauere Informationen über Empfang oder Verlust dient die Option ACK-Vektor. DCCP ist wie erwähnt kein Protokoll mit der Intention einer hundertprozentigen Nutzdatenzuverlässigkeit.

Service Code bestimmt das zu transportierende Anwendungsprotokoll. Es muss mit dem im DCCP-Request gesetzten Wert übereinstimmen.

Options and Padding: Ähnlich TCP kennt auch DCCP Optionen, darunter Change und Confirm für die Aushandlung der CCID. Die Timestamp-Option ist ein alter Bekannter aus TCP-Zeiten.Daneben existieren viele weitere Optionen.

Application Data: DCCP kann bereits beim Verbindungsaufbau Daten versenden. Dieses Feld ist optional für eine DCCP-Response.

[31]Stauvermeidung unter Linux

Ab Kernelversion 2.6.13 unterstützt Linux den modularen Austausch des Staukontrollalgorithmus für TCP mit dem Interface sysctl/proc. Die Konfiguration des Kernels erfordert die Auswahl der dafür benötigten Unterstützung: Networking/Networking options/TCP: advanced congestion control. sysctl -w net.ipv4.tcp_congestion_ control=hybla reicht danach zum Beispiel aus, um die Kommunikation mit dem Weltraumteleskop Hubble zu beschleunigen (geeignete Hardware und die korrekte Kombination aus Benutzernamen und Passwort vorausgesetzt).

Der ursprüngliche Artikel erschien in iX 05/2006. (rek [32])


URL dieses Artikels:
https://www.heise.de/-221605

Links in diesem Artikel:
[1] http://www.heise.de/glossar/entry/Intellectual-Property-397273.html
[2] http://www.heise.de/glossar/entry/Routing-398623.html
[3] http://www.heise.de/netze/rfc/rfcs/rfc3714.shtml
[4] http://www.ietf.org/rfc.html
[5] http://www.heise.de/glossar/entry/Router-399395.html
[6] http://www.heise.de/glossar/entry/Burst-399287.html
[7] http://www.heise.de/netze/rfc/rfcs/rfc2474.shtml
[8] http://urchin.earth.li/ecn/
[9] http://www.heise.de/glossar/entry/Internet-Control-Message-Protocol-398827.html
[10] http://www.heise.de/netze/rfc/rfcs/rfc792.shtml
[11] http://www.heise.de/netze/rfc/rfcs/rfc793.shtml
[12] http://www.heise.de/glossar/entry/User-Datagram-Protocol-398809.html
[13] http://www.heise.de/netze/rfc/rfcs/rfc768.shtml
[14] http://www.heise.de/glossar/entry/Overhead-396891.html
[15] http://www.heise.de/glossar/entry/Domain-Name-System-398615.html
[16] http://www.heise.de/netze/rfc/rfcs/rfc3714.shtml
[17] http://www.heise.de/glossar/entry/Session-Initiation-Protocol-397437.html
[18] http://www.heise.de/netze/rfc/rfcs/rfc2543.shtml
[19] http://www.heise.de/netze/rfc/rfcs/rfc4340.shtml
[20] #dccpabfolge-u4
[21] http://www.heise.de/netze/rfc/rfcs/rfc1191.shtml
[22] #dccppaketformate-u4
[23] http://www.heise.de/glossar/entry/Voice-over-IP-395310.html
[24] #stauvermeidung-u4
[25] http://www.jp.nishida.org/dccp/
[26] http://www.heise.de/glossar/entry/Firewall-398669.html
[27] http://www.heise.de/glossar/entry/Universal-Mobile-Telecommunications-System-395578.html
[28] mailto:rek@heise-netze.de
[29] 
[30] 
[31] 
[32] mailto:rek@ct.de