web-dev-qa-db-ja.com

サーバーはどのクライアントポートに送信するかをどのようにして見つけますか?

私が理解しているように、これはクライアントが接続要求を行ったときに何が起こるかです:

  1. サーバーは特定のポート番号にバインドされます。ポート番号は常にリスニングプロセスにバインドされています。サーバーだけが着信接続をリッスンしているので、クライアント側でバインドする必要はありません
  2. サーバーはそのポート番号でlisteninigを続けます。
  3. クライアントはconnect()リクエストを送信します。
  4. サーバーはaccept()を使用してリクエストを受け入れます。サーバーがクライアント要求を受け入れるとすぐに、カーネルはサーバーにランダムなポート番号を割り当て、さらにsend()およびreceive()を割り当てます。サーバー上の同じポート番号は送信とリッスンに使用され、以前のポートはまだ新しい接続をリッスンしています

これらすべてを考慮して、サーバーはどのようにしてクライアントが受信しているポートを見つけますか?クライアントがTCPセグメントを送信元ポートと宛先ポートで送信することを知っているので、サーバーはそのセグメントの送信元ポートを宛先ポートとして使用しますが、どの関数がサーバーを呼び出して検索しますかそのポートについてアウト?それはaccept()ですか?

26
Subi Suresh

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

たとえば、すべてのTCPパケットには、IPヘッダーが含まれています(少なくとも送信元IP、宛先IP、およびプロトコル[TCP])。次に、TCPヘッダーがあります(送信元ポートと宛先ポートに加えて)。

カーネルがSYNパケット(TCP接続の開始)を受信し、リモートIPが10.11.12.13(IPヘッダー内)およびリモートポートが12345(TCP内)の場合_ヘッダー)。リモートIPとポートを認識します。 SYN | ACKを返信します。 ACKが返された場合、listen呼び出しは、その接続用に設定された新しいソケットを返します。

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

通常、ローカルポートとローカルIPは、サーバープロセスへのすべての接続で同じです(たとえば、sshdへのすべての接続はlocal-ip:22になります)。 1つのリモートマシンが複数の接続を行う場合、それぞれが異なるリモートポートを使用します。したがって、リモートポート以外はすべて同じになりますが、それは問題ありません。4つのうち1つだけが異なっていれば十分です。

Wirehsarkなどを使用してパケットを表示すると、すべてのデータにラベルが付けられます。これが強調表示された送信元ポートです(デコードされたパケットで強調表示されていること、および下部の16進ダンプに注意してください)。

Wireshark showing a TCP SYN packet

33
derobert

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

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

2
Bruce Ediger

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

また、本当にログを知りたい場合は、getsockname(2)を使用してください(おそらくロギング用)。

1
b166er

接続はタプル(ソースIP、ソースポート、宛先IP、宛先ポート)によって定義されます。答えは逆になります。

0
vonbrand