TCP 3-way-handshake / 4-way-handshake
TCP 3-way-handshake / 4-way-handshake
TCP Handshake란?
OSI 7계층 중 Network layer에 해당하는 프로토콜인 TCP는 장치들 사이에 논리적인 접속을 성립(establish)하기 위하여 3-way handshake를 사용하고 세션을 종료를 성립하기 위해 4-way handshake를 사용한다.
용어
Client / Server
양쪽 모두 클라이언트가 될 수도, 서버가 될 수 있다. 따라서, 편의상 요청을 먼저 보낸 쪽을 클라이언트로 , 연결 요청을 받은 수신자를 서버라고 함.
SYN / ACK
SYN : Synchronize Sequence Number
ACK : Acknowledgement - 클라이언트가 보낸 동기화 요청에 대한 답변이다. 서버는 클라이언트가 보낸 동기화 요청의 SYN(synchronize Sequence Number에 + 1 을 하여 ACK로 돌려주게 된다.
TCP Header의 구성 필드들 중 하나로 Code Bit(Flag Bit)이 있다. 이 필드는 총 6Bit로 이루어져 있으며 각 비트들을 통해 해당 패킷이 어떤 내용을 담고 있는 패킷인지를 나타낸다.
예를들어 TCP 패킷이 SYN에 해당하는 패킷이라면 000010으로 표현되며, ACK 패킷일 경우에는 010000이 된다.
3-way handshake 접속 과정

-
클라이언트는 접속을 요청하는 SYN 패킷을 보낸다. 이때 클라이언트는 SYN 패킷을 보냄과 동시에 SYN/ACK 응답을 기다리기위해 SYN_SENT 상태로 변하게 된다.
-
서버는 SYN 요청을 받고 클라이언트에게 요청을 수락하는 ACK 패킷과 SYN 패킷을 보내고 SYN_RCVD(SYN_RECEIVED)상태로 변하여 클라이언트가 ACK 패킷을 보낼 때 까지 기다리게 된다.
-
클라이언트는 서버에 ACK 패킷을 보내고 이 후 ESTABLISHED 상태가 되어 데이터 통신이 가능하게 된다.
- 즉, ACK 패킷의 Acknowledgement Number는 신뢰적 데이터 전송을 위해 사용되는 것이다.
- ISN( Initialized Sequence Number ): 초기 시퀀스 번호 - SYN 패킷의 Sequence Number는 운영체제의 의해서 랜덤하게 생성된다.
- 동기화 요청에 대한 답신 - 클라이언트의 시퀀스 넘버에 +1을 해서 ack로 돌려준다.
4-way handshake 종료 과정
아래 그림에서 처음 보내는 종료 요청인(1) FIN 패킷에 실질적으로 ACK가 포함되어 있는 것을 알 수 있는데, 이러한 방식을 Half-Close 기법 이라고 한다.
- 연결을 종료 할 때 완전히 종료하지 않고 반만 종료하는 방법.
- Half-Close 기법을 사용하면 종료 요청자가 처음 보내는 FIN 패킷에 승인 번호를 함께 담아서 보내게 되는데, 이때 승인 번호의 의미는 “일단 연결은 종료할건데 귀는 열어둘게. 이 승인 번호까지 처리했으니까 더 보낼 거 있으면 보내” 이다.
- 이후 수신자가 남은 데이터를 모두 보내고 나면 다시 요청자에게 FIN 패킷을 보냄으로써 모든 데이터가 처리되었다는 신호 (3) FIN를 보내게 된다. 이 이후, 요청자는 나머지 반을 닫게 된다. 좀더 안전한 종료를 보장하기 위한 방법이다.

-
서버와 클라이언트가 TCP 연결이 되어있는 상태에서 클라이언트가 접속을 끊기 위해 CLOSE() 함수를 호출하게 된다. 이후 CLOSE() 함수를 호출하면서 FIN segment를 보내게 되고 클라이언트는 FIN_WAIT1 상태로 변하게 된다.
-
서버는 클라이언트가 CLOSE() 한다는 것을 알게되고 CLOSE_WAIT 상태로 바꾼 후 ACK segment를 전송한다. 즉, 클라이언트가 끊을 것이라는 신호를 받았다는 의미이고 CLOSE_WAIT 상태로 변하고 자신의 통신이 끝날때까지 기다린다.
-
ACK segment를 받은 클라이언트는 FIN_WAIT2로 변환되고 이때 서버는 CLOSE() 함수를 호출하고 FIN segment를 클라이언트에게 보낸다.
-
서버도 연결을 닫았다는 신호를 클라이언트가 수신하면 ACK segment를 보낸 후 TIME_WAIT 상태로 전환된다.
이 후 모든것이 끝나면 양측 모두 CLOSED 상태로 변환된다.
비정상 종료 상황
TCP에서는 연결 할 때보다 연결을 종료 할 때 더 예기치 못한 상황들이 일어나게 되는데 다양한 상황에 따른 연결의 종료를 적절하게 처리하지 못하면, FIN_WAIT_1, FIN_WAIT_2, CLOSE_WAIT 상태로 남아 계속 기다리는 상황이 올 수 있다.
- CLOSE_WAIT 상태 : 어플리케이션에서 close()를 적절하게 처리해주지 못하면, TCP 포트는 CLOSE_WAIT 상태로 계속 기다리게 된다. 이렇게 CLOSE_WAIT 상태가 statement에 많아지게 되면, Hang 이 걸려 더이상 연결을 하지 못하는 경우가 생기기도 한다. 따라서 어플리케이션 개발시 여러 상황에 따라 close() 처리를 잘 해줘야 한다.
- FIN_WAIT_1 상태 : FIN_WAIT_1 상태라는 것은 상대방측에 커넥션 종료 요청을 했는데, ACK를 받지 못한 상태로 기다리고 있는 것이다. 이것은 아마 서버를 찾을 수 없는 것으로, 네트워크 및 방화벽의 문제일 수 있다.
(FIN_WAIT_1 의 상태는 일정 시간이 지나 Time Out이 되면 자동으로 Closed한다.)
- FIN_WAIT_2 상태 : FIN_WAIT_2 상태는 클라이언트가 서버에 종료를 요청한 후 서버에서 요청을 접수했다고 ACK를 받았지만, 서버에서 종료를 완료했다는 FIN 을 받지 못하고 기다리고 있는 상태이다. 이상태는 양방의 두번의 통신이 이루어졌기 때문에 네트워크의 문제는 아닌 것으로 판단되며,(FIN 을 보내는 순간에 순단이 있어 못받은 것일 수도 있다.) 서버측에서 CLOSE를 처리하지 못하는 경우일 수도 있다. FIN_WAIT_2 역시 일정시간 후 Time Out이 되면 스스로 Closed 하게 된다.
- 어떠한 이유에서 FIN_WAIT_1과 FIN_WAIT_2 상태인 연결이 많이 남아있다면, 문제가 발생할 수 있다. 물론 일정 시간이 지나 Time Out이 되면 연결이 자동으로 종료되긴 하지만, 이 Time Out이 길어서 많은 수의 소켓이 늘어만 난다면, 메모리 부족으로 더 이상 소켓을 오픈하지 못하는 경우가 발생한다.
(이 경우는 네트워크나 방화벽 또는 어플리케이션에서 close() 처리 등에 대한 문제등으로 발생할 수 있으며, 원인을 찾기가 쉽지 않다.)
3-way handshake : 생각해볼 내용들
###
2-way가 아니라 3-way가 되어야만 하는 이유
3-way handshake의 과정을 다시 생각해보면:
클라이언트는 자신의 요청이 서버에게 도달 되었는지 물어본다.(클라이언트의 SYN 패킷 전달)
서버는 클라이언트의 요청을 받을 수 있다고 전달해준다.(ACK 패킷 (클라이언트 의 SYN요청 + 1))
그리고 다시 서버는 자신의 요청이 클라이언트에게 전달되는지 다시 물어본다.(서버의 SYN 패킷 전달)
서버의 요청을 받은 클라이언트는 다시 위과정을 반복해 3-way shake를 마치게 된다.
TCP 연결은 양방향성(bidirectional) connection이다. 클라이언트에서 서버에게 존재를 알리고 패킷을 보낼 수 있다는 것을 알리는 것처럼 서버에서도 클라이언트에게 존재를 알리고 패킷을 보낼 수 있다는 신호를 보내야 한다. 그렇기 때문에 2-way shake로만으로는 부족하다.
SYN, ACK 두가지 타입의 패킷을 사용하는 이유
→ 요청과 응답에 대한 패킷을 각각 구별하기 위해 두 종류이다.
만일 SYN, ACK이 아니라 EXA라는 하나의 패킷만 존재한다고 하자.
그렇게 된다면 위에서 설명한 과정을 논리적으로 구별할 수 없을 것이다. 풀어 설명하자면, 클라이언트가 자신의 요청이 서버에게 전달되었는지 묻는 요청과 서버에게 서버의 요청이 자신에게 전달되었다는 응답을 구분지을 수 없다.
Sequence Number는 왜 난수여만 하는가.
3-way shake에서 클라이언트가 최초로 SYN 패킷을 보낼 때, Sequence Number에는 랜덤한 숫자가 담긴다. 초기 sequence number를 ISN이라고 한다. ISN은 0부터 시작하지 않고 난수를 생성하여 초기값을 설정한다. 초기값이 난수인 이유가 무엇일까?
Connection을 맺을 때 사용하는 포트는 일회용이 아니다. 한 연결을 위해 일정기간 사용되고 나서, 일정 시간이 흐른 후 다른 연결을 위하여 재사용된다. 따라서 두 통신 호스트가 과거에 사용된 포트 번호 쌍을 다시 사용하게 될 가능성은 존재한다. 서버측에서는 패킷의 SYN을 보고 패킷을 구분하게 되는데, 난수가 아니라 순차적인 SYN 번호가 전송된다면 이전의 connection으로부터 오는 패킷으로 인식할 수도 있다.
이러한 문제가 발생할 가능성을 줄이기 위해서 난수로 ISN을 설정한다.(ISN은 각 운영체제마다 다른 방식으로 부여된다고 한다.)
댓글남기기