서버는 보낼 클라이언트 포트를 어떻게 알 수 있습니까? . 서버는를 사용하여 요청을 수락합니다 accept(). 즉시

내가 알기로 이것은 클라이언트가 연결 요청을 할 때 발생합니다.

  1. 서버는 특정 포트 번호에 바인딩됩니다. 포트 번호는 항상 청취 프로세스에 바인딩됩니다. 서버 만이 들어오는 연결을 수신하고 있기 때문에 클라이언트 쪽에서 바인딩 할 필요가 없습니다.
  2. 서버는 해당 포트 번호에서 수신 대기 상태를 유지합니다.
  3. 클라이언트가 connect()요청 을 보냅니다 .
  4. 서버는를 사용하여 요청을 수락합니다 accept(). 즉시 서버가 클라이언트 요청, 추가의 서버에 임의의 포트 번호 커널 할당 받아으로 send()하고 receive(), 서버에 동일한 포트 번호를 청취뿐만 아니라 보내는 데 사용할 수 없기 때문에, 이전 포트가 여전히를 새로운 연결 청취

이 모든 것을 감안할 때 서버는 클라이언트가 수신하는 포트를 어떻게 알 수 있습니까? 클라이언트가 소스 포트와 대상 포트가있는 TCP 세그먼트를 전송한다는 것을 알고 서버는 해당 세그먼트의 소스 포트를 대상 포트로 사용하지만 서버는 해당 포트에 대해 어떤 기능을 호출합니까? 그렇 accept()습니까?



답변

패킷에서 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, 원격 포트, 로컬 포트)으로 고유하게 식별됩니다. 최소한 하나의 연결이 다른 한 여러 연결 / 소켓을 가질 수 있습니다.

일반적으로 로컬 포트와 로컬 IP는 서버 프로세스에 대한 모든 연결에서 동일합니다 (예 : sshd에 대한 모든 연결은 local-ip : 22에 있음). 하나의 원격 시스템이 여러 개의 연결을 수행하는 경우 각 원격 시스템은 서로 다른 원격 포트를 사용합니다. 따라서 원격 포트를 제외한 모든 것은 동일하지만 괜찮습니다. 4 개 중 하나만 달라야합니다.

예를 들어 wirehsark를 사용하여 패킷을 볼 수 있으며 모든 데이터에 레이블을 지정합니다. 다음은 강조 표시된 소스 포트입니다 (디코딩 된 패킷에서 강조 표시되고 맨 아래의 16 진 덤프).


답변

“연결 요청 ( connect()일반적으로 클라이언트 프로그램의 시스템 호출)은 3 방향 핸드 셰이크를 발생시킵니다. 3 방향 핸드 셰이크 의 첫 번째 패킷 (클라이언트에서 서버로)은 SYN 플래그를 설정하며 클라이언트 프로그램의 TCP 포트 번호를 포함합니다. 커널이 할당합니다.

이것은 Nmap vs Natural SYN 패킷 에 관한 기사에서 볼 수 있습니다 . Nmap SYN 패킷 디코딩에는 “source.60058> dest.22″라는 문구가 있습니다. “합법적 인 SYN 패킷”디코딩에는 “source.35970> dest.80″이라는 문구가 있습니다. 2 개의 SYN 패킷은 패킷이 각각 TCP 포트 60058 및 포트 35970에 있음을 원격 커널에 알려줍니다.


답변

TCP 소켓은 스트림 지향 소켓입니다. 두 개의 소켓 설명자 (귀하와 동료가 소유)가 안정적으로 연결되어 있습니다. 따라서 클라이언트 포트에 대해 걱정할 필요가 없습니다. 소켓 설명자를 작성하십시오!

또한 (아마도 로깅을 위해) 정말로 알고 싶다면 getsockname (2)을 사용하십시오.


답변

연결은 튜플 (소스 IP, 소스 포트, 대상 IP, 대상 포트)로 정의됩니다. 답은 그 반대입니다.