Wie findet der Server heraus, an welchen Client-Port gesendet werden soll?

26

Soweit ich weiß, passiert Folgendes, wenn ein Client eine Verbindungsanfrage stellt:

  1. Der Server wird an eine bestimmte Portnummer gebunden. Die Portnummer ist immer an einen Abhörvorgang gebunden. Da nur der Server auf eingehende Verbindungen wartet, müssen wir keine Bindung auf der Clientseite herstellen
  2. Der Server überwacht diese Portnummer weiterhin.
  3. Der Client sendet eine connect()Anfrage.
  4. Der Server akzeptiert die Anfrage mit accept(). Sobald der Server die Client - Anforderung, das Kernel - allocates eine zufällige Portnummer für den Server zum weiteren akzeptiert send()und receive(), da die gleichen Portnummer auf dem Server für das Senden als auch Hören nicht verwendet werden kann, und der vorherigen Hafen ist immer noch neue Verbindungen suchen

Wie kann der Server angesichts all dessen herausfinden, auf welchem ​​Port der Client empfängt? Ich weiß, dass der Client TCP-Segmente mit einem Quell- und einem Zielport sendet, sodass der Server den Quellport dieses Segments als Zielport verwendet. Welche Funktion ruft der Server jedoch auf, um diesen Port zu ermitteln? Ist es accept()?

Subi Suresh
quelle

Antworten:

33

Es ist Teil des TCP-Headers (oder UDP-Headers usw.) im Paket. Der Server findet es heraus, weil der Client es ihm sagt. Dies ähnelt dem Ermitteln der IP-Adresse des Clients (die Teil des IP-Headers ist).

Beispielsweise enthält jedes TCP-Paket einen IP-Header (mindestens mit Quell-IP, Ziel-IP und Protokoll [TCP]). Dann gibt es einen TCP-Header (mit Quell- und Zielport und mehr).

Wenn der Kernel ein SYN-Paket (den Start einer TCP-Verbindung) mit einer Remote-IP von 10.11.12.13 (im IP-Header) und einem Remote-Port von 12345 (im TCP-Header) empfängt, kennt er die Remote-IP und den Remote-Port . Es sendet ein SYN | ACK zurück. Wenn es eine Bestätigung zurückerhält, gibt der listenAnruf einen neuen Socket zurück, der für diese Verbindung eingerichtet wurde.

Ein TCP-Socket wird durch die vier Werte (Remote-IP, lokale IP, Remote-Port, lokaler Port) eindeutig identifiziert. Sie können mehrere Anschlüsse / Sockets haben, sofern sich mindestens einer davon unterscheidet.

In der Regel sind der lokale Port und die lokale IP für alle Verbindungen zu einem Serverprozess gleich (z. B. alle Verbindungen zu sshd erfolgen über die lokale IP: 22). Wenn ein Remote-Computer mehrere Verbindungen herstellt, verwendet jeder einen anderen Remote-Port. Alles außer dem Remote-Port ist also gleich, aber das ist in Ordnung - nur einer der vier muss sich unterscheiden.

Sie können z. B. wirehsark verwenden, um das Paket zu sehen, und es kennzeichnet alle Daten für Sie. Hier ist der Quellport hervorgehoben (beachten Sie, dass er im dekodierten Paket hervorgehoben ist, sowie der hexadezimale Speicherauszug unten):

Wireshark zeigt ein TCP SYN-Paket

