Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Tags
- 알고리즘
- webhacking
- 웹
- CodeEngn
- reversing
- 리버싱
- 소프트웨어
- 웹해킹
- 비박스
- 모의해킹
- 시스템해킹
- Web
- WarGame
- 해킹
- dreamhack
- TCP
- XSS
- ftz
- bee-box
- 소프트웨어보안
- 네트워크
- 드림핵
- hacking
- Webhaking
- System
- 네트워크보안
- network
- 시스템
- 순서도
- 워게임
Archives
- Today
- Total
Without a Break
TCP Connection Establishment and Termination 본문
개요
- TCP는 연결형 프로토콜: 종단이 서로 데이터를 송신하기 전에 이들 사이에 연결을 확립
플래그 | 3문자 약어 | 설명 |
S | SYN | 순서번호의 동기화 |
F | FIN | 송신자는 데이터 송신을 종료 |
R | RST | 연결의 재설정 (강제 종료) |
P | PSH | 수신 프로세스가 가능한 빨리 데이터를 보낸다 |
. | 위의 4개의 플래그가 설정된 것이 없다 |
연결 확립과 종료
연결 확립 프로토콜
- [SYN] 요구 측의 종단은 접속하고자 하는 서버의 포트번호와 클라이언트의 초기순서번호(ISN)를 지정한 SYN 세그먼트를 보낸다.
- [SYN+ACK] 서버는 서버의 초기순서번호(ISN)를 포함한 자신의 SYN 세그먼트로 응답한다.
- [ACK] 클라이언트는 서버로부터 보내 온 SYN에 대하여 서버의 ISN+1 ACK로 확인응답을 보내야 한다.
=> 이와 같이 3개의 세그먼트에 의해 연결이 확립되어 이 연결 확립 과정은 three-way handshake라 부름
일반적인 연결 종료 프로토콜
- 능동 폐쇄(active close) 클라이언트가 close를 호출해 해당 연결로 더 이상 보낼 데이터가 없다고 선언하면, TCP는 close 호출 전에 클라이언트에게 처리 요청 받을 보낼 데이터를 모두 보낸 뒤 FIN 송신
- 수동 폐쇄(passive close) 서버 TCP는 앞의 데이터를 모두 받고 FIN을 수신하면 응용에 EOF를 전달하여 연결이 닫힘을 알리고, 클라이언트 TCP에 FIN의 수신을 알림 (FIN을 담은 세그먼트의 순서 번호+1에 대한 ACK)
- (active close) 서버는 read 함수에서 EOF가 리턴 된 걸 확인하면, 보통 해당 연결에 대한 close를 호출하도록 프로그램 되어 있다. 이 경우 FIN을 송신함
- (passive close) 클라이언트는 FIN을 수신하면, FIN을 담은 세그먼트의 순서번호에 1을 더한 ACK를 보낸다.
=> 위 종료 프로토콜에서 클라이언트와 서버가 바뀌어도 아무 문제가 없음 (다만, 요청-응답 응용에서 클라이언트가 먼저 닫는 경우가 많다)
연결 확립의 타임아웃
연결을 확립할 수 없는 예 : 서버 호스트의 다운
- [tos 0x10] : IP 데이터그램의 서비스 유형 필드. telnet, rlogin에서 대화용 로그인이익 때문에 클라이언트의 지연을 최소화하기 위함
- 클라이언트의 TCP가 연결을 설정하기 위해 SYN을 보냄 (첫번째 세그먼트 보낸 후 2번째 연결을 위한 시도 5.8초 후, 두번째 세그먼트를 보낸 후 3번째 연결을 위한 시도는 24초 후에 보냄)
최대 세그먼트 크기
- Maximum Segment Size(MSS): TCP가 상대편에 한번에 보낼 수 있는 데이터의 최대 크기
- 연결이 확립될 때 각 종단은 MSS를 통지 (TCP 옵션)
- MSS = MTU - IP헤더 - TCP헤더 ex) 이더넷 : 1460바이트
- Default MSS 설정 : 각 종단은 받기를 원하는 MSS를 알리는 옵션을 갖는다. => 시스템 별 default MSS가 다를 수 있음
절반 폐쇄
: TCP 연결의 한 쪽 종단이 다른 쪽 종단으로부터 데이터를 전송 받고 있는 상태에서도 데이터의 출력을 종료할 수 있는 기능
BSD Sockets API는 응용이 close를 대신 shutdown을 호출하여 절반 폐쇄함
- BSD Sockets API에서 close() 함수를 호출하는 것은 절반 폐쇄가 아님
- 절반 폐쇄가 있음에도 많은 응용은 연결 종료 시 close를 이용하여 양방향 폐쇄를 수행
서버가 EOF를 받았음에도 보낼 데이터가 남아있었고, 응용이 shutdown으로 절반 폐쇄 했기 때문에 계속 데이터를 수신하는 것이 가능함
- 만약 클라이언트가 close했는데 서버가 write하면 데이터 전달 실패됨
TCP 상태 천이도
TIME_WAIT (2MSL Wait) State (대기상태)
MSS : 세그먼트가 네트워크 상에 존재할 최대 시간
- RFC 793에서는 2분으로 명시했지만, 구현은 다른 값을 사용하기도 함
- IP 데이터그램이 TTL로 패킷의 수명을 제약하지만, 실제 시간이 아니라 hop 수 임에 주의
TCP가 능동적 폐쇄를 한 뒤 마지막 ACK를 보냈다면, 해당 연결은 2MSL동안 TIME_WAIT 상태임
- 이는 다시 말해 해당 연결을 2MSL동안 재사용할 수 없음을 의미
- 이유 : 마지막 ACK가 만야 ㄱ손시로디면, 재전송을 해야 하기 때문
- 다른 효과 : 해당 연결에 대응하는 소켓 페어의 재사용을 막기 위함 (네트워크에 남아있는 패킷이 이상행동을 일으킬 수 있으므로. 그런 패킷 도착 시 discard)
- 표준과 달리 BSD 및 BSD를 따라한 구현들을 연결뿐만 아니라 로컬 포트번호의 재사용을 막음 (TCP 표준은 같은 연결을 다시 못 맺을 뿐이지만, 구현들을 해당 포트 자체를 못 쓰게 함)
- SO_REUSEADDR 소켓 옵션을 가진 API에서는 해당 포트의 재사용을 허용할 수 있지만, 연결의 재사용은 원래 TCP 표준에서는 허용하지 않았음
- 서버의 경우 이 상태가 문제를 일으킴. 서버를 갑자기 종료시킨 뒤 재시작하면, 해당 포트를 최대 4분 동안 못 쓰는 상황이 발생
FIN_WAIT_2 상태
- FIN_WAIT_2 상태에서 서버가 FIN을 보내주지 않으면, 연결이 계속 같은 상태에 빠짐
- BSD에서 유래된 구현들은 응용 close 함수를 호출하여 능동적 폐쇄한 경우, 타이머를 설정해 타임아웃동안 연결이 휴지상태이면, 해당 연결을 CLOSED로 처리해버림
재설정(reset) 세그먼트
- 참조 연결에 대해서 바르지 않은 세그먼트가 도착할 때 발생 (*참조 연결 : 4-tuple이 명시된 연결)
연결 중단
- 정규 해제 : 상대편에 FIN 신호를 보내서 연결을 종료한 상황. FIN은 큐에 대기한 데이터를 모두 전송한 후에야 전송되므로, 데이터에 대한 손실이 없음
- 중단해제 : FIN 대신에 재설정을 전송하여 연결을 중단한 상황
연결 중단을 할 경우에 응용이 얻는 장점
- 대기 중인 데이터를 바로 버리고 즉시 재설정 신호(RST)를 전송해 연결을 재설정 가능
- RST의 수신측 TCP는 응용에 'RST 송신측이 연결을 중단했음'을 알릴 수 있음
- 따라서, API는 응용이 연결 중단을 할 수 있는 방법을 제공해야 함
- BSD는 SO_LINGER 옵션이 대표적인데, 여기서 linger는 중단 전에 기다릴 시간을 의미
절반 개방 연결
- 절반 개방 : 호스트 A가 호스트 B에게 세그먼트를 따로 보내지 않고 연결을 종료 또는 중단
- 절반만 개방된 상태이더라도, B가 데이터 전송을 시도하지 않으면 B는 고장을 알 수 없음 => 절반 개방된 연결로 B가 세그먼트를 보내는 경우, A의 TCP는 RST로 응답해야 함
TIME_WAIT Assassination (TWA)
- 아래와 같이 Client가 TIME_WAIT 상태에 있는데, Server가 오래전에 보낸 패킷이 늦게 도착하고 이를 응답하는 바람에 Server가 RST를 보내서 Client의 TIME_WAIT를 의도치 않게 꺼버리는 문제
- 대부분의 구현은 TIME_WAIT 상태 동안 도착한 RST 세그먼트를 무시함
동시 개방
- TCP의 상태 천이 다이어그램을 보면, 호스트 A와 호스트 B가 서로 간에 각각 SYN을 보내서 연결을 만들려고 할 수 있음
- 이 때 TCP표준은 두 개의 연결을 만드는 게 아니라 하나의 연결만이 이루어지도록 설계됨
- 보통 동시 개방은 이론상의 시나리오였으나, 각각 NAT를 거쳐야 글로벌 인터넷을 사용가능한 두 호스트가 상호 같에 outbound TCP 연결 (즉, peer-to-peer 연결)을 만들 필요가 있을 때 사용되며, 이를 TCP Hole Punching 이라고 부름
동시 폐쇄
- 양쪽 종단으로부터 능동적 폐쇄를 수행할 수 있음
- 동시 폐쇄는 일반적인 폐쇄와 같은 수의 세그먼트 교환
TCP
TCP 옵션
- TCP 헤더에 옵션을 추가
- RFC 793,1323은 추가적인 TCP 옵션을 정의
- 옵션의 유형은 kind의 값으로 구분
- NOP : 송신측이 필드를 4바이트의 배수가 되도록 채우기 위함
TCP 서버 설계
1. 병행성을 갖도록 설계
- 서버는 새로운 연결 요청이 도착하면 그 연결을 받아들이고 새로운 클라이언트를 처리하기 위해 새로운 프로세스 또는 스레드를 가동(folk()로 복제)
2. TCP 서버 포트 번호
netstat 옵션 | 동작 |
-a | 네트워크상의 모든 종단점을 표시 |
-n | DNS 서버를 사용하여 IP 주소를 dotted decimal로 출력하고 서비스 이름을 숫자로 포트번호를 출력 |
-f inet | TCP와 UDP 종단점만 표시 |
3. 외부 IP 주소의 제한
- TCP 서버가 자신에 대해 확립할 수 있는 제한 음식
- Iport는 서버의 알려진 포트, localIP는 로컬 인터페이스의 IP 주소
로컬 주소 | 외부 주소 | 설명 |
localIP.lport | foreignIP.fport | 하나의 클라이언트에 제한 |
localIP.lport | *.* | 하나의 로컬 인터페이스에 도착하는 연결에 제한 |
*.lport | *.* | lprot에 보네는 모든 연결을 수신 |
4. 수신 연결 큐
- 병행 서버는 각 클라이언트를 다루기 위해 새 프로세스를 만들 수 있지만, listen을 위한 서버는 accept 함수를 사용해 한 개의 연결 요청만을 처리할 수 있음
- 이러한 연결들은 (1)SYN은 받았지만 아직 연결 설립이 되지 않은 연결, 또는 (2) 핸드셰이킹이 끝났지만 listen을 위한 서버가 아직 accept하지 못한 연결 중 하나
- BSD Sockets API에서 응용이 연결 도착을 알 게 되었을 때에는 이미 TCP의 three-way 핸드 셰이킹이 끝나있는 상태임에 주의할 것
'Network > 네트워크보안과프로그래밍' 카테고리의 다른 글
Attacks on the TCP protocol (0) | 2022.11.21 |
---|---|
BSD Sockets API-based Network Programming (0) | 2022.11.06 |
TCP: Transmission Control Protocol (0) | 2022.09.30 |
UDP: User Datagram Protocol (0) | 2022.09.30 |
Address Resolution Protocol, ARP (0) | 2022.09.27 |