40. TCP와 UDP 헤더 비교 — 신뢰성과 속도의 차이

changseop lee·5일 전

📚 네트워크 · 패킷 분석 › 01. TCP/IP 구조 이해 — 40편
이전 글: 39. UDP란 무엇인가 · 다음 글: 41. TCP 3-Way Handshake — 연결이 성립했다는 증거
참고(리눅스 시스템 기초): IP / TCP / UDP / Port — TCP·UDP의 기본 개념과 포트 개념

1. 왜 알아야 하는가

TCP는 "신뢰성 있는 연결형", UDP는 "빠른 비연결형"이라는 설명은 IP / TCP / UDP / Port 글에서 정리했습니다. 이번 글은 한 단계 더 들어가, 그 차이가 헤더의 어느 필드에서 나오는지를 비교합니다.

관제에서 헤더 구조를 알아야 하는 이유는 다음과 같습니다.

  • TCP의 Flags 필드는 연결 시작·종료·거부를 나타내며, 탐지 룰과 tcpdump 필터 대부분이 이 필드를 기준으로 작성됩니다.
  • UDP 헤더에는 연결 상태를 나타내는 필드가 없습니다. 그래서 출발지 위조가 쉽고, 증폭 공격에 악용되는 이유도 여기서 나옵니다.
  • IDS 룰이나 BPF 필터의 tcp[13], udp[4:2] 같은 표현은 헤더의 바이트 위치를 가리킵니다. 구조를 알아야 읽고 쓸 수 있습니다.

각 필드를 Wireshark에서 한 줄씩 해석하는 작업은 03. Wireshark 패킷 분석 시리즈(11. TCP 헤더와 Flag 분석)에서 다루고, 여기서는 구조 비교와 의미에 집중합니다.


2. 핵심 개념

2-1. 헤더 구조 한눈에 보기

TCP 헤더 (최소 20바이트, 옵션 포함 최대 60바이트)
 0                   1                   2                   3   (바이트)
+-------------------------------+-------------------------------+
|     Source Port (16bit)       |   Destination Port (16bit)    |  0~3
+-------------------------------+-------------------------------+
|                 Sequence Number (32bit)                       |  4~7
+---------------------------------------------------------------+
|              Acknowledgment Number (32bit)                    |  8~11
+-------+-------+---------------+-------------------------------+
| Data  | Rsrvd | Control Bits  |        Window (16bit)         |  12~15
|Offset |       | CWR ECE URG   |                               |
| (4bit)|(4bit) | ACK PSH RST   |                               |
|       |       | SYN FIN       |                               |
+-------+-------+---------------+-------------------------------+
|      Checksum (16bit)         |    Urgent Pointer (16bit)     |  16~19
+-------------------------------+-------------------------------+
|            Options (0~40바이트, 4바이트 단위로 맞춤)             |  20~
+---------------------------------------------------------------+

UDP 헤더 (고정 8바이트)
+-------------------------------+-------------------------------+
|     Source Port (16bit)       |   Destination Port (16bit)    |  0~3
+-------------------------------+-------------------------------+
|        Length (16bit)         |       Checksum (16bit)        |  4~7
+-------------------------------+-------------------------------+

2-2. 필드 비교

기능TCP 필드UDP 필드차이가 만드는 결과
프로세스 구분Source/Destination PortSource/Destination Port동일 (포트 개념은 같음)
순서 보장Sequence Number없음UDP는 순서가 뒤바뀌어도 모름
수신 확인Acknowledgment Number, ACK 플래그없음UDP는 유실을 스스로 알지 못함
연결 관리SYN, FIN, RST 플래그없음UDP는 "연결 수립" 단계가 없음
흐름 제어Window없음수신 측이 받을 수 있는 양을 TCP만 조절
헤더 길이Data Offset (가변)없음 (고정 8바이트)TCP는 옵션으로 기능 확장 가능
전체 길이없음 (IP 길이로 계산)LengthUDP는 헤더+데이터 길이를 직접 기록
오류 검출Checksum (필수)Checksum (IPv4에서는 0이면 미사용, IPv6에서는 필수)둘 다 가상 헤더(IP 주소 등) 포함 계산
긴급 데이터Urgent Pointer, URG 플래그없음현재는 거의 쓰이지 않음

2-3. TCP Control Bits(Flags)

TCP 헤더 13번째 바이트(0부터 세면 오프셋 13)에 8개의 플래그가 있습니다. RFC 9293 기준입니다.

