반응형
TCP CLOSE_WAIT & TIME_WAIT
- TCP 연결 종료 단계인 4-way handshake는 1차 FIN/ACK, ACK 교환 과정과 2차 FIN/ACK, ACK 교환 과정으로 나뉨
- 연결 종료를 먼저 원하는 측에서 1차 FIN/ACK을 상대방에게 전송하여 연결을 종료할 준비를 하고 연결 종료를 요청받은 쪽에서 2차 FIN/ACK을 상대에게 보내 연결을 종료할 준비를 함
- 세션을 정상적으로 종료하기에 앞서 받지 못한 패킷이 없도록 4-way handshake를 진행하는 Endpoint(이하 엔드포인트)는 교환 과정에서 별도의 상태에 돌입함
- 4-way handshake와 상태 변화를 순서대로 보면 다음과 같음(아래 그림의 빨간색 박스에 해당)

1. 클라이언트 혹은 서버(이하 Active Closer)가 연결을 끊기 위해 상대방에게 FIN/ACK(1차)을 전송함. 이를 능동적 연결 종료 요청이라고 하여 Active Close라 부름.
2. 이 때, Active Closer는 연결 상태를 'FIN_WAIT'로 변경함. 이는 연결을 사용 중인 Application(이하 애플리케이션)으로 하여금 연결 종료 명령, Close()를 명령하여 연결을 끊을 준비를 하는 것임.
3. 클라이언트 혹은 서버(이하 Passive Closer)가 FIN/ACK(1차)을 전달 받고 ACK를 상대방에게 전송하여 종료할 준비를 함. 이를 수동적 연결 종료 승낙이라 하여 Passive Close라 부름.
4. 이 때, Passive Closer는 연결 상태를 'CLOSE_WAIT'로 변경함. 이는 연결을 사용 중인 애플리케이션으로 하여금 연결 종료 명령, Close()를 명령하여 연결을 끊을 준비를 하는 것임.
5. Passive Closer는 FIN/ACK(2차)를 Active Closer에 전송하여 연결을 종료할 준비를 할 것을 요청함. 이때 애플리케이션의 Close() 명령 수행을 한 Passive Closer는 'LAST_ACK' 상태에 돌입하여 Active Closer가 ACK를 전송하기를 기다림.
6. FIN/ACK(2차)를 받은 Active Closer는 즉시 'TIME_WAIT'를 유지하며 Passive Closer에게 ACK를 전송하고 일정 시간을 기다렸다가 연결을 완전 종료함.
7. 'LAST_ACK' 상태에서 Passive Closer는 ACK를 전달받고 연결을 완전 종료함.
- 'TIME_WAIT'는 TCP 4-way handshake 이후 "연결 종료"를 요청한 쪽(Active Closer)에서 일시적으로 유지하는 상태
- 'TIME_WAIT'을 유지하는 시간은 MSL(Maximum Segment Lifetime)이라 부르며 1분 정도의 시간을 의미함. 보통의 'TIME_WAIT'는 2MSL, 2분임
- TIME_WAIT가 필요한 이유는 2가지임
- 첫 번째, 연결 종료 과정에서 미처 다 보내지 못한 패킷을 받기 위해 기다리기 위해 사용함
- 두 번째, 'LAST_ACK' 상태에서 ACK를 기다리는 Passive Closer가 모종의 이유로 ACK를 분실하여 받지 못 했다면 'TIME_WAIT' 상태의 Active Closer에게 다시 FIN/ACK(2차)를 전송하여 ACK를 받을 수 있도록 일정 시간을 유지하는 것임.
- 'TIME_WAIT'가 없다면 Passive Closer는 ACK만을 기다리며 LAST_ACK 상태를 끊임없이 유지하게 되고 Active Closer에게 끊임없이 FIN/ACK을 전달하며 ACK를 요구하게 되며 해당 연결을 종료하지 않음. 이는 클라이언트의 Local Port(이하 로컬 포트)를 계속 점거하며 해당 포트 번호로 새로운 세션을 열지 못하는 문제를 발생시킴.
TCP Port number reused
- 'Port nubmer reused'는 말그대로 포트를 재활용하는 것임
- 이미 사용하였던 5-tuple(source-ip, destionation-ip, protocol, source-port, destination-port)를 이용해 새로운 연결을 생성함
- 위에서 언급한 로컬 포트는 세션을 열기 위해 사용하는 출발지 혹은 목적지 포트를 의미함
- 보통 목적지 포트는 사용처가 정해져 있기에 번호 또한 Port 80, Port 443 등 정해져 있지만 출발지 포트는 사용할 수 있는 모든 포트를 사용하여 연결을 생성함
- 가용한 출발지 포트는 Window의 경우, 49152 ~ 65535를 사용하고 Linux의 경우, 31768 ~ 61000을 사용하며 출발지 IP는 이 포트들 중 하나를 선택하여 목적지에 도달하고 연결을 생성함
- 포트의 수량이 많아보이지만 이는 실제 사용을 보면 그리 많은 양이 아님
- 포트 수량이 부족해지는 가장 대표적인 경우는 바로 Source IP NAT로 다수의 출발지 IP가 한 가지 공인 혹은 사설 IP로 변환되어 외부 네트워크로 나가게 되는데 이때 출발지 포트를 통해 Original IP를 구별함
- 변환되는 Originial IP가 매우 많아지고 한 개의 IP가 다수의 연결을 생성할 때 출발지 포트가 부족해짐
- 이를 어느정도 해소하기 위해 포트 번호를 재사용하여 연결을 안정적으로 생성하도록 유도함
발생 가능한 문제 현상 & 해결
- 매우 많은 수의 사설 IP의 클라이언트가 1개 공인 혹은 사설 IP만을 사용하여 Source IP NAT를 실시하는 상태에서 서버에서 먼저 연결 종료 요청(Active Close)을 실시하고 'TIME_WAIT'에 들어간다면 문제가 발생할 수 있음
- 앞서 언급한 것처럼 Active Closer는 2차 FIN/ACK 교환 과정에서 'TIME_WAIT'에 돌입함
- 클라이언트가 'LAST_ACK' 상태에서 ACK를 받고 완전히 연결을 종료한 후에 짧은 시간 내에 기존 포트를 재활용(TCP Port number reused)하여 새로운 연결을 요청한다면?
- 서버는 기존 포트를 사용하는 연결의 'TIME_WAIT' 상태를 유지하므로 상태 유지 시간 동안 클라이언트의 모든 요청을 무시함
- Wireshark에서 이를 확인해보면 4-way handshake를 정상적으로 실시한 후, 클라이언트가 포트를 재활용해 새로운 연결 생성을 요청하지만 서버가 이를 모두 받아들이지 않고 클라이언트가 'TCP Retransmission'을 세 차례 전송하고 나서 'RST' 패킷을 전송하는 것을 볼 수 있음
- 단기적 해결 방법은 L4 스위치가 있다면 L4 스위치에서 클라이언트의 Source Port를 변환하여 서버가 다른 포트를 받게끔 하여 새로운 세션을 정상적으로 생성하도록 하는 방법이 있음. 다만 이는 DSR 구성에서는 사용할 수 없음
- 장기적 해결 방법은 출발지 포트 수량을 넉넉히 하는 것, 다시 말해 Source IP NAT에 사용할 IP를 다수 확보하여 포트가 재활용될 정도로 부족해지는 현상을 막는 것임
* 참고 자료
https://tech.kakao.com/2016/04/21/closewait-timewait/
https://docs.likejazz.com/time-wait/
https://ask.wireshark.org/question/26247/tcp-port-numbers-reused/
https://smjeon.dev/etc/tcp-state/
https://docs.likejazz.com/time-wait/
반응형
'Network Know-how 기록하기' 카테고리의 다른 글
[AWS]Gateway Load Balancer #1(개요) (8) | 2023.07.23 |
---|---|
[Secui Bluemax]방화벽 도메인 객체 활용 (0) | 2023.05.31 |
[Cisco]Catalyst 9K License(with EIGRP) (0) | 2022.12.11 |
[Cisco]BGP Null Routing 활용 (0) | 2022.05.05 |
[Cisco]TACACS+ (0) | 2022.03.05 |
댓글
네트워크 엔지니어 환영님의
글이 좋았다면 응원을 보내주세요!
이 글이 도움이 됐다면, 응원 댓글을 써보세요. 블로거에게 지급되는 응원금은 새로운 창작의 큰 힘이 됩니다.
응원 댓글은 만 14세 이상 카카오계정 이용자라면 누구나 편하게 작성, 결제할 수 있습니다.
글 본문, 댓글 목록 등을 통해 응원한 팬과 응원 댓글, 응원금을 강조해 보여줍니다.
응원금은 앱에서는 인앱결제, 웹에서는 카카오페이 및 신용카드로 결제할 수 있습니다.