derobert
quelle
> Vielen Dank für die Erklärung. Sie wollten also sagen, dass ein neuer Server-Socket-Deskriptor (dh ein Tupel), der nach accept () abgerufen wurde, die Details zu Client-Port und Client-Adresse enthält und über diesen neuen Socket-Deskriptor-Server die Daten sendet und empfängt und von client.New Socket-Datei-Deskriptor wird eine neue Server-Port-Nummer von Kernel, Server-IP, Client-IP und Client-Port zugewiesen. Bin ich richtig?
Subi Suresh
@SubiSuresh ja, das Tupel wird im Kernel gespeichert, der diesem Dateideskriptor zugeordnet ist.
Derobert
> Danke derobert. Also ich komme zu dem Schluss, dass der neue Server-Socket-Deskriptor den Client-Port und die Client-Adresse haben wird, die der Server von accept () erhält. Mein Verständnis ist in Ordnung, oder?
Subi Suresh
@SubiSuresh Ja, das stimmt. Vom Standpunkt der Anwendung aus ist es Ihnen normalerweise egal (außer für die Protokollierung). Der Kernel sorgt dafür, dass die Daten, die Sie write(usw.) erhalten, an die richtige Stelle gelangen.
Derobert
> danke für deine hilfe und ich glaube, ich habe verstanden. ;-)
Subi Suresh
2

Die "Verbindungsanforderung" ( connect()normalerweise der Systemaufruf des Client-Programms ) bewirkt einen Drei-Wege-Handshake . Das erste Paket des Drei-Wege -Handshakes (vom Client zum Server) enthält das SYN-Flag und die TCP-Port-Nummer des Client-Programms Kernel weist es zu.

Sie können dies in einem Artikel über Nmap vs Natural SYN-Pakete sehen . Die Nmap-SYN-Paketdecodierung hat den Ausdruck "source.60058> dest.22". Die Dekodierung des "legitimen SYN-Pakets" enthält den Ausdruck "source.35970> dest.80". Die beiden SYN-Pakete teilen dem Remote-Kernel mit, dass die Pakete vom TCP-Port 60058 bzw. vom Port 35970 stammen.

Bruce Ediger
quelle
> Aber Bruce, das passiert im Back-End. Aber wie mein Server tatsächlich die Details wie Portnummer abruft, weil dies normalerweise in Client-Server-Programmen der Fall ist, habe ich noch nie eine Funktion zum Abrufen von Client-Port und Client-Adresse gesehen
Subi Suresh
Der Systemaufruf getpeername()sollte dies an jedem offenen Socket ermöglichen. Der accept()Systemaufruf, den der Servercode verwenden muss, um einen Socket-Dateideskriptor für die Kommunikation mit dem Client zu erhalten, enthält einen Parameter ("sockaddr" in meinen Manpages), der die IP-Adresse und die TCP-Portnummer des potenziellen Clients enthält.
Bruce Ediger
> Bitte nicht bedenken, wenn ich elloboriere. Von allen Eingaben habe ich verstanden, dass accept () die Struktur sockaddr_in mit Client-Details gefüllt hat und der neue Server-Socket-Deskriptor, der nach accept () zurückgegeben wird, automatisch Client-Port und -Adresse hat. Das ist, warum wir senden können, indem wir senden (neuer Server-Socket-Deskriptor). Ich hoffe, dass ich auf dem neuesten Stand bin?
Subi Suresh
@SubiSuresh - Ich glaube, du hast die Wahrheit geschrieben.
Bruce Ediger
1

TCP-Socket ist ein stream-orientierter Socket. Die beiden Socket-Deskriptoren (im Besitz von Ihnen und Ihrem Peer) sind zuverlässig verbunden. Sie müssen sich also keine Sorgen um den Port des Clients machen - schreiben Sie einfach Ihren Socket-Deskriptor!

Fühlen Sie sich auch frei, getsockname (2) zu verwenden, wenn Sie das wirklich wissen möchten (zum Protokollieren vielleicht).

b166er
quelle
0

Die Verbindung wird durch ein Tupel definiert (Quell-IP, Quell-Port, Ziel-IP, Ziel-Port). Die Antworten gehen in die umgekehrte Richtung.

vonbrand
quelle
@vondrand An diesem Punkt habe ich von verstanden .Aber von welcher Funktion erfährt der Server die Client-Portnummer? Ohne die Client-Portnummer zu kennen, wie sie gesendet wird. Verwendet der Server die Struktur in accept (), um den Client abzurufen Hafen ?
Subi Suresh