비트 값플래그의미tcpdump 표기BPF 이름
0x01FIN보낼 데이터가 끝났음 (정상 종료)Ftcp-fin
0x02SYN연결 시작, 시퀀스 번호 동기화Stcp-syn
0x04RST연결 즉시 중단·거부Rtcp-rst
0x08PSH버퍼링하지 말고 애플리케이션에 바로 전달Ptcp-push
0x10ACKAcknowledgment Number가 유효함.tcp-ack
0x20URGUrgent Pointer가 유효함Utcp-urg
0x40ECEECN(명시적 혼잡 통지) 관련Etcp-ece
0x80CWR혼잡 윈도우 감소 알림 (ECN)Wtcp-cwr

연결이 수립된 뒤의 TCP 세그먼트는 거의 모두 ACK 플래그가 켜져 있습니다. SYN·FIN·RST의 구체적인 사용 흐름은 08편(3-Way Handshake)과 09편(FIN·RST)에서 다룹니다.

2-4. 자주 보는 TCP 옵션

Kind옵션용도
0 / 1End of Option List / No-Operation옵션 끝 표시 / 4바이트 정렬용 채움
2MSS (Maximum Segment Size)한 세그먼트에 담을 수 있는 최대 데이터 크기 (SYN에서 교환)
3Window ScaleWindow 값을 2의 거듭제곱만큼 확대 (SYN에서 교환)
4 / 5SACK Permitted / SACK선택적 확인 응답
8Timestamps왕복 시간 측정, 시퀀스 번호 재사용 보호

SYN 패킷의 옵션 조합·순서·초기 TTL은 운영체제마다 조금씩 달라서, 패시브 OS 식별의 근거로 쓰이기도 합니다.


3. 동작 원리

같은 "짧은 요청 하나"를 TCP와 UDP로 보낼 때 네트워크에 나타나는 패킷 수를 비교합니다.

TCP 헤더 구조
그림 1. TCP 헤더 — 신뢰성을 위한 시퀀스·ACK·플래그·윈도우 필드가 있습니다

UDP 헤더 구조
그림 2. UDP 헤더 — 포트·길이·체크섬만 있는 8바이트 구조

[TCP로 요청 1개]                          [UDP로 요청 1개]

클라이언트          서버                   클라이언트          서버
   │── SYN ────────→ │   연결 수립           │── 요청 ────────→ │
   │←──── SYN/ACK ── │   (헤더만, 데이터 0)   │←──────── 응답 ── │
   │── ACK ────────→ │                      │
   │── 요청(PSH/ACK)→│   데이터 전송          (연결 수립·종료 없음,
   │←───────── ACK ──│                        유실되면 애플리케이션이
   │←─ 응답(PSH/ACK)─│                        재전송 여부를 판단)
   │── ACK ────────→ │
   │── FIN/ACK ────→ │   연결 종료
   │←──── FIN/ACK ── │
   │── ACK ────────→ │

→ 10개 안팎의 패킷, 헤더 20바이트+옵션        → 2개 패킷, 헤더 8바이트
  (ACK를 응답에 함께 싣는 등 구현에 따라 달라짐)

이 차이는 헤더 필드에서 그대로 나옵니다.

  • TCP는 Sequence/Acknowledgment 번호로 "어디까지 받았는지"를 주고받으므로 유실·순서 뒤바뀜을 스스로 복구합니다. 대신 연결 수립·확인 응답·종료 패킷이 추가됩니다.
  • UDP는 포트·길이·체크섬만 있으므로 가볍습니다. DNS 질의, NTP, 스트리밍, VoIP처럼 빠른 응답이 중요하거나 애플리케이션이 직접 재전송을 처리하는 경우에 쓰입니다.

보안 관점에서 중요한 결과가 하나 있습니다. TCP는 3-Way Handshake를 거쳐야 데이터가 오가므로, 출발지 IP를 위조하면 SYN/ACK가 위조된 주소로 가서 연결을 완성하기 어렵습니다. UDP는 이런 확인 단계가 없어, 위조된 출발지로 요청 한 번만 보내도 응답이 위조된 주소(피해자)로 갑니다. 작은 요청에 큰 응답을 돌려주는 서비스가 반사·증폭 공격에 악용되는 원리입니다.


4. 실제 명령어 / 실습

실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu) 2대(192.168.10.10 클라이언트, 192.168.10.20 서버 예시). 인터페이스 이름은 ens33을 예시로 사용합니다(환경에 따라 다름).

