Fragen? Antworten! Siehe auch: Alternativlos
Das Problem bei Windows war, dass man da einen AcceptEx-Call mit overlapped I/O losgetreten hat, und der eine Call nahm dann halt eine Verbindung an, und signalisierte erst, wenn der was schickte. Wenn jetzt aber jemand eine Verbindung aufbaute und nichts schickte, dann nahm der Server gar keine Sockets mehr an. Kurz gesagt: ein dummes Denial of Service.
Nun, Linux hat auch sowas:
int one=1;Das habe ich irgendwann gesehen, in libowfat abstrahiert, und dann in gatling eingebaut. Und jetzt stelle ich gerade fest, dass die Linux-Implementation ein sehr ähnliches Problem hat. Nur halt dass nicht ein Socket für das DoS ausreicht.
setsockopt(sockfd,IPPROTO_TCP,TCP_DEFER_ACCEPT,&one,sizeof(one));
Ich habe da gerade eine Stunde rum debuggt (weil ich auch in meinem libowfat-Code gerade herum experimentiere und erst dachte, ich hab dabei was kaputt gemacht), bis ich beim Blick auf netstat gesehen habe, dass da 16 Verbindungen im SYN_SENT bzw SYN_RECV Stadium waren (SYN_SENT beim Client und SYN_RECV beim Server, liefen auf der selben Kiste hier), und ein Socket im SYN_SENT ohne dazu gehöriges SYN_RECV. 16 ist genau das Limit, das ich bei listen() als Backlog übergeben hatte. Die Verbindungen zählen also als "halbe Verbindungen", die man aber nicht annehmen kann; vom Problem her mit einer Syn Flood verwandt.
Und da fiel es mir wie Schuppen von den Augen. Das Linux-API ist gut gemeint aber ist in Wirklichkeit ein DoS gegen sich selbst, zumindest in der aktuellen Implementation in 2.6.27. Zu allem Überfluss wird das DoS auch noch von meinem eigenen bei gatling beiliegenden Benchmark-Tool getriggert. Ich hatte gedacht, dass mal bei früheren Versionen getestet zu haben, aber habe keine Aufzeichnungen und bin mir auch gerade nicht mehr sicher. Im Moment ist jedenfalls klar: vor dieser Funktionalität kann ich nur warnen. Benutzt das nicht in eurer Software!
Danke an Johannes, der mich überhaupt erst auf das Problem hingewiesen hat.