サーバーはどのクライアントポートに送信するかをどのように調べますか?

サーバーはどのクライアントポートに送信するかをどのように調べますか?

私が理解したところ、クライアントが接続要求をすると、次のことが起こります。

  1. サーバーは特定のポート番号にバインドされます。ポート番号は常に受信プロセスに関連付けられています。サーバーだけが着信接続を受信して​​いるため、クライアント側でバインドする必要はありません。
  2. サーバーは引き続きこのポート番号をリッスンします。
  3. connect()クライアントが要求を送信します。
  4. サーバーは承認要求を使用しますaccept()。サーバーがクライアント要求を受け入れると、カーネルは追加操作のためにサーバーにランダムなポート番号を割り当てます。これは、send()サーバーreceive()の同じポート番号が送受信に使用できず、古いポートがまだ新しい接続を受信して​​いるためです。

これらすべてを考慮すると、サーバーはどのクライアントがどのポートでデータを受信して​​いるかをどのように知ることができますか?クライアントは送信元ポートと宛先ポートを含むTCPセグメントを送信することを知っているので、サーバーはそのセグメントの送信元ポートを宛先ポートとして使用しますが、サーバーはどのポートを見つけるためにそのポートを見つけるのですか?うんaccept()

答え1

これはパケットのTCP(またはUDPなど)ヘッダーの一部です。したがって、クライアントが指示するので、サーバーは調べます。これは、クライアントのIPアドレス(IPヘッダーの一部)を見つける方法と似ています。

たとえば、すべてのTCPパケットにはIPヘッダー(最小ソースIP、宛先IP、およびプロトコル[TCP]を含む)が含まれています。次にTCPヘッダー(ソースポートと宛先ポートなどを含む)が続きます。

カーネルがリモートIPが10.11.12.13(IPヘッダーから)でリモートポートが12345(TCPヘッダーから)のSYNパケット(TCP接続の開始)を受信すると、リモートIPとポートがわかります。 SYN | ACKを再送信します。 ACKが受信されると、listenコールは接続に確立された新しいソケットを返します。

TCPソケットは、4つの値(リモートIP、ローカルIP、リモートポート、ローカルポート)で一意に識別されます。少なくとも1つが異なる限り、複数の接続/ソケットを持つことができます。

通常、ローカルポートとローカルIPは、サーバープロセスへのすべての接続に対して同じです(たとえば、sshdへのすべての接続はlocal-ip:22にあります)。リモートコンピュータが複数の接続を作成する場合、各接続は異なるリモートポートを使用します。したがって、リモートポート以外のすべては同じですが、大丈夫です。 4つのポートのうち1つだけが異なる必要があります。

たとえば、wirehsark を使用してパケットを表示でき、すべてのデータにタグが付けられます。以下は強調表示されたソースポートです(デコードされたパケットで強調表示され、下部の16進ダンプに注意してください)。

Wireshark は TCP SYN パケットを表示します。

答え2

「接続要求(connect()通常はクライアントプログラムのシステムコール)による三回の握手。 3方向ハンドシェイク(クライアントからサーバーへ)の最初のパケットにはSYNフラグが設定され、クライアントプログラムカーネルによって割り当てられたTCPポート番号が含まれています。

することができますNmapとNatural SYNパケットに関する記事。 Nmap SYNパケットのデコードには、「source.60058> dest.22」というフレーズがあります。デコードされた「正当なSYNパケット」には、「source.35970> dest.80」というフレーズが含まれています。これら2つのSYNパケットは、それぞれがTCPポート60058と35970から来たことをリモートカーネルに通知します。

答え3

TCPソケットはストリーム指向のソケットです。 2つのソケット記述子(あなたと同僚が所有する)が確実に接続されています。したがって、クライアントポートについて心配する必要はありません。ソケット記述子を作成するだけです!

また、本当に知りたい場合(おそらく記録のために)、自由にgetsockname(2)を使用してください。

答え4

接続はタプル(ソースIP、送信元ポート、宛先IP、宛先ポート)として定義されます。答えは正反対です。

関連情報