# 도구 설치
sudo dnf install -y tcpdump nmap-ncat      # Rocky
sudo apt install -y tcpdump netcat-openbsd # Ubuntu

4-1. TCP 헤더 관찰 (SSH 접속)

# [서버 터미널] SSH 연결 시작 부분 10개 캡처, -v로 옵션·TTL 등 상세 표시
sudo tcpdump -nn -v -i ens33 -c 10 'tcp port 22'

# [클라이언트 터미널] 접속 시도
ssh user@192.168.10.20

4-2. UDP 헤더 관찰

# [서버 터미널] UDP 9999 대기 (Rocky의 ncat, Ubuntu의 openbsd nc 모두 동작)
nc -u -l 9999

# [서버의 다른 터미널] 캡처
sudo tcpdump -nn -v -i ens33 'udp port 9999'

# [클라이언트 터미널] 5바이트("test\n") 전송
echo test | nc -u -w1 192.168.10.20 9999

4-3. 헤더 바이트 위치를 이용한 필터

# SYN 비트가 켜진 TCP (오프셋 13, 값 0x02)
sudo tcpdump -nn -i ens33 'tcp[13] & 0x02 != 0'
# 위와 같은 의미 (이름 사용)
sudo tcpdump -nn -i ens33 'tcp[tcpflags] & tcp-syn != 0'

# TCP 옵션이 있는 세그먼트 (Data Offset 상위 4비트가 5보다 큼 = 헤더 20바이트 초과)
sudo tcpdump -nn -i ens33 'tcp and (tcp[12] >> 4) > 5'

# UDP Length 필드가 512 초과 (오프셋 4부터 2바이트)
sudo tcpdump -nn -i ens33 'udp[4:2] > 512'

# 헤더를 16진수로 함께 출력해 필드 위치 확인
sudo tcpdump -nn -X -i ens33 -c 1 'tcp port 22'

4-4. 소켓 상태로 본 차이

# TCP 소켓: 상태(State) 열이 LISTEN, ESTAB 등으로 표시
ss -tan
# UDP 소켓: 연결 상태 개념이 없어 대부분 UNCONN으로 표시
ss -uan

ss 명령의 기본 사용법은 ss와 ip 명령어 글을 참고합니다.

📷 [실습 화면 삽입] tcpdump -nn -v 'tcp port 22' 결과 — SYN 패킷의 Flags와 options 부분


5. 결과 확인

tcpdump 출력 형식 예시(값은 환경마다 다름):

