본문 바로가기
리눅스

RFC 793 문서에 있는 TCP 기본 연결, 종료

by 혜룐 2015. 11. 10.

netstat의 State 필드에 표시되는 TCP 상태표시가 갖는 의미를 알아봅시다.
RFC 793 문서에 있는 TCP 기본 연결, 종료 과정을 보면 이해가 더 빠를 거라 생각한다.
------------------------------------------------------------------------------------------------------ 
# netstat -atn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
... 생략 ... 
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN<-- 포트가 열렸음
tcp 0 0 192.168.xx:32799 207.46.106.141:1863 ESTABLISHED<-- 서로 연결중
tcp 0 0 192.168.xx:32794 218.xxx.xx.xx:22 ESTABLISHED
tcp 0 0 192.168.xx:32802 207.46.108.46:1863 CLOSE_WAIT<-- 종료 대기중
... 생략 ...
----------------------------------------------------------------------------------------------------
1) TCP 연결관련 상태 
* RFC 793문서에 나온 기본적인 TCP 연결 과정
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) 등 위에서 포트 25(mail)이 메일을 받을 수 있도록 열려 있는 
상태. 윈도우즈에서는 LISTENING으로 표시
SYN_SENT : 로컬에서 원격으로 연결 요청(SYN 신호를 보냄)을 시도한 상태
SYN_RECV : 원격으로 부터 연결 요청을 받은 상태
요청을 받아 SYN+ACK 신호로 응답은 한 상태이지만 ACK는 받지 못했다.
netstat로 확인할 때 SYN_RECV가 상당히 많다면 TCP SYN 플러딩(Flooding) 공격일 가능성이 있다. 윈도우즈와 솔라리스에서는 SYN_RECEIVED으로, FreeBSD는 SYN_RCVD으로 표시
ESTABLISHED : 서로 연결이 되어 있는 상태
위에서 192.168.xx의 포트 32794과 218.xxx.xx.xx의 포트 22(ssh)이 서로 연결되어 있는 상태
----------------------------------------------------------------------------------------------------
2) 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. TIME-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 상태가 표시된다.
----------------------------------------------------------------------------------------------------
3) 기타 
CLOSING : 연결은 종료되었으나 전송도중 데이타가 분실된 상태
UNKNOWN : 소켓의 상태를 알 수 없음
솔라리스의 netstat 명령에서는 다음 2개의 상태를 더 표시한다.
IDLE : 소켓이 열렸지만 binding 되지 않은 상태
BOUND : listen이나 연결을 위한 준비 상태
----------------------------------------------------------------------------------------------------
4) state부분에 나타나는 연결상태
netstat명령의 결과에서 state부분에 나타나는 연결상태
상태 항목
설 명
LISTEN
서버의 데몬이 떠서 접속 요청을 기다리는 상태
SYS-SENT
로컬의 클라이언트 어플리케이션이 원격 호스트에 연결을 요청한 상태
SYN_RECEIVED
서버의 원격 클라이언트로부터 접속 요구를 받아 클라이언트에게 응답을 하였지만, 아직 클라이언트에게 확인 메시지는 받지 않는 상태
ESTABLISHED
3Way-Handshaking이 완료된 후 서로 연결된 상태
FIN-WAIT1, CLOSE-WAIT, FIN-WAIT2
서버에서 연결을 종료하기 위해 클라이언트에게 종결을 요청하고 회신을 받아 종료하는 과정의 상태
CLOSING
흔하지 않지만 주로 확인 메시지가 전송도중 분실된 상태
TIME-WAIT
연결은 종료되었지만 분실되었을지 모를 느린 세그먼트를 위해 당분간 소켓을 열어놓은 상태
CLOSED
완전히 종료된 상태
----------------------------------------------------------------------------------------------------
5) 옵션
옵 션
설 명
-a
연결된 모든 소켓을 출력
-n
기호화된 호스트나 포트이름, 유저이름 대신에 숫자로 표시한다. 예를 들면 www은 80으로 표기
-p
소켓에 대한 PID/프로그램을 출력
-r
라우팅 테이블을 출력
-i
인터페이스 테이블을 출력
-s
SNMP(Simple Network Managemanet Protocol)와 같은 네트워크 통계를 출력
-c
계속되는 리스트를 출력
-t
tcp를 이용하여 접속한 리스트를 출력
-u
udp를 이용하여 접속한 리스트를 출력
address family options
형식 : --protocol (inet, unix, ipx, ax25등)
예제) netstat --inet
----------------------------------------------------------------------------------------------------
6) 실시간으로 서버가 받는 트래픽(패킷) 양을 알 수 있다. 
* 현재 상황을 실시간(?) 으로 알 수 있다. 옵션 -i
root@lhrtest:/root># netstat -i
Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 11550147 0 0 0 332259 0 0 0 BMRU
lo 16436 0 19291 0 0 0 19291 0 0 0 LRU
root@lhrtest:/root># netstat -i
Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 11550173 0 0 0 332265 0 0 0 BMRU
lo 16436 0 19291 0 0 0 19291 0 0 0 LRU
root@lhrtest:/root># netstat -i 2 # 2초 마다 리플레시 해서 출력한다.
Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 11552211 0 0 0 332545 0 0 0 BMRU
lo 16436 0 19305 0 0 0 19305 0 0 0 LRU
eth0 1500 0 11552221 0 0 0 332548 0 0 0 BMRU
lo 16436 0 19305 0 0 0 19305 0 0 0 LRU
root@lhrtest:/root># cat /proc/net/dev # 위에 값은 이 부분에서 값을 가져 온다.
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 1766914 19305 0 0 0 0 0 0 1766914 19305 0 0 0 0 0 0
eth0:850278462 11552075 0 0 0 0 0 0 53889853 332518 0 0 0 0 0 0
eth1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0