Advanced Winsock: AcceptEx und DoS-Angriffe



  • Gib doch bei WSAWaitForMultipleEvents ein Timeout an und wenn dieser auftritt führst du die Prüfung durch. Wo siehst du denn genau das Problem?



  • > führst du die Prüfung durch.

    Es gibt ja eben keine. Wenn wirklich Daten da sind, ist das hEvent von overlapped signaled. Das zu überprüfen wäre Schwachsinn, da genau dann WSAWaitForMultipleEvents() returned. Außerdem: Dann würde die Unendlichschleife ja durchlaufen.



  • Ich meine die getsockopt mit SO_CONNECT_TIME Prüfung.



  • Und was soll das bringen?

    while(running) {
       //...
       AcceptEx(...);
       //...
       WSAWaitForMultipleEvents(...); // warte eben nur 1s
       //...
       if(getsockopt(...)) { ... } // Socket nicht verbunden, gibt -1 zurück
       //...
    }
    

    Das bringt doch exakt garnichts?! Nur, dass die CPU etwas mehr blutet, da die Server-Hauptschleife jetzt jede Sekunde durchlaufen wird. getsockopt() gibt mir einfach -1 zurück, wenn AcceptEx() nicht completed ist.



  • Ja aber dann kannst du doch die Verbindung trennen wenn die Verbindung besteht aber nach einer bestimmten Zeit noch keine Daten angekommen sind.



  • Das getsockopt wird dir die Millisekunden zurückgeben die der Client bereits verbunden ist auch wenn noch keine Daten empfangen wurden.



  • Ups, sind wohl Sekunden.

    Das getsockopt wird dir nicht erst nach der AcceptEx Completion einen posiiven Wert liefern.



  • Laut Doku bekommt man nen Wert nachdem die Connection aufgebaut wurde (auch bevor Daten angekommen sind). Davor nen Fehler.

    Ich finde das allerdings trotzdem alles viel zu kompliziert.

    Vor allem muss man parallel Unmengen von AcceptEx Aufrufen pending haben wenn man nicht möchte dass langsame Clients den Server ausbremsen. Auch mit solchen Abfragen um extrem langsame Clients rauszuwerfen.

    Ohne Receive-Buffer bzw. mit dem guten alten accept() ist das nicht nötig.



  • > Ohne Receive-Buffer bzw. mit dem guten alten accept() ist das nicht nötig.

    Dafür ist accept() blockierend, nicht asynchron/overlapped und langsam.

    > Vor allem muss man parallel Unmengen von AcceptEx Aufrufen pending haben wenn man nicht möchte dass langsame Clients den Server ausbremsen.

    Ja, das Feature füge ich zu meinem Server jetzt mal hinzu. Neben dem Socket-Pool (dann spar ich mir die teure Erstellung von neuen Sockets beim AcceptEx()).

    > Ich finde das allerdings trotzdem alles viel zu kompliziert.

    Niemand hat behauptet, dass es einfach ist. 😉 Beste Performance hat seinen Preis.

    Ich habe btw. einen Weg gefunden, den ich aber erst morgen teste. Wenn ich den listen-Socket mit einem Event assoziiere (per WSAEventSelect()), das bei FD_ACCEPT signaled ist, dann weiß ich schon vor dem Aufruf von AcceptEx(), dass ein Client im Anmarsch (in der Listen-Queue) ist. Nach dem Ereignis gehe ich alle Sockets durch, die gerade in einer AcceptEx()-Operation stecken und prüfe mit getsockopt, ob und wie lange sie schon verbunden sind. Das könnte glatt funktionieren.

    Nun habe ich ein anderes Problem: Der Kernel-Mode belegt beim Aufruf von AcceptEx() Ressourcen, die (aus Performance-Gründen) nicht freigegeben werden, sollte die Overlapped-Operation abgebrochen werden. Auf Deutsch: Ich kann nicht einfach DisconnectEx() oder closesocket() auf einen Socket setzten, der im AcceptEx()-Pending steckt, aber noch keine Daten gesendet hat, sonst bekomme ich Memory-Leaks. Was kann ich da tun?



  • Ad aCTa schrieb:

    > Ohne Receive-Buffer bzw. mit dem guten alten accept() ist das nicht nötig.

    Dafür ist accept() blockierend, nicht asynchron/overlapped und langsam.

    Alter Schwede. Dann verwende AcceptEx, aber gieb KEINEN Receive Buffer mit.

    > Vor allem muss man parallel Unmengen von AcceptEx Aufrufen pending haben wenn man nicht möchte dass langsame Clients den Server ausbremsen.

    Ja, das Feature füge ich zu meinem Server jetzt mal hinzu. Neben dem Socket-Pool (dann spar ich mir die teure Erstellung von neuen Sockets beim AcceptEx()).

    Hast du es gemessen? Hast du einen Ahnung davon wie wenig das "teure" Erstellen eines Sockets im Vergleich zu anderen Operationen kostet?

    > Ich finde das allerdings trotzdem alles viel zu kompliziert.

    Niemand hat behauptet, dass es einfach ist. 😉 Beste Performance hat seinen Preis.

    Dir ist nicht mehr zu helfen.

    Ich habe btw. einen Weg gefunden, den ich aber erst morgen teste. Wenn ich den listen-Socket mit einem Event assoziiere (per WSAEventSelect()), das bei FD_ACCEPT signaled ist, dann weiß ich schon vor dem Aufruf von AcceptEx(), dass ein Client im Anmarsch (in der Listen-Queue) ist. Nach dem Ereignis gehe ich alle Sockets durch, die gerade in einer AcceptEx()-Operation stecken und prüfe mit getsockopt, ob und wie lange sie schon verbunden sind. Das könnte glatt funktionieren.

    Nun habe ich ein anderes Problem: Der Kernel-Mode belegt beim Aufruf von AcceptEx() Ressourcen, die (aus Performance-Gründen) nicht freigegeben werden, sollte die Overlapped-Operation abgebrochen werden. Auf Deutsch: Ich kann nicht einfach DisconnectEx() oder closesocket() auf einen Socket setzten, der im AcceptEx()-Pending steckt, aber noch keine Daten gesendet hat, sonst bekomme ich Memory-Leaks. Was kann ich da tun?

    Wo hast du denn die Info her?

    Ich finde es aber echt witzig wie realitäts-resistent du bist. Lass den Receive-Buffer bei AcceptEx weg, und alles wird gut. Aber ne. Du brauchst ja die bessere Performance. Obwohl du nichtmal nen Vergleich hast um wieviel es wirklich um ist. Naja. Jeder wie er meint.



  • Warum gönnst du ihm nicht den Spaß optimieren? 😡 😃 😡



  • > Wo hast du denn die Info her?

    Aus Network Programming For Microsoft Windows, eines der besten Bücher über WinSock, die es gibt. 🙄

    > Hast du es gemessen? Hast du einen Ahnung davon wie wenig das "teure" Erstellen eines Sockets im Vergleich zu anderen Operationen kostet?

    Relativ viel. Wesentlich weniger als ein WSARecv(). Und wie soll ich bitte messen, wenn ich nicht mal ein Programm habe? 😃 Der Accept-Prozess muss so kurz wie möglich sein. Da braucht man nicht noch Socket-Erstellung. (Wozu alte Sockets nicht wiederverwenden?)

    > Dir ist nicht mehr zu helfen.

    Doch, meine Frage ist immer noch offen.



  • Hi

    Und wie soll ich bitte messen, wenn ich nicht mal ein Programm habe?

    Verzeihe mir, aber bist du so oder tust du nur so?
    kannst ja die Zeit messen ! Wo ist das Problem ?

    sta = clock();
    end = clock();

    differenz vergleichen ! Und schon hast du die Zeit. 🙄 😉
    Und glaube mir Hustbaer hat recht ! Solltest lieber mal andere Operationen optimieren !

    lowbyte



  • > Wo ist das Problem ?

    Du hast mich da nicht ganz verstanden. Da ich noch keinen funktionierenden Server mit Io-Completionports programmiert habe, mit dem ich die Zeitmessung durchführen könnte, kann ich logischerweise auch noch nichts messen. Und selbst wenn ich einen Timer eingebaut hätte: die Zeit läge um 1ms, egal, ob ich select() oder Io-Completionports nutze, da das Loopback sehr schnell ist. Einen Server über X Indirektionen, auf dem ich das effektiv testen könnte, habe ich einfach nicht. 😃

    > Und glaube mir Hustbaer hat recht !

    Natürlich hat er Recht. Das, was ich hier baue wird nie 100000000 Clients gleichzeitig behandeln müssen. Aber trotzdem will ich die Technik dahinter verstehen. Ich weiß nicht, warum alle damit ein Problem haben. 🙄

    > Solltest lieber mal andere Operationen optimieren !

    Da gibt's nichts zu optimieren. Wenn die Verbindung von TCP erst einmal besteht, geht das alles recht schnell. Der teuerste Prozess ist der Verbindungsaufbau, den will ich optimieren.



  • Hi

    Der teuerste Prozess ist der Verbindungsaufbau, den will ich optimieren.

    So ein schwachsin !
    Was willst du da Optimieren.. du willst mir nicht sagen das dieser kleine aber nur winzige unterschied was ausmacht ?!!!
    Ich habe es getestet, und es bringt dir nichts absolut nicht. Weil sich nie 1000 Host auf einmal verbinden.Und ausserdem ist der Verbindungsaufbau nur initial, und wird wärend der Session nicht mehr ausgeführt, darum verstehe ich die Optimierungen((minimal) weniger geht nicht mehr) in diesem Fall nicht.

    Komprimierst du dein stream ? MTU(Maximum Transmission Unit) ? etc. etc. das sind alles Sachen die man sich mal überlegen sollte ! Und wie sieht es mit Encryption aus ? Da, solltest du beim Thema Sicherheit mal anfangen !!

    Und ich denke jetz giebt es nichts mehr zu sagen !

    lowbyte

    lowbyte



  • Hi

    Der teuerste Prozess ist der Verbindungsaufbau, den will ich optimieren.

    😃 😃

    Das war aber nicht dein ernst ?

    lowbyte



  • > Ich habe es getestet,

    Auf Localhost? Ja toll, das Loopback ist ja wohl keine reale Bedingung.

    > du willst mir nicht sagen das dieser kleine aber nur winzige unterschied was ausmacht ?!!!

    Doch, will ich.

    MSDN: A program can make a connection to a socket more quickly using AcceptEx instead of the accept function.

    NPFMW:
    Perhaps the most useful extension API for scalable TCP/IP servers is AcceptEx.
    [...] So the socket handle for the client needs to be created before posting the AcceptEx call. This is necessary because socket creation is expensive, and if a server is interested in handling client connections as fast as possible, it needs to have a pool of sockets already created on which new connections will be assigned.

    > solltest du beim Thema Sicherheit mal anfangen !!

    Ja, genau das steht im Thread-Titel, ich wollte diese große Sicherheitslücke stopfen, und dafür habe ich einen Weg gefunden. Sobald ich getesteten Code habe, kann ich ihn ja mal präsentieren.



  • Ich halte es zwar immer noch für Unsinn, aber wenn du unbedingt willst kannst du man probieren ob das Receive-Timeout (SO_RCVTIMEO) auch bei AcceptEx greift.

    Was du auch nicht zu verstehen scheinst: ausser dass minimal mehr CPU Zeit verbraten wird, macht es für die Geschwindigkeit der Verbindungsherstellung keinen Unterschied ob du accept, AcceptEx oder AcceptEx mit einem Receive-Buffer verwendest.

    Da gibt's nichts zu optimieren. Wenn die Verbindung von TCP erst einmal besteht, geht das alles recht schnell. Der teuerste Prozess ist der Verbindungsaufbau, den will ich optimieren.

    Sorry, aber das ist auch Unsinn. Mach dich mal über Dinge wie Delayed ACK und Nagles Algorithms schlau.



  • Präsentier mal deinen Code bitte! 🙂



  • Lad dir den OllyDebugger runter: http://www.ollydbg.de/

    Debugg deine Connect Funktionen oder was weiss ich was du da alles hast und Optimier die viel spass. ^^

    Hier hat wer so etwas mit der strcmp Funktion gemacht:

    http://www.masm32.com/board/index.php?PHPSESSID=de82d816a4afabcbe608a5b512dc126f&topic=2508.0


Anmelden zum Antworten