# TCP (SYN)
IP (tos 0x0, ttl 64, id 40211, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.10.10.51514 > 192.168.10.20.22: Flags [S], cksum 0x9a3c (correct), seq 1180562114, win 64240, options [mss 1460,sackOK,TS val 1920311 ecr 0,nop,wscale 7], length 0

# UDP
IP (tos 0x0, ttl 64, id 5521, offset 0, flags [DF], proto UDP (17), length 33)
    192.168.10.10.41234 > 192.168.10.20.9999: UDP, length 5
출력 요소해당 헤더 필드
proto TCP (6) / proto UDP (17)IP 헤더의 Protocol 번호 (TCP 6, UDP 17)
IP length 60 (TCP)IP 20 + TCP 40 (기본 20 + 옵션 20) + 데이터 0
IP length 33 (UDP)IP 20 + UDP 8 + 데이터 5
Flags [S], seq, winTCP Control Bits, Sequence Number, Window
options [mss …, wscale 7]TCP Options (SYN에서 교환)
UDP, length 5UDP 데이터 길이 (UDP Length 필드 13 = 헤더 8 + 데이터 5)
cksum … (correct)체크섬. 송신 호스트에서 캡처하면 NIC 오프로딩 때문에 incorrect로 보일 수 있음
  • TCP 헤더 최소 20바이트, UDP 헤더 8바이트임을 IP length로 역산해 확인했다
  • SYN 패킷에서 MSS·SACK·Timestamps·Window Scale 옵션을 찾았다
  • tcp[13] 필터와 tcp[tcpflags] 필터가 같은 결과임을 확인했다
  • ss -tan과 ss -uan의 State 열 차이를 설명할 수 있다
  • UDP에는 SYN/ACK 같은 연결 확인 절차가 없음을 캡처로 확인했다

📷 [실습 화면 삽입] UDP 캡처 결과 — proto UDP (17), length 33과 UDP, length 5


6. 패킷 / 로그 분석

관찰정상일 수 있는 경우의심해야 하는 경우
TCP 플래그 조합SYN, SYN/ACK, ACK, PSH/ACK, FIN/ACK, RST, RST/ACK플래그 없음(NULL), FIN만, FIN+PSH+URG, SYN+FIN 등 RFC상 정상 흐름에 없는 조합 (05. 네트워크 스캔 · 공격 징후 분석 시리즈에서 다룸)
SYN 패킷에 데이터 포함TCP Fast Open 사용 환경 (일부 클라이언트·서버)지원하지 않는 환경에서 SYN에 페이로드
TCP 옵션 없는 SYN일부 경량 장비·임베디드 기기일반 OS에서 나올 수 없는 옵션 조합 → 도구가 직접 만든 패킷일 가능성
큰 UDP 응답이 한 방향으로만 대량대용량 DNS 응답(DNSSEC), 스트리밍요청한 적 없는 DNS/NTP 응답이 외부 다수 IP에서 유입 → 반사·증폭 공격 피해
UDP 체크섬 0 (IPv4)일부 터널링 프로토콜 구현일반 서비스에서 반복적으로 보임
# 플래그가 하나도 없는 TCP (NULL)
sudo tcpdump -nn -i ens33 'tcp[tcpflags] == 0'

# SYN과 FIN이 동시에 켜진 TCP
sudo tcpdump -nn -i ens33 'tcp[tcpflags] & (tcp-syn|tcp-fin) == (tcp-syn|tcp-fin)'

# 외부에서 들어오는 출발지 포트 53 UDP 중 큰 응답 (반사 트래픽 점검용)
sudo tcpdump -nn -i ens33 'udp src port 53 and udp[4:2] > 512'

필터는 후보를 좁히는 용도입니다. 비정상 플래그 한두 개는 네트워크 장비 오류나 패킷 손상일 수도 있으므로, 출발지·빈도·대상 범위를 함께 봐야 합니다.


7. 보안관제 관점

흔적이 남는 곳

  • 방화벽 세션 로그: TCP는 연결 시작~종료가 명확해 세션 단위 기록이 정확합니다. UDP는 연결 개념이 없어 장비가 타이머로 세션을 추정합니다(일정 시간 패킷이 없으면 종료로 간주).
  • IDS/IPS: 플래그 조합, 헤더 길이, 옵션 이상 등 헤더 기반 룰이 많습니다(06. 방화벽 · IDS/IPS 분석 시리즈에서 다룸).
  • NetFlow/세션 요약 로그: 세션별 TCP 플래그 누적값(OR 값)을 기록하는 경우가 많아, 전체 패킷 없이도 "SYN만 있고 ACK가 없는 세션" 같은 판단이 가능합니다.

한계와 오탐 주의

  • UDP 출발지 IP는 위조가 쉬우므로, UDP 로그의 출발지를 실제 공격 주체로 단정하면 안 됩니다. 반사 공격이라면 로그상 출발지(DNS·NTP 서버)는 오히려 악용당한 쪽입니다.
  • 송신 호스트에서의 캡처는 체크섬 오프로딩, TSO(세그먼트 분할 오프로딩) 때문에 실제 전송과 다르게 보일 수 있습니다(큰 세그먼트, 잘못된 체크섬 표시). 캡처 위치에 따른 차이는 03. Wireshark 패킷 분석 시리즈에서 다룹니다.
  • "UDP = 위험, TCP = 안전"이 아닙니다. 어떤 프로토콜이든 어떤 서비스가 쓰는지가 판단 기준이며, 이는 02. 포트 · 프로토콜 분석 시리즈에서 다룹니다.

8. 핵심 정리

  • TCP 헤더는 최소 20바이트(옵션 포함 최대 60바이트), UDP 헤더는 고정 8바이트입니다.
  • TCP의 신뢰성은 Sequence·Acknowledgment·Window·Flags 필드에서, UDP의 가벼움은 이 필드들이 없다는 점에서 나옵니다.
  • TCP Flags는 오프셋 13바이트에 있으며, tcp[13] 또는 tcp[tcpflags]로 필터링합니다.
  • UDP는 연결 확인 절차가 없어 출발지 위조가 쉽고, 이 구조가 반사·증폭 공격의 원리가 됩니다.
  • 정상 흐름에 없는 플래그 조합이나 비정상 옵션은 탐지 단서지만, 빈도·출발지와 함께 판단해야 합니다.

다음 글: 08. TCP 3-Way Handshake — 연결이 성립했다는 증거

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글