2009-10-07 9 views
7

Wenn ich ein großes HTTP-Paket habe, das in eine Anzahl von TCP-Paketen aufgeteilt wurde, wie kann ich sie in ein einzelnes HTTP-Paket zurückverwandeln? Grundsätzlich, wo im Paket sehe ich aus, wenn ein HTTP-Paket beginnt/endet? Ich sehe anscheinend keine Flags/Felder im TCP-Header, die den Anfang oder das Ende des HTTP-Pakets anzeigen.HTTP-Paketrekonstruktion

EDIT: Im Anschluss an die Antworten. Wenn TCP den Stream verwaltet, wie weiß er, wann der Stream beginnt und endet? Wird das durch das Öffnen und Schließen der Steckdose bestimmt? Einige Protokolle müssen auf einer bestimmten Ebene wissen können, wann der HTTP-Datenstrom/das HTTP-Paket gestartet und beendet wurde. Das würde ich gerne wissen.

Die Situation, in der ich bin, verwende ich einen Paket-Sniffer in C#, der TCP-Pakete einliest, und ich möchte in der Lage sein, die HTTP-Anfragen/Antworten/etc zu rekonstruieren. Durch die Schnittstelle gehen, wie wireshark und verschiedene andere Sniffer es schaffen. Gibt es alternativ C# -Bibliotheken, mit denen Sie die HTTP-Streams auf der höheren Ebene anzapfen können, wodurch ich die HTTP-Streams/-Pakete selbst rekonstruieren muss?

Danke.

Antwort

10

OK Ich habe herausgefunden, wie man das macht (zweifelhaft, aber es macht den Job erledigt).

Es ist einfach, die Ethernet-, IP- und TCP-Header zu entfernen, so dass Sie die Nachricht "Rohdaten" erhalten. Wenn Sie innerhalb der Nachricht nachsehen, ist es leicht zu erkennen, ob es der Start eines HTTP-Pakets ist, indem Sie nach dem "HTTP/1.1 ..." am Anfang des Pakets suchen. Dies zeigt an, dass das Paket der Start eines HTTP-Streams/größeren Pakets/was auch immer ist. Sie können auch ein einfaches Parsing durchführen, um das Feld "Content-Length" zu lesen, das die Gesamtlänge des gesamten HTTP-Pakets angibt.

Sie können auch die Quell-/Ziel-IP & Portnummern verwenden, um eine eindeutige ID für die Verbindung zu bilden. Nachdem Sie das Header-Paket empfangen haben, notieren Sie diese 4 Dinge (SRCIP, SRCPORT, DESTP, DESTPORT). Wenn Sie das nächste Mal ein Paket erhalten, das dieser Port/IP-Kombination entspricht, können Sie prüfen, ob es sich um den nächsten Teil des HTTP-Pakets handelt. Sie können die Sequenznummern verwenden, um etwas zu validieren und wahrscheinlich andere Dinge, aber im Allgemeinen sind die Pakete in Ordnung, also ist es in Ordnung.Ich denke, dass ein neuer Port für jeden HTTP-Stream geöffnet wird, so dass Sie keine zufälligen Pakete erhalten sollten, die nicht Teil des Streams sind, aber dies könnte ein fehleranfälliger Bereich sein.

Wie auch immer, nachdem Sie dieses Paket erhalten haben, entfernen Sie wieder die Header und erhalten Sie die rohe Nachricht. Fügen Sie es dem bereits bekannten Teil der Nachricht hinzu. Wenn die Länge der gesamten Nachricht, die bisher empfangen wurde, gleich der aus dem Feld "Content-Length" abgelesenen Länge ist, ist das Paket vollständig!

Diese Methode ist offensichtlich anfällig für eine große Anzahl von Fehlern, aber ich bin nicht auf eine extrem robuste Art und Weise, dies zu tun. Ich dachte, ich würde meine eigene Frage beantworten, falls jemand anderes in Zukunft auf dasselbe Problem stoßen sollte! Viel Glück mit Ihrem Schnüffeln: D

+2

Wenn der Content-Length-Feld nicht angegeben ist, gibt es andere Möglichkeiten zu, die Länge zu trainieren. z.B. http://www.httpwatch.com/httpgallery/chunked/ – mike

+2

Möglicherweise ein bisschen spät, aber die 'Content-Length' Header nicht die gesamte Paketlänge angeben. Es gibt lediglich die Größe des Inhalts an, also den Body, der hinter den Headern steht. Die Header und der Körper sind durch '\ r \ n \ r \ n' getrennt. –

7

Sie sollten keine Informationen von der TCP-Ebene verwenden, um HTTP-Anforderungsgrenzen zu bestimmen. TCP bietet einen zuverlässigen Byte-Stream-Dienst; Sie können keine Felder oder Flags in TCP sehen, die dabei helfen, weil sie nicht da sind.

Um festzustellen, wo die Grenzen in einer HTTP-Anfrage sind, sollten Sie RFC 2616 folgen. Die Grenzen sind gut definiert, und Sie können sie durch Parsing der Daten bestimmen, die Sie erhalten.

2

TCP ist ein Stream Protokoll, kein Paketprotokoll. Die Anwendungsschicht (d. H. Sie) erhält einen Datenstrom, nicht einen Bündel von Paketen. Sie lesen einfach weiter Bytes aus dem Stream und Sie erhalten Ihre gesamte HTTP-Payload, während TCP die Fehlerprüfung durchführt, erneut sendet, usw. darunter.

4

In jedem TCP-Paket befindet sich der Start der Nutzdaten unmittelbar nach dem TCP-Header, und das Ende der Nutzdaten ist das Ende des IP-Pakets.

Das Ende des TCP-Headers ist leicht zu finden - das Data Offset ist ein 4-Bit-Feld in der Kopfzeile, die die Länge des Headers in 32-Bit-Worten enthält (also multiplizieren Sie es mit 4, um die Länge in 8- zu erhalten) Bit-Bytes).

Verwenden Sie die TCP-Sequenznummern aus dem Feld Sequence, um die Nutzdaten in der richtigen Reihenfolge zusammenzufassen. Beachten Sie, dass es im Fall von Wiederholungen zu Duplikaten kommen kann.

1

Wir mussten arbeiten, um das gleiche Problem zu lösen. Wir konnten einige der Kernfunktionen in einem Open-Source-Projekt extrahieren.

http://code.google.com/p/pcap-reconst/

Bitte, check it out und lassen Sie mich wissen, ob es Ihnen helfen.

+0

Ich bin daran interessiert, Ihren Code zu verwenden. Ohne zu tief in die Quelle eindringen zu müssen, behandelt Ihr Projekt a) komprimierte Daten auf der Grundlage des Headers "Content-Encoding" dekomprimieren, b) in eine gemeinsame Textcodierung konvertieren, die auf dem Zeichensatz im Content-Type basiert Header und c) Umgang mit Chunked-Codierung, wenn der 'Transfer-Encoding' Header auf' chunked' gesetzt ist? –