본문 바로가기

Network H&S/Network Basic

3-Way HandShaking 분석

TCP/IP Protocol 에서 TCP에 대해 분석한 문서에보면 TCP는 연결지향 프로토콜이라고 해놓았습니다.

이러한 연결지향 전송은

1. 연결 설정
2. 데이터 전송
3. 연결 종료


위 세가지 절차를 통하여 이루어지게 됩니다. 

이번에는 위 3가지중 연결 설정에 해당하는 3-way handshaking 에 대해서 알아보겠습니다. 그리고 마지막에 실제 패킷을 캡쳐하여 분석해 보겠습니다.

이 과정이 일어나기 위해서는 일반적으로

* 서버 프로그램이 자신의 TCP에게 연결할 수 있다는 것을 알립니다. ( passive open )
* 서버와 연결하고자 하는 클라이언트 프로그램은 active open을 위한 요구를 수행합니다.

위의 두가지 절차가 끝나게 되면 본격적으로 3-way handshake 절차를 시작하게 됩니다.

그러면 이제 그 절차를 하나하나 알아보도록 하겠습니다.





1. 클라이언트는 첫 번째 세그먼트로서 SYN Flag가 1로 설정된 SYN 세그먼트를 전송하여 연결 요청을 합니다.


처음 보내는 SYN 세그먼트는 seq의 동기화가 목적입니다. 

여기서는 seq = 8000 으로 설정이 되어 있네요. ( 이 번호를 ISN [ Initial Sequence Number ] 이라고도 합니다. )

SYN 세그먼트는 데이터를 전달하지는 않지만 하나의 seq를 소비합니다.

즉, 지금 seq = 8000 이지만 다음번 SYN 세그먼트를 보내거나 데이터를 전송할 경우 seq = 8001이 됩니다.


[ Client 상태 ] C로 언급

CCLOSE 상태에서 Active Open 요구를 수행하고 SYN 세그먼트를 전송하는 순간 자신의 상태를 SYN-SENT 상태로 변경합니다.

[Server 상태 ] S로 언급
SCLOSE 상태에서 Passive Open으로 인해 LISTEN 상태로 변경되고 이 상태는 SYN + ACK 세그먼트를 전송하기 전까지는 변경되지 않습니다. 즉, 여기서는 SYN 세그먼트를 받기만 하였으므로 S의 상태는 LISTEN 상태입니다.





2. 서버는 두 번째 세그먼트로 SYN와 ACK Flag 비트가 1로 설정된 SYN + ACK 세그먼트를 전송하여 클라이언트의 요청을 받아들이는 동시에 서버가 클라이언트로 연결을 요청합니다.


SYN + ACK 세그먼트는 두가지 목적을 가지고 있습니다.

또한, Server 버퍼에서 데이터 손실을 막기 위해 Server가 수신할 수 있는 바이트수를 나타내는 rwnd(Reciver Window)필드를 포함합니다. 

첫 번째로, Client 로 통신을 하기 위해 동기화를 위한 SYN 세그먼트를 전송합니다.
두 번째로, Client 로부터 수신받을 다음 seq 번호를 ACK 필드에 표시 함으로써 Client 로부터 다음 SYN 세그먼트 수신을 확인합니다. 

여기서는 seq = 15000, ack = 8001, rwnd = 5000 으로 설정이 되어 있네요.

SYN + ACK 세그먼트는 데이터를 전달하지는 않지만 하나의 seq를 소비합니다.

즉, 지금 seq = 15000 이지만 다음번 SYN 세그먼트를 보내거나 데이터를 전송할 경우 seq = 15001이 됩니다. 그리고 첫번째 세그먼트에서 seq = 8000 을 받았으므로 다음에는 seq = 8001부터 전송하라는 의미로 ack = 8001이 됩니다. 이말은 seq = 8000 까지는 잘 받았다는 의미가 됩니다. 만약 10 Byte의 데이터가 세그먼트에 포함되어 있었다면 ack = 8011이 됩니다. 이 부분에 대해서는 다음에 설명할 데이터 전송에서 더 자세히 다루겠습니다. 


[ Client 상태 ]

CSYN-SENT 상태에서 SYN + ACK 세그먼트를 수신하였지만 ACK 세그먼트를 전송하기 전까지는 SYN-SENT상태를 유지합니다. 즉, 여기서는 ACK 세그먼트를 전송하지 않았으므로 CSYN-SENT 상태를 유지합니다.

[Server 상태 ] 
SLISTEN 상태에서 SYN + ACK 세그먼트를 전송하였으므로 SYN-RCVD 상태로 변경됩니다.





3. 클라이언트는 세 번째 세그먼트로 ACK Flag 비트가 1로 설정된 ACK 세그먼트를 전송하여 서버의 요청을 받아들입니다. 이로써 서버와 클라이언트간에 연결이 설정되었습니다.


이 세그먼트는 ACK Flag와 ACK 번호 필드를 이용하여 두 번째 세그먼트의 수신을 확인합니다.

또한, Client 버퍼에서 데이터 손실을 막기 위해 Client가 수신할 수 있는 바이트수를 나타내는 rwnd(Reciver Window)필드를 포함합니다.

여기서는 seq = 8001, ack = 15001, rwnd = 10000 으로 설정이 되어 있네요. 

ACK 세그먼트는 데이터를 전달하지 않는 경우에는 seq를 소비하지 않습니다.

즉, 처음 보냈던 세그먼트의 seq = 8000 에서 1이 증가되어 seq = 8001 이 되고 ACK 세그먼트는 seq를 소비하지 않기 때문에 다음번에 SYN 세그먼트나 데이터를 전송할때도 seq = 8001 이 됩니다. 그리고 두번째 세그먼트로부터 seq = 15000 을 받았으므로 ack = 15001 이 됩니다.


[ Client 상태 ]

CSYN-SENT 상태에서 ACK 세그먼트를 전송하였으므로 ESTABLISH 상태로 변경됩니다. 이 상태에서 TCP는 양방향으로 데이터를 교환하며 확인, 응답 합니다.

[Server 상태 ] 
SSYN-RCVD 상태에서 ACK 세그먼트를 수신하였으므로 ESTABLISH 상태로 변경됩니다. 이 상태에서 TCP는 양방향으로 데이터를 교환하며 확인, 응답 합니다.





위의 이론이 맞는지 실제 패킷을 캡쳐하여 보았습니다.


1. SYN 전송
2. SYN, ACK 수신
3. ACK 전송

3-way handshaking 이 일어 났네요 ^^

좀더 자세히 보기 위해 패킷들의 세부사항을 캡쳐해 보았습니다.




다른건 볼거 없구 seq = 0, SYN Flag = 1, Window  Size = 65535 이렇게 설정되어 있네요

여기에서는 Ack number 번호가 없으니 Window Size는 무의미 하겠네요 ~




seq = 0, ACK = 1, SYN Flag = 1, ACK Flag = 1, Window Size = 8190 으로 설정되어 있네요.

ACK number 값이 있으니 Window Size 값은 적용이 되겠지요 ^^





seq = 1, ACK = 1, ACK Flag = 1, Window Size = 65535 로 설정 되어 있습니다.