일을 하다보면 netstat 명령어를 자주 사용하게 된다. 현재 LISTEN 중인 포트를 확인하려는 용도가 거의 대부분인데 상태를 보면 ESTABLISHED, CLOSE_WAIT, TIME_WAIT, FIN_WAIT_2 이런 것들이 보인다. 막연하게만 봤던 상태들인데 정리해보자. 네트워크 지식이 빈약해서 다른 글들을 그대로 카피하여 정리했다.
MS .NET에 TcpState 정의가 있어서 가져왔다. 어디서 별도로 정리한걸 보는것보다 더 나을 것 같다.
CLOSED | 1 | TCP 연결이 닫혀 있습니다. |
CLOSE_WAIT | 8 | TCP 연결의 로컬 엔드포인트에서 로컬 사용자로부터의 연결 종료 요청을 기다리고 있습니다. Passive Close 하는 쪽에서 프로그램이 소켓을 종료시키는 것을 기다리기 위한 상태. 가령, 소켓 프로그래밍 시 TCP connection 을 close 함수로 명시적으로 끊어주지 않으면 CLOSE_WAIT 상태로 영원히 남을 수 있고 이는 resource leak 으로 이어짐 |
CLOSING | 9 | TCP 연결의 로컬 엔드포인트에서 이전에 보낸 연결 종료 요청의 승인을 기다리고 있습니다. |
ESTABLISHED | 5 | TCP 핸드셰이크가 완료되었습니다. 연결이 설정되었으므로 데이터를 보낼 수 있습니다. |
FIN_WAIT1 | 6 | TCP 연결의 로컬 엔드포인트에서 원격 엔드포인트로부터의 연결 종료 요청 또는 이전에 보낸 연결 종료 요청의 승인을 기다리고 있습니다. |
FIN_WAIT2 | 7 | TCP 연결의 로컬 엔드포인트에서 원격 엔드포인트로부터의 연결 종료 요청을 기다리고 있습니다. |
LAST_ACK | 10 | TCP 연결의 로컬 엔드포인트에서 이전에 보낸 연결 종료 요청의 최종 승인을 기다리고 있습니다. |
LISTEN | 2 | TCP 연결의 로컬 엔드포인트에서 원격 엔드포인트로부터의 연결 요청을 수신하고 있습니다. |
SYN_RECEIVED | 4 | TCP 연결의 로컬 엔드포인트에서 연결 요청을 보내고 받았으며 승인을 기다리고 있습니다. |
SYN_SENT | 3 | TCP 연결의 로컬 엔드포인트에서 원격 엔드포인트에 동기화(SYN) 제어 비트 집합과 함께 세그먼트 헤더를 보냈으며 일치하는 연결 요청을 기다리고 있습니다. |
TIME_WAIT | 11 | TCP 연결의 로컬 엔드포인트에서 원격 엔드포인트가 연결 종료 요청의 승인을 받았는지 확인하는 데 충분한 시간이 경과하기를 기다리고 있습니다. |
Unknown | 0 | TCP 연결 상태를 알 수 없습니다. |
- CLOSED : 연결이 없습니다.
- LISTEN : 로컬 끝점이 원격 끝점의 연결 요청을 기다리고 있습니다. 즉, 수동 열기가 수행되었습니다.
- SYN-SENT: 3방향 연결 핸드셰이크의 첫 번째 단계가 수행되었습니다. 연결 요청이 원격 끝점으로 전송되었습니다. 즉, 활성 열기가 수행되었습니다.
- SYN-RECEIVED: 3방향 연결 핸드셰이크의 두 번째 단계가 수행되었습니다. 수신된 연결 요청과 연결 요청에 대한 승인이 원격 끝점으로 전송되었습니다.
- ESTABLISHED: 3방향 연결 핸드셰이크의 세 번째 단계가 수행되었습니다. 연결이 열려 있습니다.
- FIN-WAIT-1: 활성 닫기(4방향 핸드셰이크)의 첫 번째 단계가 수행되었습니다. 로컬 끝점이 원격 끝점에 연결 종료 요청을 보냈습니다.
- CLOSE-WAIT: 로컬 끝점이 연결 종료 요청을 수신하고 이를 승인했습니다. 예를 들어 수동 닫기가 수행되었고 로컬 끝점이 이 상태를 떠나기 위해 활성 닫기를 수행해야 합니다.
- FIN-WAIT-2: 원격 끝점이 이전에 보낸 연결 종료 요청에 대한 승인을 보냈습니다. 로컬 끝점은 원격 끝점에서 활성 연결 종료 요청을 기다립니다.
- LAST-ACK: 로컬 끝점이 수동 닫기를 수행하고 원격 끝점에 연결 종료 요청을 보내 능동 닫기를 시작했습니다.
- CLOSING: 로컬 끝점이 TIME-WAIT 상태로 전환되기 전에 연결 종료 요청에 대한 승인을 기다리고 있습니다.
- TIME-WAIT: 로컬 끝점은 원격 끝점이 승인을 수신했는지 확인하기 위해 CLOSED로 이동하기 전에 최대 세그먼트 수명(MSL)의 두 배를 기다립니다.
두번째 아래 TCP 상태 변화 다이어그램을 이해하면 될 것 같다.
TCP STATE TRANSITION DIAGRAM
CLOSE_WAIT 로 인한 서버 행업 현상
개요만 이해한대로 정리해보자면
1. 서버와 클라이언트가 연결이 수립된 상태(ESTABLISHED)를 가정한다.
2. Active Close 쪽에서 Fin_Wait_1 상태로 변경 후 종료 신호인 Fin을 Passive Close 측으로 보낸다. 보낸 후에 Fin_Wait_2로 변경. 대기한다.
3. 받는 쪽이 Passive Close가 되고 Fin신호를 받고 Ack(ACKnowledgement : 승인 : 응답)을 보낼수 없는 행 상태로 보류되면 CLOSE_WAIT가 걸리게 된다.
Passive Close에서 행을 걸게 만들수 있는 자바 코드는 Thread.sleep으로 처리했다.
// should now be in CLOSE_WAIT
Thread.sleep(Integer.MAX_VALUE);
Active Close 측의 Fin_Wait_2는 CentOS의 경우 60초이며 아래처럼 타임아웃 설정을 바꿀 수 있고
# vi /etc/sysctl.conf
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 10
해당 시간이 지나게 되면 TIME_WAIT 상태로 변경되며 2*MSL(Maximum Segment Lifetime) 로 60초로 고정, 변경 불가하다. 이 얘기는 Active Close 측 상태는 120초 정도면 해당 상태가 종료되서 별 문제가 생기지 않는다.
하지만 Passive Close가 CLOSE_WAIT가 다수로 걸리게 되면 해당 쓰레드의 행업을 의심하여 조치하는 것이 필수적으로 필요하다.
TIME_WAIT는 엄청난 부하로 인하여 왠만큼 발생하더라도 문제가 생기지 않는다. ( 수만건도.. ) FIN_WAIT2와 TIME_WAIT는 같다. FIN_WAIT_1은 상대방 OS 응답 문제, FIN_WAIT_2는 상대 어플리케이션 응답 문제
- 소켓의 최대 갯수는 65,535개가 아니다. 소켓은 <protocol>, <src addr>, <src port>, <dest addr>, <dest port> 5개의 값으로 유니크하게 구성되며, 서버 포트 또는 클라이언트의 IP가 추가될 경우 그 만큼의 새로운 쌍을 생성할 수 있다.
이 엄청난 글을 꽤 읽었지만 한번에 이해하거나 학습이 되지 않을 것 같아. 여러번 보면서 본문을 고쳐야 된다고 생각한다. TCP/IP Illustrated 책도 봐야 한다.
참고
https://ktdsoss.tistory.com/282
https://tech.kakao.com/2016/04/21/closewait-timewait/
https://docs.oracle.com/cd/E37933_01/html/E36459/ipconfig-142.html
https://benohead.com/blog/2013/07/21/tcp-about-fin_wait_2-time_wait-and-close_wait/
'dev' 카테고리의 다른 글
Base64 이해와 Base62 비교 (0) | 2022.12.20 |
---|---|
ChatGPT 으로 작성해본 ChatGPT 장점, 단점, 후기 (1) | 2022.12.19 |
letsencrypt ssl 인증서 : There were too many requests of a given type :: too many failed authorizations recently (0) | 2022.06.12 |
Log4J(Log4Shell) 역대급 보안 취약점 정리(22.01.24 업데이트) (0) | 2022.01.24 |
OWASP top 10대 웹 보안 취약점 (0) | 2021.08.17 |
ftp, ftps, sftp(ssh) 개념 정리 (0) | 2021.07.26 |
GitHub Copilot - AI 페어 프로그래머, 코딩을 자동으로? (2) | 2021.07.18 |
깃허브 액션(github action) 에서 젠킨스로 갈아탄 이유 (1) | 2021.04.26 |