📚 네트워크 · 패킷 분석 › 01. TCP/IP 구조 이해 — 49편
이전 글: 48. DHCP DORA 과정 — IP를 받는 4단계 · 다음 글: 50. 웹 요청 하나의 전체 경로 — 01 시리즈 종합
참고(리눅스 시스템 기초): Firewalld 이해 — masquerade·포트 포워딩 설정이 있는 곳
보안관제에서 가장 자주 하는 작업 중 하나는 "이 IP가 누구인가"를 밝히는 일입니다. 그런데 같은 통신 하나를 두고도 장비마다 기록된 IP가 다릅니다.
192.168.10.25192.168.10.25 → 변환 후 198.51.100.5198.51.100.5세 로그가 모두 맞습니다. 중간에 NAT(Network Address Translation) 가 주소를 바꿨기 때문입니다. 이 구조를 모르면 다음과 같은 실수를 하게 됩니다.
| 실수 | 결과 |
|---|---|
| 웹서버 로그의 공인 IP를 곧바로 "공격자 PC"로 판단 | 실제로는 회사·통신사 NAT 뒤의 수많은 사용자 중 하나일 수 있음 |
| 외부 위협 인텔리전스에서 받은 IP로 내부 로그 검색 | 내부 로그에는 사설 IP만 남아 있어 검색 결과 0건 |
| 방화벽 NAT 로그 없이 내부 단말 추적 | 공인 IP → 사설 IP 역추적 불가 |
이번 글은 사설 IP와 공인 IP의 역할, NAT가 주소를 바꾸는 방식, 그 흔적이 어디에 남는지를 다룹니다. 사설·특수 대역의 전체 표는 03. IPv4 주소와 서브넷(CIDR)에 정리했으므로 여기서는 반복하지 않습니다.
| 구분 | 사설 IP | 공인 IP |
|---|---|---|
| 범위 | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 (RFC 1918) | 그 외 인터넷에서 라우팅되는 주소 |
| 유일성 | 조직 내부에서만 유일하면 됨 (다른 회사와 겹쳐도 됨) | 인터넷 전체에서 유일 |
| 인터넷 라우팅 | 인터넷 라우터가 전달하지 않음 | 전달됨 |
| 관제에서의 의미 | 내부 자산 식별 (자산 대장·DHCP 로그와 연결) | 외부 통신 상대 식별 (평판·위치 조회 대상) |
추가로 통신사 내부 NAT용으로 100.64.0.0/10(RFC 6598, Shared Address Space) 대역이 있습니다. 모바일·일부 가정용 회선에서 CGNAT(Carrier-Grade NAT) 에 쓰이며, 이 경우 사용자 단말 → 통신사 NAT → 인터넷 순으로 NAT가 두 번 일어나기도 합니다.
| 종류 | 바뀌는 것 | 대표 용도 | Linux(netfilter)에서의 이름 |
|---|---|---|---|
| SNAT (Source NAT) | 출발지 IP(와 포트) | 내부 PC들이 공인 IP 하나로 인터넷 사용 | SNAT, MASQUERADE |
| DNAT (Destination NAT) | 목적지 IP(와 포트) | 공인 IP:443 → 내부 웹서버 10.0.20.10:8443 포트 포워딩 | DNAT |
| PAT / NAPT | IP + 포트 조합 | 여러 내부 호스트가 하나의 공인 IP를 공유 (포트로 구분) | SNAT/MASQUERADE 시 포트 변환 포함 |
| 1:1 Static NAT | IP만 고정 매핑 | 특정 서버에 전용 공인 IP 부여 | SNAT + DNAT 조합 |
MASQUERADE는 SNAT의 일종으로, 변환할 공인 IP를 나가는 인터페이스의 현재 주소로 자동 선택합니다. DHCP로 외부 주소가 바뀌는 환경에 쓰입니다.
NAT 장비는 "어떤 내부 주소:포트를 어떤 외부 주소:포트로 바꿨는지"를 변환 테이블에 기록해 둡니다. 응답 패킷이 돌아오면 이 테이블을 보고 원래 내부 주소로 되돌립니다. Linux에서는 netfilter의 conntrack(connection tracking) 이 이 역할을 합니다. 즉, NAT는 상태를 기억하는(stateful) 기능이며, 변환 테이블이 사라지면 역추적 근거도 사라집니다.
내부 PC 192.168.10.25가 외부 웹서버 203.0.113.10:443에 접속하고, 방화벽의 공인 IP가 198.51.100.5인 상황입니다.

