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:23

Process-to-Process Communication

Some well-known port numbers used by TCP

 

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

Sequence Number Example

  • 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의 보수 수행

Checksum data

  • 마찬가지로 NIC이 연산해줌

Encapsulation

  • TCP는 App layer로부터 데이터를 받아서 세그먼트로 구성함
  • 다음과 같이 계층적으로 encapsuled
    1. Application data
    2. TCP segment (header + data)
    3. IP datagram (header + segment)
    4. Frame (header + datagram)

Encapsulation 과정

 

Connection Establishment(연결 수립)

Virtual Connection

  • TCP는 물리적인 연결이 아니라 가상(논리적) 연결을 형성
  • 즉, 두 장치 간의 연결은 실제 선으로 이어진 게 아니라 논리적으로 서로 세그먼트를 주고받을 수 있는 상태가 된 것임

 Full-duplex(전이중 통신)

  • TCP 연결은 양방향으로 동시에 통신 가능함
  • 클라이언트와 서버가 동시에 데이터 전송 가능
  • 양쪽 모두 연결을 초기화하고 승인해야 데이터 전송 가능
    • 한쪽만 일방적으로 보내면 안 됨

Three-Way Handshaking

  • 연결을 설정할 때 사용하는 과정
    • 클라이언트가 연결을 시작하려 함 (active open)
    • 서버는 연결 요청을 받을 준비를 함 (passive open) 
    • 이 후 3-way 악수 시작
  1. 클라이언트 → 서버 (SYN)
    • 클라이언트는 ISN을 생성해 SYN flag가 설정된 Segment를 서버에 보냄
    • 이때 데이터는 포함되지 않지만 시퀀스 번호는 1을 소비함(다음 전송 번호는 +1)
  2. 서버 → 클라이언트 (SYN + ACK)
    • 서버는 받은 클라이언트의 ISN을 ACK함
    • 자신의 ISN을 포함하여 다시 SYN 요청을 보냄 (SYN + ACK segment)
    • 이 세그먼트에는 rwnd(수신 윈도우 크기) 정보도 포함되어 클라이언트가 데이터를 얼마나 보낼 수 있는지 지정함
  3. 클라이언트 → 서버 (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로 위조하여 다수의 클라이언트인 것처럼 위장함

공격 절차

  1. 공격자가 서버에 SYN 세그먼트를 반복 전송
  2. 각 SYN에 대해 서버는 자원을 할당하고, SYN+ACK을 응답
  3. 하지만 공격자는 ACK을 보내지 않음 → 3-way handshake가 완료되지 않음
  4. 서버는 해당 연결을 일정 시간 유지하려고 자원을 점유
  5. 이 과정을 반복하면 서버는 가짜 연결 요청들 때문에 진짜 사용자를 위한 자원을 못 쓰게 됨

Countermeasures(방어 방법)

  • 연결 요청 제한: 일정 시간 내 허용 가능한 연길 시도 수를 제한
  • SYN Cookie 기법
    • 서버가 클라이언트의 응답(ACK)을 받기 전까지 자원을 할당하지 않음
    • 대신 암호화된 ISN(cookie)을 발급하고, 이후 ACK에서 이를 검증함
  • 그냥 Firewall(router+보안SW) 켜기

 

Data Transfer in TCP

  • TCP 연결이 설정된 이후, 클라이언트와 서버는 서로 동시에 데이터와 ACK 전송 가능

 

  1. 클라이언트가 2,000바이트를 두 개의 세그먼트로 전송
  2. 서버는 2,000바이트를 한 세그먼트로 전송
  3. 이 때, 앞선 세그먼트들(총 3개)은 데이터 + ACK를 함께 담고 있음
  4. 클라이언트가 보낸 세그먼트에는 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단계로 나눔

종료 절차

  1. 클라이언트가 세그먼트에 FIN + ACK flag를 설정하여 더 이상 보낼 데이터가 없음을 알림
    • FIN만 단독으로 보낼 수 있지만 거의 항상 ACK와 같이 보냄
    • 마지막 데이터도 함께 실을 수 있음
    • 그러려면 시퀀스 번호 1 소비 (안 실으면 시퀀스 번호 소비 X)
  2. 서버는 FIN 수신을 확인하면서, 동시에 서버도 연결 종료 의사(FIN)를 전달함
    • FIN + ACK flag 설정
  3. 클라이언트는 서버의 FIN을 받고 마지막 ACK 전송
    • 양방향 모두 종료 완료

seq, ack number 잘 확인

 

Half-Close

  • 연결의 한 쪽 방향(보내기)만 종료하고, 다른 방향(받기)은 계속 열어두는 상태
  • 즉, 한쪽이 더 이상 데이터를 보내지는 않지만, 상대방의 데이터를 받는 건 계속 유지하는 상태
  • 클라이언트나 서버 중 한 쪽이 FIN 세그먼트를 보냈을 때, 상대방이 FIN을 보내지 않으면, 그쪽의 데이터는 계속 수신 가능
  • ex) 클라이언트가 업로드를 완료하고 더 이상 보낼 건 없지만 서버는 처리 결과를 아직 보내야 할 

seq, ack 뭐지