📚 네트워크 · 패킷 분석 › 01. TCP/IP 구조 이해 — 39편
이전 글: 38. TCP란 무엇인가 · 다음 글: 40. TCP와 UDP 헤더 비교 — 신뢰성과 속도의 차이
UDP(User Datagram Protocol)는 전송 계층 프로토콜로, IP 헤더의 Protocol 번호 17을 사용하며 RFC 768(1980)에 정의되어 있습니다. 명세가 몇 쪽에 불과할 만큼 단순하며, IP에 포트 번호와 선택적 체크섬만 더해 줍니다.
| UDP가 하는 일 | UDP가 하지 않는 일 |
|---|---|
| 포트로 애플리케이션(프로세스) 구분 | 연결 수립·해제 |
| 체크섬으로 손상 검출 (IPv4에서는 선택) | 유실 시 재전송 |
| 메시지 경계 보존 | 순서 보장 |
| — | 흐름 제어·혼잡 제어 |
UDP가 보내는 단위인 Datagram의 구조와 크기는 30. UDP Datagram, 헤더 필드를 TCP와 나란히 비교하는 내용은 40. TCP와 UDP 헤더 비교 — 신뢰성과 속도의 차이에서 다룹니다. 이 글은 UDP라는 선택이 무엇을 의미하는지에 집중합니다.
UDP 통신에는 "연결"이 없습니다. 보내는 쪽은 상대가 준비됐는지 확인하지 않고 바로 데이터를 보내고, 받는 쪽은 해당 포트에 대기 중인 소켓이 있으면 전달합니다.
[DNS 질의 예: 클라이언트 192.168.10.10 → 리졸버 192.168.10.53]
클라이언트 (임의 포트 53001) 리졸버 (UDP 53)
│ ── 질의 Datagram (Transaction ID=0x1a2b) ──→ │
│ │ 처리
│ ←── 응답 Datagram (같은 ID, 53 → 53001) ──── │
↓
응답이 안 오면? → UDP는 아무것도 하지 않음
→ DNS 클라이언트(애플리케이션)가 타이머 후 재질의
[닫힌 포트로 보낸 경우]
│ ── Datagram → 192.168.10.20:9999 (대기 소켓 없음) ──→
│ ←── ICMP 3/3 Port Unreachable (호스트가 보냄, 설정·방화벽에 따라 없을 수 있음)
UDP를 선택하는 이유는 대체로 세 가지입니다. 빠른 짧은 요청·응답(연결 수립 비용이 아까움), 실시간성(늦게 도착한 데이터는 쓸모가 없음), 브로드캐스트·멀티캐스트(1:N 전송은 연결 개념과 맞지 않음).
| 서비스 | 포트 | UDP를 쓰는 이유 |
|---|---|---|
| DNS | 53 | 짧은 질의·응답 (응답이 크거나 영역 전송이면 TCP 사용) |
| DHCP | 67(서버) / 68(클라이언트) | IP가 없는 상태에서 브로드캐스트로 요청 |
| NTP | 123 | 짧은 시간 교환, 지연 측정 |
| SNMP | 161 / 162(Trap) | 장비 상태 조회·알림 |
| Syslog | 514 | 로그를 가볍게 전송 (전달 보장 없음) |
| TFTP | 69 | 단순 파일 전송 (자체 확인 응답 사용) |
| QUIC (HTTP/3) | 443 | 자체 신뢰성·암호화 구현 |
| VoIP·스트리밍(RTP 등) | 동적 | 재전송보다 실시간성이 중요 |
Syslog를 UDP로 받는 경우 네트워크 혼잡 시 로그가 조용히 유실될 수 있다는 점은 관제 인프라 설계에서도 중요합니다. 전달 보장이 필요하면 TCP·TLS 기반 전송을 검토합니다.
| 보안상 성질 | 결과 |
|---|---|
| 연결 수립이 없음 | 출발지 IP를 위조한 요청이 그대로 처리됨 → 응답이 위조된 주소(피해자)로 감 |
| 요청보다 큰 응답을 주는 서비스 존재 | 반사·증폭(Reflection/Amplification) DDoS에 악용 |
| 열린 포트도 응답하지 않을 수 있음 | 스캔 결과가 "열림 또는 필터됨"처럼 모호함 |
| 상태가 없음 | 방화벽은 타임아웃으로 가상의 세션을 만들어 추적 |
실습 예시 — 본인 소유 Linux VM에서 UDP 소켓과 통신을 확인합니다.
# UDP로 대기 중인 소켓 (-u UDP, -l 대기, -n 숫자, -p 프로세스)
sudo ss -ulnp
# 현재 UDP 소켓 전체 (연결 상태 개념이 없어 대부분 UNCONN)
ss -uan
# DNS 질의를 UDP로 보내고 캡처 (Rocky: bind-utils, Ubuntu: dnsutils 패키지의 dig)
sudo tcpdump -nn -i ens33 'udp port 53' &
dig @192.168.10.53 example.com A
ss -ulnp 출력 형식 예시(값은 환경마다 다름):
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",...))
UNCONN 0 0 0.0.0.0:68 0.0.0.0:* users:(("dhclient",...))
UNCONN 0 0 0.0.0.0:123 0.0.0.0:* users:(("chronyd",...))
| 출력 요소 | 읽는 법 |
|---|---|
UNCONN | UDP 소켓의 일반 상태. TCP의 LISTEN/ESTAB 같은 구분이 없음 |
127.0.0.53%lo:53 | Ubuntu의 로컬 DNS 스텁(systemd-resolved) 예시 |
0.0.0.0:123 | 모든 인터페이스에서 NTP 수신 대기 |
tcpdump에서는 IP 192.168.10.10.53001 > 192.168.10.53.53: 6699+ A? example.com. (29)처럼 질의 한 줄, 응답 한 줄로 끝나는 형태가 보입니다(형식 예시).
| 흔적 위치 | 확인할 수 있는 것 |
|---|---|
| 방화벽 로그 | UDP 흐름(타임아웃 기반 세션)의 5-tuple, 패킷·바이트 수 |
| DNS·NTP 서버 로그 | 질의 출발지, 질의 유형, 응답 크기 (로그 설정 필요) |
| IDS/IPS | 증폭 공격, DNS 이상, UDP 스캔 관련 시그니처 |
| NetFlow | 요청 대비 응답 바이트 비율, 출발지 수 |
관제자가 확인할 질문
오탐 주의: UDP 흐름에는 종료 신호가 없어 방화벽 세션의 지속 시간·종료 사유는 타임아웃 설정에 따라 결정됩니다. 스트리밍·VoIP·QUIC(443/udp)은 정상적으로 대량 UDP를 만들며, 출발지 IP는 위조 가능하므로 UDP 단독 로그의 출발지를 "실제 공격자"로 단정하지 않습니다.