49. 사설 IP · 공인 IP와 NAT — 로그의 IP가 서로 다른 이유

changseop lee·5일 전

📚 네트워크 · 패킷 분석 › 01. TCP/IP 구조 이해 — 49편
이전 글: 48. DHCP DORA 과정 — IP를 받는 4단계 · 다음 글: 50. 웹 요청 하나의 전체 경로 — 01 시리즈 종합
참고(리눅스 시스템 기초): Firewalld 이해 — masquerade·포트 포워딩 설정이 있는 곳

1. 왜 알아야 하는가

보안관제에서 가장 자주 하는 작업 중 하나는 "이 IP가 누구인가"를 밝히는 일입니다. 그런데 같은 통신 하나를 두고도 장비마다 기록된 IP가 다릅니다.

  • 내부 PC의 EDR 로그: 출발지 192.168.10.25
  • 방화벽 로그: 내부 192.168.10.25 → 변환 후 198.51.100.5
  • 외부 웹서버 접근 로그: 출발지 198.51.100.5

세 로그가 모두 맞습니다. 중간에 NAT(Network Address Translation) 가 주소를 바꿨기 때문입니다. 이 구조를 모르면 다음과 같은 실수를 하게 됩니다.

실수결과
웹서버 로그의 공인 IP를 곧바로 "공격자 PC"로 판단실제로는 회사·통신사 NAT 뒤의 수많은 사용자 중 하나일 수 있음
외부 위협 인텔리전스에서 받은 IP로 내부 로그 검색내부 로그에는 사설 IP만 남아 있어 검색 결과 0건
방화벽 NAT 로그 없이 내부 단말 추적공인 IP → 사설 IP 역추적 불가

이번 글은 사설 IP와 공인 IP의 역할, NAT가 주소를 바꾸는 방식, 그 흔적이 어디에 남는지를 다룹니다. 사설·특수 대역의 전체 표는 03. IPv4 주소와 서브넷(CIDR)에 정리했으므로 여기서는 반복하지 않습니다.


2. 핵심 개념

2-1. 사설 IP와 공인 IP

구분사설 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가 두 번 일어나기도 합니다.

2-2. NAT의 종류

종류바뀌는 것대표 용도Linux(netfilter)에서의 이름
SNAT (Source NAT)출발지 IP(와 포트)내부 PC들이 공인 IP 하나로 인터넷 사용SNAT, MASQUERADE
DNAT (Destination NAT)목적지 IP(와 포트)공인 IP:443 → 내부 웹서버 10.0.20.10:8443 포트 포워딩DNAT
PAT / NAPTIP + 포트 조합여러 내부 호스트가 하나의 공인 IP를 공유 (포트로 구분)SNAT/MASQUERADE 시 포트 변환 포함
1:1 Static NATIP만 고정 매핑특정 서버에 전용 공인 IP 부여SNAT + DNAT 조합

MASQUERADE는 SNAT의 일종으로, 변환할 공인 IP를 나가는 인터페이스의 현재 주소로 자동 선택합니다. DHCP로 외부 주소가 바뀌는 환경에 쓰입니다.

2-3. 변환 테이블(연결 추적)

NAT 장비는 "어떤 내부 주소:포트를 어떤 외부 주소:포트로 바꿨는지"를 변환 테이블에 기록해 둡니다. 응답 패킷이 돌아오면 이 테이블을 보고 원래 내부 주소로 되돌립니다. Linux에서는 netfilter의 conntrack(connection tracking) 이 이 역할을 합니다. 즉, NAT는 상태를 기억하는(stateful) 기능이며, 변환 테이블이 사라지면 역추적 근거도 사라집니다.


3. 동작 원리

내부 PC 192.168.10.25가 외부 웹서버 203.0.113.10:443에 접속하고, 방화벽의 공인 IP가 198.51.100.5인 상황입니다.

NAT 변환 시퀀스
그림 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

여기서 관제 관점의 핵심은 세 가지입니다.

  1. 외부에서 보이는 것은 ③의 주소뿐입니다. 웹서버·외부 보안업체는 198.51.100.5만 알 수 있습니다.
  2. 공인 IP → 내부 PC를 되찾으려면 ②의 기록(NAT 로그 또는 세션 로그)이 필요합니다. 여기에는 시각 + 변환된 포트가 반드시 있어야 합니다. 같은 공인 IP를 수백 대가 공유하므로 IP만으로는 구분되지 않습니다.
  3. DNAT는 반대 방향입니다. 외부에서 198.51.100.5:443으로 들어온 요청이 내부 서버 10.0.20.10:8443으로 바뀌므로, 내부 서버 로그의 목적지 포트와 방화벽 정책의 포트가 다를 수 있습니다.

NAT는 IP 헤더의 주소를 바꾸기 때문에 IP·TCP/UDP 체크섬도 다시 계산됩니다. 또한 NAT 뒤의 호스트는 외부에서 먼저 연결을 시작할 수 없으므로(DNAT 설정이 없는 한), "외부에서 내부 PC로 직접 들어온 연결"이 보인다면 포트 포워딩이나 정책 설정을 먼저 확인해야 합니다.


