Wie kann ich eine Socket-Verbindung in C ablehnen?
Lesezeit: 6 Minuten
Wenn ich eine Verbindung annehmen will, rufe ich an acceptaber wie kann ich eine Verbindung ablehnen?
In einem funktionierenden Socket-Echo-Client habe ich diese if-Anweisung. Wie kann ich im Echo-Server bewirken, dass der Echo-Client dies erreicht? printf Aussage?
@BartFriederichs: Das mache ich gerade, aber gibt es eine Möglichkeit, es tatsächlich expliziter abzulehnen?
– c00kiemonster
16. Mai 2013 um 14:58 Uhr
Basierend auf was würden Sie ablehnen? Ich würde sagen, was Sie wollen, ist die Aufgabe einer Firewall. Die meisten Anwendungen, die ich kenne, die mit Blacklisting oder ähnlichem arbeiten, würden akzeptieren und schließen.
– Bart Friedrichs
16. Mai 2013 um 15:00 Uhr
Eigentlich möchte ich unbedingt eine Verbindung nur auf diesem bestimmten Port. Jede andere Verbindung sollte idealerweise auf sehr offensichtliche Weise fehlschlagen.
– c00kiemonster
16. Mai 2013 um 15:03 Uhr
Setzen Sie das Backlog-Argument auf listen(2).
– Fizzer
16. Mai 2013 um 15:04 Uhr
jxh
Um das gewünschte Verhalten zu erzielen (akzeptiere nur jeweils eine Verbindung, andere Clients sollten beim Versuch fehlschlagen), gibt es zwei Möglichkeiten.
Sie können Ihren Listen-Socket schließen, nachdem Sie eine Verbindung akzeptiert haben. Erstellen Sie Ihren Listen-Socket neu, nachdem die akzeptierte Verbindung geschlossen wurde.
Sie können neu hergestellte Verbindungen schließen, wenn bereits eine Verbindung besteht. Wenn Sie möchten, dass der Client einen TCP-Reset sieht, lösen die meisten TCP-Stacks einen aus, wenn Sie die Linger-Option mit einem Timeout von 0 aktivieren.
Wird die erste Möglichkeit in der Praxis wirklich genutzt? Es könnte besser sein, den Listening-Socket offen zu halten, um sicherzustellen, dass die Ressource dem Programm für seine Verwendung “gehört”, solange es läuft.
– Craig McQueen
9. Mai 2016 um 0:34 Uhr
@CraigMcQueen: Ich gehe davon aus, dass Serverports bereitgestellt wurden, wenn diese Option verwendet wird.
– jxh
9. Mai 2016 um 8:16 Uhr
Meines Wissens nach funktioniert TCP so nicht. Das accept(..) Der Anruf wird immer mit den Kundendetails zurückgegeben. Es gibt keine Möglichkeit spähen am Anschluss und selektiv ablehnen.
So wie du es jetzt machst, ist es eigentlich richtig: Akzeptieren und dann schließen. Falls Sie über dieser Ebene eine andere Nachrichtenstruktur haben, können Sie eine benutzerdefinierte “Ablehnungsnachricht” erstellen. Diese Option hängt vollständig von Ihrem Anwendungsfall ab.
Falls Sie nach einer Ablehnung auf der Grundlage der IP-Adresse suchen, liegt diese nicht innerhalb Ihrer App-Domain. Es ist die Aufgabe Ihrer Firewall (wie @Bart Friederichs sagt). Auf diese Weise berührt die Anfrage nicht einmal den TCP-Stack.
Eigentlich möchte ich unbedingt eine Verbindung nur auf diesem bestimmten Port. Jede andere Verbindung sollte idealerweise auf sehr offensichtliche Weise fehlschlagen.
Lassen Sie die Anrufannahme nicht in Ihren Kontrollfluss. Nur wenn Sie warten accept wird Ihr Programm auf eine Socket-Verbindung warten, sonst nie.
In Standard-Socket-APIs auf den meisten Plattformen gibt es keine Möglichkeit, eine Verbindung abzulehnen. Du musst accept() die Verbindung und schließen Sie sie sofort, wenn Sie dies nicht möchten.
Die Ausnahme von dieser Regel ist die Winsock-spezifische WSAAccept() Funktion. Es bietet einen Rückruf, der es einer Anwendung ermöglicht, für jede Verbindung zu entscheiden, ob eine Verbindung akzeptiert, abgelehnt oder in der Rückstandswarteschlange gehalten werden soll.
Es könnte hilfreich sein
um den lauschenden Server-Socket nach erfolgreichem Abschluss zu schließen accept()ing der Client-Verbindung und
um es wiederherzustellen, nachdem die Client-Verbindung aus irgendeinem Grund unterbrochen wurde.
Etwas spät zur Party, aber Sie können WSAAccept() anstelle von accept() verwenden. WSAAccept() verfügt über eine optionale Callback-Funktion, mit der Sie einen Blick darauf werfen können, wer an die Tür klopft, und entscheiden, ob Sie antworten möchten. Ihre Callback-Funktion kann die Konstanten CF_ACCEPT, CF_REJECT und CF_DEFER zurückgeben. Die ersten beiden sind offensichtlich. Die dritte ermöglicht es Ihnen, die Beantwortung aufzuschieben, falls Sie sich später entscheiden müssen. Sobald Sie sich sicher entschieden haben, rufen Sie WSAAccept() erneut auf und akzeptieren oder lehnen ab.
Leider müssen Sie entweder akzeptieren oder ablehnen, um den Eintrag von der Vorderseite der Listen-Warteschlange zu entfernen. Der Grund, warum ich sage, dass es unglücklich ist, ist, dass es einen offensichtlichen Unterschied zum Verbindungscomputer gibt, ob er abgelehnt wird oder nie eine Antwort erhält (Zeitüberschreitung).
Wenn ein Hacker einen Port-Scanner verwendet, weiß er, dass Sie den Port abhören, wenn Sie ihn ablehnen. An diesem Punkt können sie anfangen, sich einzuhacken. Es wäre schön, den Eintrag von der Vorderseite der Warteschlange entfernen zu können, ohne jemals etwas damit zu tun, so dass derjenige am anderen Ende nicht weiß, dass Sie mithören dieser Hafen.
Es ist so seltsam, dass es dafür keine Funktionen gibt. Ich erstelle einen Webserver und dachte, dass ich jedes gesperrte IP-Timeout machen sollte (nicht die TCP-Verbindung öffnen und mein Betriebssystem alle Informationen freigeben sollte, die dieser eingehenden Verbindung zugewiesen sind). Aber das scheint nicht möglich zu sein, ohne mein eigenes Betriebssystem oder meinen eigenen Netzwerktreiber zu schreiben? Ich denke, wenn ich die Verbindung nie öffne, werden die Router auch keine Pakete mehr davon akzeptieren. Dadurch kann ich im Falle von DoS etwas Bandbreite sparen.
– Joakim L. Christiansen
4. Februar 2020 um 6:48 Uhr
Eine Fortsetzung dessen, was ich oben geschrieben habe. Da ich Linux verwende, habe ich festgestellt, dass der Dienst firewalld tun kann, was ich will. Ich kann es anweisen, bestimmte IP-Adressen zu “sperren”, und für sie sieht es so aus, als ob ich dann keinen Server betreibe. Und ich kann mit diesem Dienst von meinem eigenen Server aus kommunizieren 🙂
– Joakim L. Christiansen
4. Februar 2020 um 10:09 Uhr
Es ist so seltsam, dass es dafür keine Funktionen gibt. Ich erstelle einen Webserver und dachte, dass ich jedes gesperrte IP-Timeout machen sollte (nicht die TCP-Verbindung öffnen und mein Betriebssystem alle Informationen freigeben sollte, die dieser eingehenden Verbindung zugewiesen sind). Aber das scheint nicht möglich zu sein, ohne mein eigenes Betriebssystem oder meinen eigenen Netzwerktreiber zu schreiben? Ich denke, wenn ich die Verbindung nie öffne, werden die Router auch keine Pakete mehr davon akzeptieren. Dadurch kann ich im Falle von DoS etwas Bandbreite sparen.
– Joakim L. Christiansen
4. Februar 2020 um 6:48 Uhr
Eine Fortsetzung dessen, was ich oben geschrieben habe. Da ich Linux verwende, habe ich festgestellt, dass der Dienst firewalld tun kann, was ich will. Ich kann es anweisen, bestimmte IP-Adressen zu “sperren”, und für sie sieht es so aus, als ob ich dann keinen Server betreibe. Und ich kann mit diesem Dienst von meinem eigenen Server aus kommunizieren 🙂
– Joakim L. Christiansen
4. Februar 2020 um 10:09 Uhr
12984500cookie-checkWie kann ich eine Socket-Verbindung in C ablehnen?yes
akzeptieren und sofort schließen
– Bart Friedrichs
16. Mai 2013 um 14:57 Uhr
@BartFriederichs: Das mache ich gerade, aber gibt es eine Möglichkeit, es tatsächlich expliziter abzulehnen?
– c00kiemonster
16. Mai 2013 um 14:58 Uhr
Basierend auf was würden Sie ablehnen? Ich würde sagen, was Sie wollen, ist die Aufgabe einer Firewall. Die meisten Anwendungen, die ich kenne, die mit Blacklisting oder ähnlichem arbeiten, würden akzeptieren und schließen.
– Bart Friedrichs
16. Mai 2013 um 15:00 Uhr
Eigentlich möchte ich unbedingt eine Verbindung nur auf diesem bestimmten Port. Jede andere Verbindung sollte idealerweise auf sehr offensichtliche Weise fehlschlagen.
– c00kiemonster
16. Mai 2013 um 15:03 Uhr
Setzen Sie das Backlog-Argument auf listen(2).
– Fizzer
16. Mai 2013 um 15:04 Uhr