📚 네트워크 · 패킷 분석 › 01. TCP/IP 구조 이해 — 10편
이전 글: 09. IPv6 기초 — 관제에서 놓치기 쉬운 두 번째 주소 체계 · 다음 글: 11. Unicast, Broadcast, Multicast
공인 IP(Public IP) 는 인터넷 전체에서 유일하도록 관리되며, 인터넷 라우터들이 전달해 주는 주소입니다. 사설 IP(Private IP) 는 조직 내부에서만 쓰도록 따로 떼어 둔 주소로, 인터넷 라우터는 이 주소를 목적지로 하는 패킷을 전달하지 않습니다.
IPv4 사설 대역은 RFC 1918에 정의된 세 구간입니다.
| 대역 | 범위 | 주소 수 |
|---|---|---|
10.0.0.0/8 | 10.0.0.0 ~ 10.255.255.255 | 16,777,216 |
172.16.0.0/12 | 172.16.0.0 ~ 172.31.255.255 | 1,048,576 |
192.168.0.0/16 | 192.168.0.0 ~ 192.168.255.255 | 65,536 |
172.16.0.0/12는 172.16부터 172.31까지이므로, 172.32.x.x는 사설 대역이 아닙니다. 그 밖의 특수 대역은 14. IPv4 주소와 서브넷(CIDR) — 같은 네트워크인지 판단하는 법에 정리되어 있습니다.
공인 IP는 계층적으로 할당됩니다.
IANA (전 세계 주소 총괄)
↓ 대륙·지역별로 큰 블록 배분
RIR (지역 인터넷 레지스트리: APNIC, ARIN, RIPE NCC, LACNIC, AFRINIC)
↓ 아시아·태평양은 APNIC
NIR (국가 레지스트리: 한국은 KISA가 운영하는 KRNIC)
↓
ISP·기관 (통신사, 대학, 대기업)
↓
고객 회선 / 서버 / 방화벽의 외부 인터페이스
반면 사설 IP는 누구에게 할당받을 필요 없이 조직이 자유롭게 씁니다. 그래서 A사와 B사가 모두 192.168.10.0/24를 써도 문제가 없습니다. 대신 사설 IP 호스트가 인터넷과 통신하려면, 경계 장비가 출발지를 공인 IP로 바꿔 주는 NAT가 필요합니다. NAT의 변환 방식과 흔적은 49. 사설 IP · 공인 IP와 NAT — 로그의 IP가 서로 다른 이유에서 다룹니다.
| 구분 | 공인 IP | 사설 IP |
|---|---|---|
| 할당 | IANA → RIR → ISP 계층 할당 | 조직이 자유롭게 사용 |
| 유일성 | 인터넷 전체에서 유일 | 조직 내부에서만 유일하면 됨 |
| 인터넷 라우팅 | 가능 | 불가 (NAT 필요) |
| WHOIS·평판 조회 | 의미 있음 (소유 기관 확인 가능) | 의미 없음 (내부 자산 목록으로 확인) |
| 흔한 위치 | 방화벽 외부 인터페이스, 공개 서버, 클라우드 | 사내 PC, 내부 서버, 가정용 공유기 안쪽 |
헷갈리기 쉬운 대역도 알아 두면 좋습니다.
100.64.0.0/10 (RFC 6598): 통신사 내부 NAT(CGNAT)용 공유 주소 공간. 사설 대역은 아니지만 인터넷에서 라우팅되지도 않습니다.192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 (RFC 5737): 문서·예제용 주소. 이 블로그의 예시 "외부 IP"도 이 대역을 씁니다.127.0.0.0/8(루프백), 169.254.0.0/16(링크 로컬)은 사설 대역과 목적이 다릅니다.IPv6에서는 fc00::/7(실제 사용은 fd00::/8)의 ULA(Unique Local Address)가 사설 주소와 비슷한 역할을 합니다(09. IPv6 기초 — 관제에서 놓치기 쉬운 두 번째 주소 체계에서 다룸).
실습 예시 — 주소가 어느 범주인지 판별 (Rocky·Ubuntu 공통, python3 기본 제공)
python3 - <<'EOF'
import ipaddress
for s in ["192.168.10.25", "172.31.5.9", "172.32.5.9", "100.64.1.1", "203.0.113.10"]:
a = ipaddress.ip_address(s)
print(f"{s:15} private={a.is_private!s:5} global={a.is_global}")
EOF
# 출력 예시(값은 환경마다 다름)
192.168.10.25 private=True global=False
172.31.5.9 private=True global=False
172.32.5.9 private=False global=True
100.64.1.1 private=False global=False
203.0.113.10 private=True global=False
마지막 줄에 주의해야 합니다. Python의 is_private는 RFC 1918뿐 아니라 문서용 대역 등 "인터넷에서 쓰이지 않는 대역" 전체를 True로 봅니다. 즉 도구의 "private" 판정 기준이 RFC 1918과 정확히 같지 않을 수 있으므로, 판별 로직을 쓸 때는 기준을 명시해야 합니다.
호스트에서 보이는 주소(ip -4 addr)가 사설 IP라면, 외부에서 보이는 공인 IP는 경계 장비(공유기·방화벽)의 외부 인터페이스 주소입니다. Windows에서는 ipconfig로 같은 방식으로 확인합니다.
169.254.169.254(클라우드 메타데이터 주소) 접근에 악용될 수 있습니다.관제에서 알림을 받으면 가장 먼저 출발지·목적지가 공인인지 사설인지로 통신 방향을 분류합니다.
| 출발지 → 목적지 | 의미 | 우선 확인할 것 |
|---|---|---|
| 공인 → 사설(공개 서버) | 외부에서 내부 서비스로 인바운드 | 노출 서비스, 공격 시도 여부, 응답 결과 |
| 사설 → 공인 | 내부에서 외부로 아웃바운드 | 목적지 평판, 업무 관련성, 전송량 |
| 사설 → 사설 | 내부 간 통신(East-West) | 내부 확산·정찰 여부 |
| 공인 → 공인 | 경계 장비 외부 구간 | 경계 장비 대상 공격, DMZ 구성 확인 |
관제자가 확인할 질문은 다음과 같습니다.
⚠️ 오탐 주의: 사설 IP라는 이유만으로 "내부 정상 통신"으로 넘기면 내부 확산을 놓칩니다. 반대로 CGNAT 대역(100.64.0.0/10)이나 클라우드 VPC 대역을 외부 공격 IP로 오인하는 경우도 있으므로, 조직의 대역 구성표를 기준으로 판단해야 합니다.
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 세 가지입니다(172.32.x.x는 제외).