본문 바로가기

3-5. Networks

]무조건 긁어오기] TCP 연결 상태

TCP 연결 단계 (RFC 793)
       TCP A                                                                                              TCP B
1.  CLOSED                                                                                            LISTEN
2.  SYN-SENT    --> < SEQ=100>< CTL=SYN>                                   -->  SYN-RECEIVED
3.  ESTABLISHED <-- < SEQ=300>< ACK=101>< CTL=SYN,ACK>       <--    SYN-RECEIVED
4.  ESTABLISHED --> < SEQ=101>< ACK=301>< CTL=ACK>                -->  ESTABLISHED
5.  ESTABLISHED --> < SEQ=101>< ACK=301>< CTL=ACK>< DATA>   -->  ESTABLISHED

LISTEN       : 데몬이 요청을 발을 수 있도록 연결 요구를 기다리는 상태.
                   즉, http(80), mail(25), ftp(21), telnet(23) 등의 포트가 열려있음을 의미.
                   윈도우즈에서는 LISTENING으로 표시.
SYN_SENT : 로컬에서 원격으로 연결 요청(SYN 신호를 보냄)을 시도한 상태.
SYN_RECV : 원격으로 부터 연결 요청을 받은 상태.
                   요청을 받아 SYN+ACK 신호로 응답은 한 상태이지만 ACK는 받지 못했다.
                   netstat로 확인할 때 SYN_RECV가 아주 많다면 TCP SYN 플러딩(Flooding) 공격일 가능성이 있다.
                   윈도우즈와 솔라리스에서는 SYN_RECEIVED으로, FreeBSD는 SYN_RCVD으로 표시.
ESTABLISHED : 서로 연결이 되어 있는 상태
                   위에서 192.168.123.10의 포트 32794과 218.xxx.xx.xx의 포트 22(ssh)이 서로 연결되어 있는 상태.





TCP 종료 단계
* 정상적인 연결 종료 과정
      TCP A                                                                                     TCP B
1.  ESTABLISHED                                                                           ESTABLISHED
2.  (Close)
     FIN-WAIT-1       --> <SEQ=100><ACK=300><CTL=FIN,ACK>  -->  CLOSE-WAIT
3.  FIN-WAIT-2      <--  <SEQ=300><ACK=101><CTL=ACK>       <--   CLOSE-WAIT
4.                                                                                                 (Close)
    TIME-WAIT      <--  <SEQ=300><ACK=101><CTL=FIN,ACK>  <--    LAST-ACK
5.  IME-WAIT         --> <SEQ=101><ACK=301><CTL=ACK>         -->  CLOSED
6.  (2 MSL)
     CLOSED                                                    

FIN_WAIT1     : 소켓이 닫히고 연결이 종료되고 있는 상태. 원격의 응답은 받을 수 있다.
                      솔라리스에서는 FIN_WAIT_1로 표시.
FIN_WAIT2     : 로컬이 원격으로 부터 연결 종료 요구를 기다리는 상태.
                      솔라리스에서는 FIN_WAIT_2로 표시.
CLOSE_WAIT : 원격의 연결 요청을 받고 연결이 종료되기를 기다리는 상태 .
                      원격으로 부터 FIN+ACK 신호를 받고 ACK 신호를 원격에 보냈다.
TIME_WAIT    : 연결은 종료되었으나 원격의 수신 보장을 위해 기다리고 있는 상태.
                      이 상태를 특히 자주 보게되는 경우 => Apache에서 KeepAlive를 OFF로 해둔 경우, Tomcat 서버를 쓰는 경우 등.
LAST_ACK    : 연결은 종료되었고 승인을 기다리는 상태.
CLOSED       : 완전히 연결이 종료된 상태.

※ 위의 FIN_WAIT1, FIN_WAIT2, CLOSE_WAIT 3개 상태는
    연결 종료를 위해 서로간에 신호를 주고받는 과정에 나타나는 상태로 이해하면 된다.
    종료 요청을 한 곳에서는 FIN_WAIT1, FIN_WAIT2, TIME_WAIT 상태가,
    종료 요청을 받는 곳에서는 CLOSE_WAIT, LAST_ACK 상태가 표시된다.





TIME_WAIT 상태 없애기
이미 발생한 TIME_WAIT 상태는 일정시간이 지나면 없어지지만,
client가 server에 매우 빈번히 connect/disconnect를 반복한다면
많은 TCP port가 TIME_WAIT 상태가 되서 문제가 생길 수 있음.

client application에서 socket option 중 linger option을 off 시키면,
client에 의한 connection close시 TIME_WAIT 상태를 거치지 않고
ClOSED 상태로 바뀌게 되므로, TIME_WAIT 상태가 발생하지 않게 됨.

/* 중략 */
int sock
struct linger   ling;

ling.l_onoff = 1;
ling.l_linger = 0;      /* 0 for abortive disconnect */

setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling))






TCP 상태별 정의
ESTABLISHED
   3단계 핸드쉐이킹 후 연결 성립

SYN_SENT
   원격 호스트에 능동적인 개설 요청(능동적 열기)

SYN_RECV
   네트워크 통한 연결요청 받음(수동적 열기)

FIN_WAIT1
   능동적 닫기(active close) 요청을 한 상태

FIN_WAIT2
   로컬에서 종결(FIN)세그먼트를 전송하였고 원격 시스템에서 이에 대한 확인메시지를 수신하였지만,
   원격 애플리케이션이 작업을 종료하지 않아 원격 호스트의 종결 세그먼트를 기다리는 상태

TIME_WAIT
   회선의 종결 절차가 완료되었지만 분실되었을지 모르는 느린 세그먼트를 위해
   소켓을 열어 놓고 유지하고 있는 상태

CLOSED
   회선이 종결되고 모든 자원을 해제한 상태

CLOSE_WAIT
   수동적 닫기를 하고 있는 상태로 FIN 종결 세그먼트를 수신하고 이에 대한 확인 메시지를 전송한 상태

LAST_ACK
   FIN 종결 요청을 받고 로컬에서도 회선 종결에 합의하여 종결을 요청(FIN)한 상태로
   이에 대한 확인 메시지가 수신되면 회선이 종결됨

LISTEN
   서버 애플리케이션에서 수동적 열기로 연결 요청을 기다리고 있는 상태

CLOSING
   로컬 TCP는 FIN_WAIT_1에서 설명한대로 FIN 종결 세그먼트를 전송하였고,
   LAST_ACK에서 설명한대로 원격 시스템의 종결 세그먼트도 수신하였지만,
   FIN_WAIT_1 단계에서 전송한 세그먼트에 대한 확인 메시지(ACK)를 수신하지 못한 상태로
   보통 확인 메시지가 전송 도중 분실되었다는 것을 나타냄

UNKOWN
   소켓의 상태에 대해서 확인이 안되는 경우