Advanced Winsock: AcceptEx und DoS-Angriffe



  • 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



  • OllyDbg habe ich bereits und nutze ihn auch manchmal. 😉

    @ sehenwoller:

    Das sind mittlerweile ~400 Zeilen, die ich hier erst mal nicht poste.

    > 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.

    Ja keine Ahnung... Ich will es trotzdem selber messen und die Skalierbarkeit sehen. Ich nehme deine Meinung jetzt einfach mal so hin. 🙂

    So, jetzt ist die Sache schon ziemlich komplex geworden. Da ein AcceptEx() zu wenig ist, will ich nun mehrere haben, und so soll das ganze nun so funktionieren:

    Ich setzte eine obere und untere Grenze für laufende AcceptEx-Calls (also solche, bei denen noch kein Client in Bedienung ist), die alle ein eigenes OVERLAPPED mit Event haben. Mit WASWaitForMultipleEvents() komme ich an den Index des Overlapped-Arrays und kann mit dem auf den Index des Accept-Socket-Arrays schließen und den Client weiter behandeln.
    Jetzt bleibt noch das selbe Problem wie oben: was, wenn jemand alle AcceptEx belegt (keine Daten sendet)? Natürlich das selbe nochmal: Mit WSAEventSelect und FD_ACCEPT den Listen-Socket assoziieren. Nur, jetzt bin ich etwas darüber verwirrt, wann FD_ACCEPT signalisiert wird. Im magischen Buche steht:

    On Windows 2000 and later versions, Winsock provides a mechanism for determining if an application is running behind in posting adequate AcceptEx calls. When creating the listening socket, associate it with an event by using the WSAEventSelect API call and registering for FD_ACCEPT notification. If there are no pending AcceptEx operations but there are incoming client connections (accepted by the system according to the backlog value), then the event will be signaled. This can even be used as an indication to post additional AcceptEx operations.

    Das heißt, dass FD_ACCEPT nur signaled ist, wenn ein Client statt im Accept in der Backlog-Queue landet? Also wenn es kein accept gibt, welches den Client aufnimmt. Bisher dachte ich, dass jeder Client zunächst in die Backlog-Queue kommt (unabhängig, ob ein accept da ist oder nicht), dadurch FD_ACCEPT signaled ist und dann evtl. ein Accept aufgerufen wird. 😕



  • Okay, meine Vermutung hat sich bestätigt. 🙂 FD_ACCEPT tritt nur ein, wenn ein Client in der Queue landet, und das passiert wirklich nur, wenn kein Accept-Call läuft.
    Jetzt läuft das ganze schon ganz chick, nur eröffnet sich jetzt ein kleines neues Problemfeld: was fange ich mit dem Socket hat, hinter dem ein Angreifer sitzt und den AcceptEx-Call und den Socket blockiert? Die erste Antwort wäre closesocket(), nur müsste ich dann im Rahmen den Accept-Prozesses mit WSASocket() einen neuen erstellen, und das wird bei vielen Sockets etwas zu teuer.
    Nun habe ich DisconnectEx() gefunden. Nur irgendwie ist die Funktion an einer Stelle doof: sie findet ihre Completion erst nach 120s (Wartezeit zwischen Disconnect und dem Re-Use (!) des Handles). Also 120s Funkstille am Server? Es ist ja in dem Moment kein Socket-Handle mehr frei! Das kann nicht gut gehen. Kann man einen Client irgendwie ganz schnell einfach los werden, ohne das Handle zu opfern?



  • Ad aCTa schrieb:

    Die erste Antwort wäre closesocket(), nur müsste ich dann im Rahmen den Accept-Prozesses mit WSASocket() einen neuen erstellen, und das wird bei vielen Sockets etwas zu teuer.

    Hast du es denn ausprobiert?
    Nein?
    Eben.
    Aber warum einfach wenns kompliziert auch geht.



  • Auch bei closessocket() sollten sich die Sockets danach noch einige Zeit im TIME_WAIT State befinden.



  • Du kannst mal versuchen den Socket mittels setsockopt auf "no linger" zu stellen bevor du eine Verbindung schnell loswerden willst. Dann sollte IMHO DisconnectEx auch "sofort" fertig werden.



  • () schrieb:

    Auch bei closessocket() sollten sich die Sockets danach noch einige Zeit im TIME_WAIT State befinden.

    Wird wohl so sein, ja. Macht aber nix, wenn man gleich nen neuen Socket anlegt und den dann weiter verwendet.
    Wenn natürlich mal hunderte "böse" Verbindungen pro Sekunde reinkommen hilft auch das nichts mehr.

    Was "no linger" angeht: bist du sicher dass das bei TIME_WAIT hilft? IIRC hilft da nur wenn man dieses "reuse address" Flag setzt.



  • Bin mir nicht sicher, habs nur gelesen. 🙂

    z.B. hier: http://www.lenholgate.com/archives/000779.html

    ... this sets the socket's linger options in such a way that the socket is closed immediately and all pending data is discarded. What's especially useful is that this also sends a RST (reset) on the TCP/IP connection and this closes the connection without putting the closer into the TIME_WAIT state; which is useful sometimes.



  • Nach meinem (zugegebenermassen nicht sehr tief gehenden) Verständnis von TCP/IP kann da nur ein empfangenes RST was bringen, nicht aber ein gesendetes.


Anmelden zum Antworten