그림 1. PAT 변환 — 내부 사설 IP·포트가 공인 IP·포트로 바뀌고, 응답은 NAT 테이블로 역변환됩니다
[내부 PC] [NAT 방화벽/라우터] [외부 웹서버]
192.168.10.25 내부 192.168.10.1 203.0.113.10
외부 198.51.100.5
① 요청 (내부 구간)
src 192.168.10.25:51514 → dst 203.0.113.10:443
↓
② SNAT 변환 + 변환 테이블 기록
192.168.10.25:51514 ⇄ 198.51.100.5:40001
↓
③ 요청 (외부 구간)
src 198.51.100.5:40001 → dst 203.0.113.10:443 → 웹서버 로그에는 198.51.100.5
↓
④ 응답 (외부 구간)
src 203.0.113.10:443 → dst 198.51.100.5:40001
↓
⑤ 변환 테이블 조회 후 역변환
dst 198.51.100.5:40001 → 192.168.10.25:51514
↓
⑥ 응답 (내부 구간)
src 203.0.113.10:443 → dst 192.168.10.25:51514
여기서 관제 관점의 핵심은 세 가지입니다.
198.51.100.5만 알 수 있습니다.198.51.100.5:443으로 들어온 요청이 내부 서버 10.0.20.10:8443으로 바뀌므로, 내부 서버 로그의 목적지 포트와 방화벽 정책의 포트가 다를 수 있습니다.NAT는 IP 헤더의 주소를 바꾸기 때문에 IP·TCP/UDP 체크섬도 다시 계산됩니다. 또한 NAT 뒤의 호스트는 외부에서 먼저 연결을 시작할 수 없으므로(DNAT 설정이 없는 한), "외부에서 내부 PC로 직접 들어온 연결"이 보인다면 포트 포워딩이나 정책 설정을 먼저 확인해야 합니다.
실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu). 인터페이스 이름은 ens33을 예시로 사용합니다(환경에 따라 다름). VMware의 NAT 네트워크 모드를 쓰면 VM 자체가 NAT 뒤에 있으므로, 추가 구성 없이 "내부 주소와 외부에 보이는 주소가 다르다"는 사실을 관찰할 수 있습니다.
# 인터페이스의 IPv4 주소 확인
ip -4 addr show ens33
# 기본 게이트웨이(= NAT를 수행할 가능성이 있는 장비) 확인
ip route show default
inet 192.168.x.x/24처럼 사설 대역이면, 이 VM이 인터넷으로 나갈 때 어딘가에서 반드시 SNAT가 일어납니다.
# Rocky Linux
sudo dnf install -y conntrack-tools
# Ubuntu
sudo apt install -y conntrack
# 현재 추적 중인 연결 목록
sudo conntrack -L
# TCP만, 특정 목적지 포트만
sudo conntrack -L -p tcp --dport 443
# 추적 중인 연결 수 / 최대값
cat /proc/sys/net/netfilter/nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
# 새 연결이 생기고 사라지는 이벤트를 실시간 확인 (Ctrl+C로 종료)
sudo conntrack -E
nf_conntrack 모듈이 로드되지 않은 환경에서는 /proc/sys/net/netfilter/ 경로가 없을 수 있습니다. firewalld가 동작 중이면 일반적으로 로드되어 있습니다.
# 활성 zone 확인
sudo firewall-cmd --get-active-zones
# masquerade(SNAT) 사용 여부
sudo firewall-cmd --zone=public --query-masquerade
# 포트 포워딩(DNAT) 규칙 목록
sudo firewall-cmd --zone=public --list-forward-ports
일반 서버라면 masquerade는 no, 포워딩 규칙은 비어 있는 것이 보통입니다. 서버가 의도치 않게 NAT 장비 역할을 하고 있다면 그 자체가 점검 대상입니다(라우팅 여부는 04편의 ip_forward 참고).
📷 [실습 화면 삽입]
ip -4 addr show ens33와ip route show default결과 — 사설 IP와 게이트웨이 확인
# tcpdump 설치 (없을 경우)
sudo dnf install -y tcpdump # Rocky
sudo apt install -y tcpdump # Ubuntu
# 외부 443 통신을 5개만 캡처
sudo tcpdump -nn -i ens33 -c 5 'tcp port 443'
다른 터미널에서 curl -sI https://example.com처럼 외부 사이트에 요청하면, 캡처에는 VM의 사설 IP가 출발지로 찍힙니다. 외부 서버가 보는 출발지는 이와 다르다는 점이 NAT의 흔적입니다.
conntrack -L 출력 형식 예시(값은 환경마다 다름):
tcp 6 431999 ESTABLISHED src=192.168.10.25 dst=203.0.113.10 sport=51514 dport=443 src=203.0.113.10 dst=198.51.100.5 sport=443 dport=40001 [ASSURED] mark=0 use=1
한 줄에 튜플이 두 개입니다.
| 부분 | 의미 |
|---|---|
첫 번째 src/dst/sport/dport | 원래 방향(original): 내부 PC가 보낸 그대로 |
두 번째 src/dst/sport/dport | 응답 방향(reply): 돌아올 패킷이 가져야 할 주소 |
| 두 튜플이 대칭이 아님 | 주소 변환이 일어났다는 뜻 (위 예시는 reply의 dst=198.51.100.5 dport=40001 → SNAT) |
431999 | 이 항목이 만료되기까지 남은 초 |
[ASSURED] | 양방향 트래픽이 확인된 연결 |
NAT를 하지 않는 일반 서버에서는 두 튜플이 정확히 뒤집힌 대칭 형태입니다.
ip -4 addr로 내 주소가 사설 대역인지 확인했다conntrack -L에서 original / reply 튜플을 구분해 읽을 수 있다📷 [실습 화면 삽입]
sudo conntrack -L -p tcp --dport 443출력 — original/reply 튜플 표시
NAT가 있는 환경에서 IP를 해석할 때 판단 기준입니다.
| 관찰 | 정상일 수 있는 경우 | 의심해야 하는 경우 |
|---|---|---|
| 외부 로그에 같은 공인 IP에서 대량 요청 | 회사·학교·통신사 NAT 뒤의 여러 사용자 | 동일 User-Agent·동일 경로를 초 단위로 반복 |
| 내부 서버 로그의 출발지가 전부 방화벽 내부 IP | 방화벽이 SNAT까지 하는 구성, 리버스 프록시 경유 | 설계와 다르게 원래 출발지가 사라진 경우 (추적 불가 상태) |
서버에서 masquerade yes | 게이트웨이·VPN 서버 역할이 문서화됨 | 일반 서버인데 켜져 있음 (피벗 경로가 될 수 있음) |
| 모르는 포트 포워딩 규칙 | 변경 이력·승인이 있는 서비스 공개 | 이력 없이 추가된 고포트 → 내부 SSH/RDP 연결 |
| conntrack 수가 최대값 근접 | 트래픽이 많은 게이트웨이의 정상 피크 | 평소 대비 급증 + 대부분 미완성 연결 (flood 가능성) |
conntrack 테이블이 가득 차면 커널 로그에 table full, dropping packet이 포함된 nf_conntrack 메시지가 남습니다.
# 커널 로그에서 conntrack 포화 흔적 확인
sudo journalctl -k | grep -i conntrack
# Rocky: /var/log/messages, Ubuntu: /var/log/syslog 에도 남음
sudo grep -i 'conntrack' /var/log/messages # Rocky
sudo grep -i 'conntrack' /var/log/syslog # Ubuntu
역추적 순서(외부에서 "198.51.100.5가 공격했다"는 통보를 받은 경우의 일반적인 흐름):
외부 통보: 시각 T, 공인 IP 198.51.100.5, 출발지 포트 40001
↓
방화벽 NAT/세션 로그에서 T 전후 + 변환 포트 40001 검색
↓
내부 사설 IP 192.168.10.25 확인
↓
DHCP 로그로 시각 T의 192.168.10.25 → MAC 주소 → 자산(사용자) 확인
↓
해당 단말의 EDR·프록시 로그로 실제 행위 확인
통보에 출발지 포트가 없으면 같은 시각 같은 목적지로 나간 세션이 여러 개일 수 있어 단정할 수 없습니다. 이때는 "후보 목록"으로 보고하는 것이 정확합니다.
흔적이 남는 곳
| 위치 | 남는 정보 |
|---|---|
| 방화벽/UTM 세션·NAT 로그 | 변환 전·후 IP와 포트, 세션 시작·종료 시각 (장비에 따라 NAT 로그를 별도로 켜야 함) |
| DHCP 서버 로그 | 사설 IP ↔ MAC ↔ 시각 (DHCP 과정은 02. 포트 · 프로토콜 분석 시리즈에서 다룸) |
| 프록시·로드밸런서 | X-Forwarded-For 헤더로 원래 클라이언트 IP 전달 (단, 클라이언트가 위조 가능하므로 신뢰 구간에서만 사용) |
| Linux 게이트웨이 | conntrack (메모리상 정보, 만료되면 사라짐) |
한계와 오탐 주의
conntrack -L의 original/reply 튜플 비대칭으로 변환 여부를 확인할 수 있습니다.