일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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
- 자바스크립트
- trie
- 이분 탐색
- Prisma
- 그래프 탐색
- Next
- string
- map
- router
- JavaScript
- branch
- MySQL
- 백준 9527번
- 트라이
- ERD
- MongoDB
- localstorage
- DP
- PROJECT
- insomnia
- 게임 서버 아키텍처
- HTTP
- 그리디
- pm2
- Github
- vector insert
- Express.js
- Keys
- html5
- ccw 알고리즘
Archives
- Today
- Total
dh_0e
[Transport Layer] TCP (Transmission Control Protocol) Part I. 본문
Network Programming/Transport Layer
[Transport Layer] TCP (Transmission Control Protocol) Part I.
dh_0e 2025. 6. 3. 04:23Process-to-Process Communication
Stream Delivery Service
- 메시지 단위가 아닌 byte 흐름 단위로 데이터를 전송
- 나눠서 혹은 합쳐서 받을 수 있음
- Segment: TCP의 data unit으로, Application에서 받은 바이트 스트림을 TCP가 적절히 나눠서 만든 패킷
Numbering System (번호 체계)
- TCP는 두 가지 번호 필드를 사용함
- Sequence Number
- Acknowledgment Number
- 이 번호들은 세그먼트 번호가 아니라 바이트 번호를 기준으로 함
- Byte Number
- TCP는 보통 0부터 시작하지 않음
- 임의의 시작 번호(ISN)를 선택함 (0 ~ $2^{32}-1$ 사이에서 임의로 고름)
- ex) ISN(Initial Sequence Number)이 1057이고 총 6000바이트를 보낸다면
>> 바이트 번호는 1057 ~ 7056이 됨
- Sequence Number
- 각 세그먼트는 첫 번째 바이트의 번호를 시퀀스 번호로 가짐
- ex) 바이트 1057 ~ 2056을 담은 세그먼트는 시퀀스 번호 1057
- Acknowledgment Number
- 수신자가 어떤 바이트까지 잘 받았는지를 송신자에게 알려주는 번호
- 사실상 다음에 받고 싶은 바이트의 번호를 의미함
- GBN 프로토콜과 마찬가지로 cumulative(누적) ACK임
- 즉 중간에 일부만 받고 일부는 못 받았다면 그 다음 번호를 보내지 않음
- ex) 1057 ~ 2056까지 잘 받았다면 Ack = 2057
Segment Format
- TCP에서의 패킷 단위
- TCP 세그먼트는 헤더 + 데이터로 이루어짐
- Header(20~60bytes): option이 포함되면 최대 60바이트까지 확장 가능
- Data: App 프로그램에서 내려보낸 바이트 스트림
Source port address(16bits)
- 세그먼트를 보내는 쪽의 Application port 번호
- ex) Web 브라우저가 사용할 때는 클라이언트 쪽 임시 포트
Destination port address(16bits)
- 세그먼트를 받는 쪽의 Application port 번호
- ex) 웹 서버의 포트 80
Sequence Number(32bits)
- 세그먼트가 보내는 데이터 중 첫 번째 바이트의 번호
- 시작할 때 양쪽에서 ISN을 생성하여 설정
- 클라이언트와 서버 각각 다른 ISN 사용
- 보안 및 충돌 방지를 위함
Acknowledgment Number(32bits)
- 상대방에게 다음에 받고 싶은 바이트 번호(마지막에 받은 바이트 번호+1)를 알려줌
- 세그먼트를 수신한 쪽이 성공적으로 받은 바이트까지를 기준으로 보냄
- ex) 500까지 잘 받았으니 501번 줘라
- 데이터와 Ack를 함께 보내는 경우 piggybacking이라 부름
Header Length(4bits)
- TCP 헤더의 길이를 4바이트 단위로 나타냄
- ex) 값이 5이면 5x4=20바이트라는 뜻
- 최소 5(20bytes) ~ 최대 15(60bytes)
Control field(6bits)
- 6개의 control flag가 있음
- TCP의 제어 동작을 나타내며 여러 비트를 동시에 켤 수 있음
플래그 | 의미 |
URG | 긴급 데이터 여부 표시 |
ACK | 확인 응답 번호가 유효함을 표시 |
PSH | 데이터를 즉시 상위 계층에 전달 요청(원래는 A-L에서 충분히 기다린 다음 전달) |
RST | 연결 재설정 (비정상 종료) |
SYN | 연결 시작 요청 (초기 핸드셰이크용) |
FIN | 연결 종료 요청 |
- 이 flag들을 통해 흐름 제어, 연결 설정/해제, 데이터 전송 방식 등을 제어함
Window Size(16bits)
- 송신 측 TCP의 window size를 바이트 단위로 정의
- 일반적으로 수신 측이 제어함 >> 수신 윈도우(rwnd)라 부름
- 16비트이므로 최대 크기가 65,535bytes까지 나타낼 수 있음
- 송신자는 수신자가 알려준 rwnd 값보다 더 많은 데이터 전송 불가
Urgent Pointer(16bits)
- URG 플래그가 설정되었을 때만 유효
- Pointer 값으로 세그먼트 내의 어느 위치까지가 긴급 데이터인지를 알려줌
>> sequence number + urgent pointer = 마지막 긴급 바이트 위치 - ex) 긴급 포인터가 10이면, sequence 번호부터 시작해서 10번째 바이트까지가 긴급 데이터
Checksum(16bits)
- TCP 오류 검출을 위한 mandatory(필수) 필드 (UDP는 선택이었음)
- TCP는 신뢰성 있는 전송을 보장하기 위해 오류 검출이 필수이기 때문
- 계산 방식은 UDP의 체크섬 계산 방식과 동일함
- 즉, 전송 전 세크먼트 전체(헤더 + 데이터) + pseudo-header를 합쳐서 1의 보수 수행
- 마찬가지로 NIC이 연산해줌
Encapsulation
- TCP는 App layer로부터 데이터를 받아서 세그먼트로 구성함
- 다음과 같이 계층적으로 encapsuled
- Application data
- TCP segment (header + data)
- IP datagram (header + segment)
- Frame (header + datagram)
Connection Establishment(연결 수립)
Virtual Connection
- TCP는 물리적인 연결이 아니라 가상(논리적) 연결을 형성함
- 즉, 두 장치 간의 연결은 실제 선으로 이어진 게 아니라 논리적으로 서로 세그먼트를 주고받을 수 있는 상태가 된 것임
Full-duplex(전이중 통신)
- TCP 연결은 양방향으로 동시에 통신 가능함
- 클라이언트와 서버가 동시에 데이터 전송 가능
- 양쪽 모두 연결을 초기화하고 승인해야 데이터 전송 가능
- 한쪽만 일방적으로 보내면 안 됨
Three-Way Handshaking
- 연결을 설정할 때 사용하는 과정
- 클라이언트가 연결을 시작하려 함 (active open)
- 서버는 연결 요청을 받을 준비를 함 (passive open)
- 이 후 3-way 악수 시작
- 클라이언트 → 서버 (SYN)
- 클라이언트는 ISN을 생성해 SYN flag가 설정된 Segment를 서버에 보냄
- 이때 데이터는 포함되지 않지만 시퀀스 번호는 1을 소비함(다음 전송 번호는 +1)
- 서버 → 클라이언트 (SYN + ACK)
- 서버는 받은 클라이언트의 ISN을 ACK함
- 자신의 ISN을 포함하여 다시 SYN 요청을 보냄 (SYN + ACK segment)
- 이 세그먼트에는 rwnd(수신 윈도우 크기) 정보도 포함되어 클라이언트가 데이터를 얼마나 보낼 수 있는지 지정함
- 클라이언트 → 서버 (ACK)
- 클라이언트는 서버의 ISN을 ACK하고 3번째 segment(ACK)를 보냄
- 이 ACK 세그먼트는 첫 번째 SYN의 시퀀스 번호 + 1로 보내며, ACK이므로 시퀀스 번호를 소비하지 않음
서버가 ACK 받으면 Socket 완성~ 근데 사실 SYN 받을 때부터 Socket은 만들어지는 중이었음ㅋㅋ
- ACK에서는 서로의 rwnd를 전달하므로 크기가 서로 다름
Simultaneous Open
- 일반적인 client-server 모델이 아닌, 양쪽 모두 동시에 연결을 시도하는 상황
- 개별 host들이 client, server 역할을 동시에
- 양쪽 모두 active open을 시도함
- 즉, 둘 다 동시에 SYN 세그먼트 전송 (global clock으로 상대 process랑 통신을 약속하고 하는 느낌)
- 두 TCP가 서로 SYN + ACK 세그먼트 교환
- 총 4번의 메시지 교환 발생 >> 4-way handshake 형태
- 결국은 하나의 TCP 연결이 설정되지만 TCP의 정상적인 사용은 아님
- ex) Peer-to-Peer(P2P) 구조: 토렌트
SYN Flooding Attack
- 공격자가 다수의 SYN 패킷을 보내서 서버의 자원을 고갈시키는 DoS(서비스 거부) 공격의 일종
- 공격자는 소스 IP 주소를 SW로 위조하여 다수의 클라이언트인 것처럼 위장함
공격 절차
- 공격자가 서버에 SYN 세그먼트를 반복 전송
- 각 SYN에 대해 서버는 자원을 할당하고, SYN+ACK을 응답함
- 하지만 공격자는 ACK을 보내지 않음 → 3-way handshake가 완료되지 않음
- 서버는 해당 연결을 일정 시간 유지하려고 자원을 점유함
- 이 과정을 반복하면 서버는 가짜 연결 요청들 때문에 진짜 사용자를 위한 자원을 못 쓰게 됨
Countermeasures(방어 방법)
- 연결 요청 제한: 일정 시간 내 허용 가능한 연길 시도 수를 제한
- SYN Cookie 기법
- 서버가 클라이언트의 응답(ACK)을 받기 전까지 자원을 할당하지 않음
- 대신 암호화된 ISN(cookie)을 발급하고, 이후 ACK에서 이를 검증함
- 그냥 Firewall(router+보안SW) 켜기
Data Transfer in TCP
- TCP 연결이 설정된 이후, 클라이언트와 서버는 서로 동시에 데이터와 ACK 전송 가능
- 클라이언트가 2,000바이트를 두 개의 세그먼트로 전송
- 서버는 2,000바이트를 한 세그먼트로 전송
- 이 때, 앞선 세그먼트들(총 3개)은 데이터 + ACK를 함께 담고 있음
- 클라이언트가 보낸 세그먼트에는 PSH(push) 플래그가 설정됨
→ 서버는 받은 즉시 애플리케이션에 데이터를 넘기도록 요청받은 것
→ 키 입력처럼 빠른 응답이 필요한 상황에서 유용
Pushing Data (PSH flag)
- TCP는 송신 application으로부터 받은 데이터를 버퍼에 저장하고 윈도우 크기나 전송 효율에 맞춰 적절히 세그먼트로 만들어 상위 계층으로 전달함 >> 효율적이지만 때로는 지연을 유발할 수 있음
- 키보드 입력, 채팅, 명령 전송, 게임 구현 등 즉시 반응이 필요한 경우 "입력 즉시 전송" 되기를 원함
- Application이 push 요청을 하면 송신 TCP는 버퍼가 꽉 차지 않아도 즉시 세그먼트 생성, PSH flag 설정해서 바로 전송
- 수신 TCP는 PSH flag 보고 데이터를 즉시 application에 전달
Connection Termination (FIN flag)
- TCP 연결을 종료할 때도 handshake가 필요함 (Four-way handshake)
- FIN + ACK로 termination도 3-way라고 할만한데?
- 각자 독립적으로 FIN을 보내야 하기 때문에, 논리적 동작을 기준으로 FIN, ACK, FIN, ACK 4단계로 나눔
- FIN + ACK로 termination도 3-way라고 할만한데?
종료 절차
- 클라이언트가 세그먼트에 FIN + ACK flag를 설정하여 더 이상 보낼 데이터가 없음을 알림
- FIN만 단독으로 보낼 수 있지만 거의 항상 ACK와 같이 보냄
- 마지막 데이터도 함께 실을 수 있음
- 그러려면 시퀀스 번호 1 소비 (안 실으면 시퀀스 번호 소비 X)
- 서버는 FIN 수신을 확인하면서, 동시에 서버도 연결 종료 의사(FIN)를 전달함
- FIN + ACK flag 설정
- 클라이언트는 서버의 FIN을 받고 마지막 ACK 전송
- 양방향 모두 종료 완료
Half-Close
- 연결의 한 쪽 방향(보내기)만 종료하고, 다른 방향(받기)은 계속 열어두는 상태
- 즉, 한쪽이 더 이상 데이터를 보내지는 않지만, 상대방의 데이터를 받는 건 계속 유지하는 상태
- 클라이언트나 서버 중 한 쪽이 FIN 세그먼트를 보냈을 때, 상대방이 FIN을 보내지 않으면, 그쪽의 데이터는 계속 수신 가능
- ex) 클라이언트가 업로드를 완료하고 더 이상 보낼 건 없지만 서버는 처리 결과를 아직 보내야 할
'Network Programming > Transport Layer' 카테고리의 다른 글
[Transport Layer] TCP (Transmission Control Protocol) Part III. (0) | 2025.06.04 |
---|---|
[Transport Layer] TCP (Transmission Control Protocol) Part II. (0) | 2025.06.03 |
[Transport Layer] UDP (User Datagram Protocol) (0) | 2025.06.03 |
[Transport Layer] Introduction (0) | 2025.06.02 |