4. 실제 명령어 / 실습

실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu). 인터페이스 이름은 ens33을 예시로 사용합니다(환경에 따라 다름). VMware의 NAT 네트워크 모드를 쓰면 VM 자체가 NAT 뒤에 있으므로, 추가 구성 없이 "내부 주소와 외부에 보이는 주소가 다르다"는 사실을 관찰할 수 있습니다.

4-1. 내 주소가 사설인지 확인

# 인터페이스의 IPv4 주소 확인
ip -4 addr show ens33

# 기본 게이트웨이(= NAT를 수행할 가능성이 있는 장비) 확인
ip route show default

inet 192.168.x.x/24처럼 사설 대역이면, 이 VM이 인터넷으로 나갈 때 어딘가에서 반드시 SNAT가 일어납니다.

4-2. conntrack 도구 설치와 조회

# 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가 동작 중이면 일반적으로 로드되어 있습니다.

4-3. firewalld의 NAT 설정 상태 조회 (조회만)

# 활성 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와 게이트웨이 확인

4-4. 캡처로 "내부 구간 주소" 보기

# 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의 흔적입니다.


5. 결과 확인

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 튜플을 구분해 읽을 수 있다
  • firewalld의 masquerade·포워딩 설정이 의도한 상태인지 확인했다
  • 캡처된 출발지 IP와 외부에 보이는 IP가 다르다는 점을 설명할 수 있다

📷 [실습 화면 삽입] sudo conntrack -L -p tcp --dport 443 출력 — original/reply 튜플 표시


6. 패킷 / 로그 분석

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·프록시 로그로 실제 행위 확인

통보에 출발지 포트가 없으면 같은 시각 같은 목적지로 나간 세션이 여러 개일 수 있어 단정할 수 없습니다. 이때는 "후보 목록"으로 보고하는 것이 정확합니다.


7. 보안관제 관점

흔적이 남는 곳

위치남는 정보
방화벽/UTM 세션·NAT 로그변환 전·후 IP와 포트, 세션 시작·종료 시각 (장비에 따라 NAT 로그를 별도로 켜야 함)
DHCP 서버 로그사설 IP ↔ MAC ↔ 시각 (DHCP 과정은 02. 포트 · 프로토콜 분석 시리즈에서 다룸)
프록시·로드밸런서X-Forwarded-For 헤더로 원래 클라이언트 IP 전달 (단, 클라이언트가 위조 가능하므로 신뢰 구간에서만 사용)
Linux 게이트웨이conntrack (메모리상 정보, 만료되면 사라짐)

한계와 오탐 주의

  • conntrack은 로그가 아니라 현재 상태입니다. 사후 분석을 하려면 방화벽 세션 로그를 SIEM으로 수집해 두어야 합니다.
  • NAT 로그 상관분석은 시각이 생명입니다. 장비 간 시간이 몇 초만 어긋나도 다른 세션과 섞입니다(시간 동기화는 02. 포트 · 프로토콜 분석 시리즈의 17. NTP와 로그 시간 동기화에서 다룸).
  • 같은 공인 IP에서 온 다수의 로그인 실패를 곧바로 "한 명의 공격자"로 판단하면 오탐이 될 수 있습니다. 반대로 공인 IP 기준 임계치 차단은 NAT 뒤 정상 사용자 전체를 차단할 수 있습니다.
  • CGNAT 환경의 외부 IP는 통신사 협조 없이는 개인 단위로 특정되지 않습니다.
  • 방화벽 정책·NAT 규칙 설계 자체는 06. 방화벽 · IDS/IPS 분석 시리즈에서 다룹니다.

8. 핵심 정리

  • 사설 IP(RFC 1918)는 내부에서만 유일하고, 인터넷으로 나갈 때 NAT가 공인 IP로 바꿉니다.
  • SNAT/MASQUERADE는 출발지를, DNAT(포트 포워딩)는 목적지를 바꾸며, 여러 호스트가 공인 IP 하나를 쓸 때는 포트까지 변환(PAT)합니다.
  • 같은 통신도 장비마다 기록된 IP가 다르므로, 로그를 볼 때 "NAT 전 구간인지 후 구간인지"를 먼저 판단해야 합니다.
  • 공인 IP → 내부 단말 역추적에는 시각 + 변환 포트 + NAT 로그 + DHCP 로그가 모두 필요합니다.
  • Linux에서는 conntrack -L의 original/reply 튜플 비대칭으로 변환 여부를 확인할 수 있습니다.
  • 공인 IP 하나 = 사용자 한 명이 아니므로, IP 기준 판단·차단 전에 NAT 가능성을 먼저 고려합니다.

다음 글: 06. ICMP와 ping — 오류 보고 프로토콜 읽는 법

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

0개의 댓글