Http-Sniffer in C++ Builder



  • Hallo,

    ich habe im Forum schon Einiges zum Thema gelesen aber erhielt auf meine Fragen keine Antworten. Nun denn, ich möchte den Datenverkehr von einem Online-Browsergame analysieren und dadurch Statistiken generien. Das Programm soll nur mithören und nicht Daten manipulieren, was auch gegen die AGB verstossen würde. Die Analyse der Daten (HTTP-Packete) hab ich grösstenteils schon realisiert und stellt kein Problem mehr dar. Meine Fragen wären:

    Welche Library? Habe von Winpcap gehört aber bin mir nicht sicher, ob es einfacher gehen würde. Mit Winpcap müsste ich mir selbst einen TCP/IP-Stack basteln um schlussendlich dann an die HTTP-Packete zu gelangen und das dürfte einen erheblichen Mehraufwand bedeuten. Gibt es alternative Bibliotheken die das bereits beinhalten? In Perl hab ich zB Sniffer::HTTP gefunden - genau das in C++ suche ich.
    Weiter möchte ich das Projekt im Borland C++ Builder realisieren, habe allerdings bis jetzt sämtliche Beispiele von Winpcap nur für Visual C++ Studio gefunden. Gibts ein Example mit Winpcap für den C++ Builder?

    Schon in Voraus danke für eure Antworten
    mfg



  • nex schrieb:

    Weiter möchte ich das Projekt im Borland C++ Builder realisieren, habe allerdings bis jetzt sämtliche Beispiele von Winpcap nur für Visual C++ Studio gefunden. Gibts ein Example mit Winpcap für den C++ Builder?

    Da sollte es keine Unterschiede geben.

    Für die Benutzung von WinPcap mit C++Builder ist in den WinPcap-FAQ übrigens ein Eintrag zu finden.



  • Ok danke für den Hinweis. Ich dachte bloss, dass es womöglich auch schon ein Beispielprojekt für den Builder gibt, damit nicht jeder aufs Neue das Ganze wieder anpassen muss.

    Trotzdem meine wesentliche Frage ist eigentlich, ob es nicht Bibliotheken gibt, welche schon höhere Schichten implementiert haben? Ich kann mir irgendwie nicht vorstellen, dass sich jeder Benutzer seinen eigenen TCP/IP-Stack zu Winpcap schreibt. Könntest Du, oder ihr weisen Leute da draussen ;), mir etwas empfehlen? Meine Suche war bis jetzt erfolgslos geblieben.



  • Dieser Thread wurde von Moderator/in akari aus dem Forum VCL (C++ Builder) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Den TCP/IP Stack muss man mit Sicherheit nicht neu programmieren, den stellt Windows zur Verfügung.
    Ich weiss nicht, welche Statistiken du erstellen willst, aber du musst eigentlich nur folgende Dinge mit winpcap tun:

    - Identifikation des richtigen TCPI/IP Packets, dazu gehören Identifikation des Typs (HTTP, TCP/IP) und des richtigen Absenders, schliesslich willst du ja nur die Daten des Browserspiels behandeln und nicht etwa noch google Anfragen eines zweiten Browsers. Dieser Teil ist ziemlich trivial.

    - Falls du ingame Daten benötigst musst du den HTTP Datenstrom noch parsen und nach den richtigen Abschnitten suchen, das wird dann wohl die grössere Programmieraufgabe. Weil das Browsergame wohl sein eigenes Datenformat benutzt wirst du nicht drumherumkommen, das selbst programmieren zu müssen.

    Gruß,
    Doc





  • Hi _DocShoe_,

    womöglich habe ich mich etwas unpräzise ausgedrückt...
    Winpcap liefert mir ja direkt die Ethernetrahmen und diese müsste ich dann nach dem IP-Header durchsuchen, TCP-Header auslesen um an die TCP-Payload, die eigentlichen HTTP-Pakete, zu gelangen. Die einzelnen Rahmen müssten noch auf Übertragungsfehler überprüft und dann schlussendlich nach Sequenznummer in der richtigen Reihenfolge zusammengefügt werden. Unter Umständen können sich die Antwortpakete von zwei Requests ja auch noch abwechseln, was das Ganze etwas komplizierter machen dürfte. So ungefähr das und Weiteres sollte ein TCP/IP Stack erledigen und dies möchte ich nur ungern selbst implementieren.
    Die Auswertung der HTTP-Daten ist dann wie gesagt kein bzw. ein lösbares Problem.

    Danke für den Link Isp - es scheint auf den ersten Blick genau das zu sein was ich suchte 🙂



  • Also dafür nen eigenen LSP zu programmieren halte ich für zu umständlich. Und vor allem stellt es dich schlussendlich wieder vor das gleiche Problem: Du musst den HTTP Stream doch wieder selber parsen. Der LSP bietet weit mehr Möglichkeiten als winpcap, ich sehe nur nicht, wie dir das weiterhilft. Du kannst ja mal von deinen Erfolgen berichten, wenn´s soweit ist.

    Gruß,
    Doc



  • nex schrieb:

    Mit Winpcap müsste ich mir selbst einen TCP/IP-Stack basteln um schlussendlich dann an die HTTP-Packete zu gelangen und das dürfte einen erheblichen Mehraufwand bedeuten.

    du brauchst keinen tcp-stack, sondern du musst nur die header auswerten. ethernet- ip- und tcp-header (letzterer ohne options) haben feste längen. du bekommst von winpcap in dieser reihenfolge:
    - 14 bytes eth header
    - 20 bytes ip header
    - 20 bytes tcp header
    - x bytes nutzdaten (z.b. http-protokoll)
    wenn dich z.b. nur das http interessiert, dann überspring' einfach die ersten 54 bytes.
    🙂



  • Grundsätzlich hast du schon recht mit deiner Aussage fricky, jedoch beginnen danach erst die wirklichen Probleme. Ich habe nun jedenfalls begonnen es mit Winpcap zu realisieren, da ich selbst auch keine Alternative mehr fand. Es funktioniert soweit auch wunderbar und ich erhalte brav die einzelnen Pakete. Stecken geblieben bin ich momentan beim Umwandeln der Pakete (Ethernet) in HTTP-Requests/-Responses. Folgende Tatsachen erschweren mein Weiterkommen:

    - Segmentierung. Falls die HTTP-Daten zu gross sind, werden sie in mehreren TCP-Paketen gesendet.
    - Werden mehrere HTTP-Requests abgeschickt, wird nicht zuerst auf den ersten Request geantwortet und danach auf die Weiteren sondern "gleichzeitig" auf alle - die TCP-Pakete der Requests wechseln sich ab.
    - Die Reihenfolge der TCP-Segmente kann sich während der Übertragung ändern.
    - "Content-Length" scheint in HTTP kein Pflichtfeld zu sein.

    Mir stellt sich momentan die Frage, wie ich erkennen kann, ob ich das "letzte" TCP-Paket erhalten habe und ob sämtliche Pakete zwischen Erstem und Letztem auch schon angekommen sind oder noch folgen werden?
    Zur Zeit ermittle ich anhand der TCP-Paket-Grösse, ob noch weitere Pakete folgen sollten. Es scheint mir jedoch nicht unbedingt der sauberste Weg zu sein ... womöglich übersehe ich aber auch einfach Etwas und werde mich nun erstmal noch besser über TCP informieren.



  • du könntest es vielleicht so machen:
    1. pakete die vom webserver kommen, deren local-port == 80 ist und die SYN+ACK im tcp-header gesetzt haben, bedeuten dass eine verbidnung stattgefunden hat. aus einem solchen paket extrahierst du beide ip-adressen und beide portnummern.
    2. von allen weiteren paketen, bei denen portnummern und ip-adressen gleich denen aus (1) sind, speicherst du die nutzdaten ab. das ist dann nämlich der http-datenstrom.
    3. kommt vom server ein tcp paket, in dessen header die flags FIN+ACK gesetzt sind, dann speicherst du ebenfalls die nutzdaten ab und die verbindung ist beendet.
    ^^so kriegst du alle daten vom server für diese verbindung. die daten vom client kriegst du, wenn du ähnliches machst, nur sind dabei portnummern und ip-adressen vertauscht.
    🙂



  • Die erste Filterung der Pakete (Port & IP) mache ich bereits mit Winpcap. Ich erhalte also nur Pakete, die mich auch interessieren.

    Die Detektion eines Verbindungsaufbaus habe ich bereits implementiert und es werden nun auch die richtigen Pakete in richtiger Reihenfolge zusammengefügt. Was noch fehlt ist weiterhin eine "saubere" Erkennung des letzten TCP-Paketes - momentan wird das immernoch anhand der Grösse des Paketes entschieden.

    Sauber wäre es natürlich, wenn man auf das FIN-Paket warten würde, jedoch dauert es im besten Fall um ~5 Sekunden, bis die Verbindung auch geschlossen wird. Ein Webbrowser wird also auch nicht auf das Beenden der TCP-Verbindung warten, ehe er die Daten auswertet und mir dauert das eigentlich auch zu lange ...



  • nex schrieb:

    Sauber wäre es natürlich, wenn man auf das FIN-Paket warten würde, jedoch dauert es im besten Fall um ~5 Sekunden, bis die Verbindung auch geschlossen wird.

    dann hast du aber 'ne super-lahme verbindung. normalerweise geht das viel schneller.

    nex schrieb:

    Ein Webbrowser wird also auch nicht auf das Beenden der TCP-Verbindung warten, ehe er die Daten auswertet und mir dauert das eigentlich auch zu lange ...

    ich denke auch, dass der browser die daten, während sie eintrudeln, schon verarbeitet. allerdings wird er mit dem darstellen warten müssen, bis alles da ist. es könnte ja ein CSS, etc. am ende sein, das alles ändern könnte. aber wenn keine content-length angegeben ist, dann ist die http-übertragung mit dem FIN vom server beendet. ich wüsste nicht, ob es noch 'ne andere möglichkeit gibt.
    🙂



  • Hm, also ich bin mir eigentlich sehr sicher, dass die Dauer, bis die TCP-Verbindung geschlossen wird nicht von der Geschwindigkeit der Internetverbindung abhängig ist. Wie ich gelesen habe wird die Verbindung nach einem Timeout geschlossen und dieser liegt nunmal im Bereich einiger Sekunden.
    Hast du mal mit Packetyzer oder Ähnlichem deinen TCP-Verkehr angeschaut? Bei mir treffen die FIN-Pakete um Einiges verzögert ein, während der Browser den Ladevorgang bereits abgeschlossen hat und die Seite darstellt.



  • nex schrieb:

    Hm, also ich bin mir eigentlich sehr sicher, dass die Dauer, bis die TCP-Verbindung geschlossen wird nicht von der Geschwindigkeit der Internetverbindung abhängig ist. Wie ich gelesen habe wird die Verbindung nach einem Timeout geschlossen und dieser liegt nunmal im Bereich einiger Sekunden.

    du meinst bestimmt diese fin-wait-x bzw. time-wait states von tcp? die greifen nur bei langsamen netzen. wenn beide ihre FIN-ACK/ACKs schnell genug austauschen, was im normalfall passiert, ist die verbindung schnell beendet (im millisekundenbereich).

    nex schrieb:

    Hast du mal mit Packetyzer oder Ähnlichem deinen TCP-Verkehr angeschaut? Bei mir treffen die FIN-Pakete um Einiges verzögert ein, während der Browser den Ladevorgang bereits abgeschlossen hat und die Seite darstellt.

    weiss nicht wo diese verzögerungen herkommen, aber normal ist das nicht. guck doch mal mit wireshark auf die zeitstempel der pakete.
    🙂



  • fricky schrieb:

    guck doch mal mit wireshark auf die zeitstempel der pakete.

    Genau das habe ich getan und deshalb bin ich auch auf die ~5 Sekunden gekommen. Der Wert schwankt jedoch sehr und hängt auch von der Seite ab, die ich aufrufe. Er bleibt jedoch mindestens im Bereich von einigen Sekunden.
    Z. B. Google schliesst die Verbindung erst nach ~20 Sekunden. Könntest du (oder ein Anderer ;)) mal prüfen, ob das bei dir wirklich anders ist?

    Ich habe es bereits bei mir zu Hause (ADSL 3500/300 Kbps) und hier an der Uni geprüft und vermute deshalb, dass es eigentlich nicht an mir liegen sollte.



  • nex schrieb:

    Z. B. Google schliesst die Verbindung erst nach ~20 Sekunden. Könntest du (oder ein Anderer ;)) mal prüfen, ob das bei dir wirklich anders ist?

    du hast recht. google lässt die verbindung eine ganze weile offen !?
    seltsam, seltsam.
    aber hier steht, wie man das ende einer http-message erkennen kann: http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html
    (unter 4.4 Message Length)
    🙂


Anmelden zum Antworten