관리 메뉴

피터의 개발이야기

[Network] 21. 여러 집이 하나의 공인 주소를 함께 쓸 수 있을까? 본문

DevOps/Network

[Network] 21. 여러 집이 하나의 공인 주소를 함께 쓸 수 있을까?

기록하는 백엔드개발자 2026. 7. 23. 22:21
반응형

목차: [Network] TCP/IP를 우편 시스템으로 이해하기
TCP/IP를 우편 시스템으로 이해하기 — Part 7. 인터넷의 주소를 함께 쓰고 경계를 지키는 법

ㅁ 들어가며

집 안에는 Phone, Notebook, TV, Game Console처럼 많은 기기가 있다.

각 기기는 서로 다른 IPv4 주소를 사용한다.

Phone       192.168.10.10
Notebook    192.168.10.20
TV          192.168.10.30
Game Console 192.168.10.40

 

그런데 인터넷에서 이 집을 바라보면 여러 연결이 하나의 공인 IPv4 주소에서 온 것처럼 보일 수 있다.

Internet에서 보이는 Source IP
203.0.113.5

 

서로 다른 내부 주소가 어떻게 하나의 외부 주소를 동시에 사용할 수 있을까?

주소만 똑같이 바꾸면 답장이 왔을 때 어느 기기로 돌려줘야 하는지 구분할 수 없다.

203.0.113.5로 답장이 도착
→ Phone의 대화인가?
→ Notebook의 대화인가?
→ TV의 대화인가?

가정용 Router가 흔히 수행하는 기능은 주소만 바꾸는 단순한 NAT가 아니다. Address와 Transport Port를 함께 바꾸고 그 대응 관계를 기억하는 NAPT, 또는 PAT다.

이번 글에서는 Private IPv4 Address, NAT, NAPT/PAT, SNAT, DNAT, Translation Table, Connection Tracking, Port Forwarding, CGNAT를 실제 왕복 Packet으로 추적한다.


ㅁ 모든 기기에 전 세계 고유 주소를 줄 수 없었을까?

IPv4 Address는 32비트다.

2^32 = 4,294,967,296

약 43억 개의 Bit Pattern이 있지만 전부 일반 Host에 자유롭게 배정할 수 있는 것은 아니다. Network 운영과 특수 목적을 위한 범위가 있고, Internet에 연결되는 장비와 서비스는 계속 늘어났다.

IPv4 주소 부족을 완화하기 위해 내부 Network에서는 전 세계적으로 유일하지 않아도 되는 Private Address를 사용할 수 있다.

RFC 1918에서 정의한 범위는 다음과 같다.

10.0.0.0/8
172.16.0.0/12
192.168.0.0/16

서로 다른 집과 회사가 똑같이 192.168.10.10을 사용해도 내부 Network가 분리되어 있으면 충돌하지 않는다.

집 A의 Notebook  192.168.10.10
집 B의 Notebook  192.168.10.10

각자 내부에서는 서로 다른 Network

 

하지만 Private Address는 공용 Internet에서 전역적으로 Route되는 주소로 사용하지 않는다.

내부 Host가 Internet Server와 통신하려면 경계 장비가 외부에서 Route 가능한 주소로 바꾸는 과정이 필요하다.


ㅁ 공인 주소와 사설 주소는 보안 등급일까?

Public Address는 공용 Internet에서 전역적으로 Route할 수 있도록 배정·광고되는 주소를 뜻한다.

Private Address는 제한된 내부 Network에서 재사용하도록 예약한 범위다.

Public / Private
→ Routing Scope의 차이
→ 신뢰도나 암호화 등급의 차이가 아님

 

Public Address가 있다고 누구나 해당 Host에 접속할 수 있는 것은 아니다.

Firewall Policy와 Service Listen 상태가 별도로 허용되어야 한다.

Private Address를 사용한다고 Packet 내용이 자동으로 암호화되거나 내부 Host가 안전해지는 것도 아니다.

 

이 글의 예시에 사용하는 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24는 문서 예시용 주소 범위다.

실제 공인 주소처럼 인터넷 서비스에 사용하기 위한 값은 아니다.


ㅁ NAT는 정확히 무엇을 바꿀까?

Network Address Translation(NAT)은 경계 장비가 IP Packet의 Address를 다른 Address로 바꾸는 기능을 넓게 가리킨다.

가장 단순한 형태는 하나의 내부 주소를 하나의 외부 주소에 대응시키는 1:1 변환이다.

내부 10.0.0.10
↔ 외부 203.0.113.10

Address Pool에서 사용할 외부 주소를 동적으로 배정할 수도 있다.

내부 Host 여러 개
↔ 외부 Address Pool 여러 개

하지만 하나의 공인 IPv4 Address를 여러 내부 Host가 동시에 공유하려면 IP Address만으로는 부족하다.

Transport Port까지 함께 사용해야 한다.


ㅁ NAT와 NAPT, PAT는 같은 말일까?

Network Address and Port Translation(NAPT)은 IP Address와 TCP·UDP Port를 함께 변환한다.

Port Address Translation(PAT) 또는 Port Overload라고 부르기도 한다.

NAT
└─ Address 변환을 가리키는 넓은 표현

NAPT / PAT
└─ Address와 Port를 함께 변환해 다수 연결을 공유

가정용 Router에서 흔히 “NAT를 한다”고 말할 때 실제 동작은 NAPT인 경우가 많다.

용어를 지나치게 엄격히 나누지 않는 제품도 있지만,

여러 Host가 하나의 공인 주소를 어떻게 동시에 쓰는지 설명하려면 Port 변환을 빼놓을 수 없다.


ㅁ 내부 Client 한 대가 HTTPS 연결을 시작하면

Notebook이 외부 Web Server의 443 Port로 TCP 연결을 시작한다고 하자.

Notebook
192.168.10.20:51514

NAT Router의 Public Address
203.0.113.5

Web Server
198.51.100.20:443

 

NAT 전 내부 Packet의 5-Tuple은 다음과 같다.

Protocol        TCP
Source IP       192.168.10.20
Source Port     51514
Destination IP  198.51.100.20
Destination Port 443

 

NAT Router는 외부에서 사용할 Source Port 40001을 배정했다고 하자.

많은 구현은 먼저 원래 Source Port 51514를 그대로 쓰려고 시도하고, 

같은 공인 주소에서 그 Port가 이미 다른 연결에 쓰이는 등 충돌이 있을 때만 40001처럼 다른 Port로 재배정한다. 

이 글에서는 설명을 위해 바뀐 경우를 예로 든다.

변환 전: 192.168.10.20:51514
변환 후: 203.0.113.5:40001

 

외부로 나가는 Packet은 다음처럼 보인다.

TCP 203.0.113.5:40001
→   198.51.100.20:443

 

Destination은 그대로이고 Source Address와 Source Port가 바뀌었다.

이를 Source 기준으로 보면 Source NAT(SNAT)다.

 

여기서는 Address뿐 아니라 Source Port까지 함께 바꾸므로, 앞서 정의한 NAPT/PAT에도 해당한다.

두 이름은 층위가 다르다.

SNAT는 어느 쪽 주소를 바꾸는가(방향)를, NAPT는 Port까지 바꿔 다수 연결을 공유하는가(기법)를 가리킨다.


ㅁ Router는 답장을 위해 무엇을 기억할까?

NAT Router는 변환하면서 대응 관계를 상태로 저장한다.

설명용 Translation Table의 한 행은 다음과 같다.

Protocol 내부 Endpoint 외부에서 보이는 Endpoint Remote Endpoint
TCP 192.168.10.20:51514 203.0.113.5:40001 198.51.100.20:443

 

실제 NAT가 Mapping을 구분하는 범위는 구현과 동작 방식에 따라 다를 수 있다.

Protocol, 내부 Endpoint, Remote Endpoint, Connection State 등이 함께 사용될 수 있다.

핵심은 외부 Tuple을 원래 내부 Tuple로 되돌릴 정보를 기억한다는 점이다.

203.0.113.5:40001로 돌아온 TCP 응답
→ 192.168.10.20:51514로 복원

 

이 상태가 없으면 공인 주소만 보고 어느 내부 Host와 Socket에 답장을 전달할지 알 수 없다.


ㅁ Server의 답장은 어떻게 원래 Notebook으로 돌아갈까?

Web Server는 자신이 본 Source로 응답한다.

TCP 198.51.100.20:443
→   203.0.113.5:40001

 

Packet이 NAT Router에 도착하면 Translation Table을 조회한다.

Protocol TCP
Destination 203.0.113.5:40001

Mapping 발견
→ 내부 192.168.10.20:51514

 

변환된 내부 방향 Packet은 다음과 같다.

TCP 198.51.100.20:443
→   192.168.10.20:51514

 

나갈 때 Source를 바꾼 것이 SNAT였다면, 

돌아올 때는 저장해 둔 대응 관계로 Destination을 원래 내부 Endpoint로 되돌린다. 

방향으로 보면 이쪽은 목적지를 바꾸는 변환(Destination NAT, DNAT에 해당)이다. 

하나의 연결에서 나갈 때와 돌아올 때가 서로 대칭을 이룬다.

 

왕복 흐름을 한 번에 보면 다음과 같다.

Notebook                 NAT Router                   Web Server

192.168.10.20:51514
        ────────────────> 203.0.113.5:40001
                              ───────────────────────> 198.51.100.20:443

                              <─────────────────────── 198.51.100.20:443
        <──────────────── 203.0.113.5:40001
192.168.10.20:51514

 

외부 Server는 원래 Private Address를 보지 않는다.

NAT Router의 Public Address와 변환된 Port를 Client Endpoint로 인식한다.


ㅁ 두 Client가 같은 Source Port를 사용하면 충돌하지 않을까?

Phone과 Notebook이 우연히 같은 Source Port 51514를 사용해 같은 Web Server에 연결한다고 하자.

Phone    192.168.10.10:51514 → 198.51.100.20:443
Notebook 192.168.10.20:51514 → 198.51.100.20:443

 

NAT Router는 외부 Port를 다르게 배정할 수 있다.

내부 Endpoint 외부에서 보이는 Endpoint Remote Endpoint
192.168.10.10:51514 203.0.113.5:40001 198.51.100.20:443
192.168.10.20:51514 203.0.113.5:40002 198.51.100.20:443

 

Server의 응답 Destination Port가 40001이면 Phone으로, 40002이면 Notebook으로 복원한다.

203.0.113.5라는 Address는 공유
40001과 40002라는 Port로 Mapping을 구분

 

NAPT가 하나의 Public Address를 다수의 동시 Flow로 확장하는 핵심 원리다.

NAT가 항상 원래 Source Port를 바꾸는 것은 아니다.

충돌이 없고 정책이 허용하면 같은 Port를 보존할 수 있으며 필요할 때 다른 Port를 선택할 수 있다.


ㅁ Address와 Port를 바꾸면 Checksum은 어떻게 될까?

IPv4 Header의 Source 또는 Destination Address가 바뀌면 IPv4 Header Checksum도 다시 맞아야 한다.

TCP와 0이 아닌 UDP Checksum 계산에는 IP Source와 Destination을 포함한 Pseudo Header가 관여한다.

Port까지 바뀌므로 Transport Checksum도 영향을 받는다.

NAT가 바꾸는 값
├─ IPv4 Source 또는 Destination Address
├─ TCP/UDP Source 또는 Destination Port 가능
├─ IPv4 Header Checksum 갱신
└─ TCP/UDP Checksum 갱신

 

실제 구현은 전체를 처음부터 다시 계산하거나 변경분을 이용해 효율적으로 갱신할 수 있다.

IPv4 UDP에서 Checksum Field가 0이면 Checksum을 사용하지 않는다는 특별한 의미이므로 별도로 처리된다.

NAT는 Packet 겉면만 별도의 표에 기록하는 장치가 아니다. 전달 중인 Packet Header를 실제로 수정한다.

그래서 암호학적으로 Header 변경까지 보호하는 Protocol이나

Payload 안에 Address를 직접 넣는 Application은 NAT와 추가 조정이 필요할 수 있다.


ㅁ Translation Table은 언제 만들어지고 사라질까?

동적인 NAPT Mapping은 영구히 남지 않는다.

TCP에서는 SYN, ACK, FIN, RST 같은 Flag와 Connection State를 관찰해 Mapping의 수명을 관리할 수 있다.

TCP SYN 관찰
→ 새 Mapping 생성

ESTABLISHED Traffic
→ State 갱신

FIN/RST 또는 긴 Idle
→ 일정 조건 후 Mapping 제거

 

UDP에는 TCP Handshake와 FIN이 없다.

NAT는 같은 Tuple의 Packet이 일정 시간 보이지 않으면 UDP Mapping을 만료시키는 식으로 상태를 관리할 수 있다.

UDP Packet 관찰
→ Mapping 생성

Idle Timeout 경과
→ Mapping 제거

 

구체적인 Timeout은 장비, Protocol, Connection State와 정책에 따라 다르다.

Application이 NAT Mapping을 오래 유지하려고 Keepalive를 사용할 수 있지만 지나치게 잦은 Keepalive는 Battery, Traffic, NAT State를 소비한다.


ㅁ NAT Rule과 Connection Tracking은 같은 표일까?

Linux 같은 Stateful NAT 구현을 생각해 보자.

NAT Rule은 어떤 Traffic을 어떤 방식으로 변환할지 정한다.

내부 Prefix에서 외부 Interface로 나가는 Packet
→ 외부 Address로 Source NAT

 

첫 Packet이 Rule과 Connection Tracking을 통해 Mapping을 만들면

같은 Flow의 뒤 Packet과 Return Packet에는 저장된 상태가 일관되게 적용된다.

NAT Rule
→ 변환 정책

Conntrack Entry
→ 현재 Flow의 원래 Tuple, 응답 Tuple, State와 변환 관계

NAT Rule 목록의 Packet Counter만 보고 현재 활성 Mapping을 모두 알 수 있는 것은 아니다.

Linux에서는 환경에 따라 conntrack 도구로 활성 Connection Tracking Entry를 관찰할 수 있다.


ㅁ Port도 유한하다면 무한히 공유할 수 있을까?

TCP와 UDP Port Field는 각각 16비트다.

0부터 65,535까지의 값

모든 값을 동적 변환에 자유롭게 사용하는 것도 아니며 이미 사용 중인 Mapping, 예약 범위와 정책이 있다.

 

하나의 Public Address가 만들 수 있는 동시 Mapping에는 한계가 있다.

내부 Client 수 증가
× Client당 동시 Connection 증가
× 목적지와 Protocol 조합
→ NAT State와 외부 Port 소비 증가

사용 가능한 외부 Port와 Connection Tracking 자원이 부족해

새 Mapping을 만들지 못하는 상황을 Port Exhaustion 또는 NAT Resource Exhaustion이라고 한다.

증상은 기존 연결은 유지되지만 새로운 연결만 간헐적으로 실패하는 모습으로 나타날 수 있다.

장비는 Public Address Pool을 늘리거나 Mapping 재사용 정책, Timeout, Port Block 할당과 Capacity를 조정할 수 있다.

단순히 “Public IP 하나면 내부 Host 수가 무한해진다”는 뜻은 아니다.


ㅁ 외부에서 먼저 연결하면 왜 내부 Host를 찾지 못할까?

외부 Client가 다음 Packet을 보냈다고 하자.

Destination 203.0.113.5:8080

NAT Router에 해당 Port의 기존 Mapping도, 정적인 변환 Rule도 없다.

203.0.113.5:8080
→ 어느 내부 Address와 Port인가?
→ 알 수 없음

동적인 NAPT는 보통 내부에서 먼저 시작한 Flow를 보며 Mapping을 만든다.

외부에서 갑자기 도착한 Packet은 원래 내부 목적지를 복원할 근거가 없다.

 

내부 Server를 외부에 공개하려면 명시적인 정적 Mapping을 만들 수 있다.

Public 203.0.113.5:8443
→ Private 192.168.10.50:443

 

이를 Port Forwarding이라고 흔히 부른다.

외부 Packet의 Destination을 내부 Address와 Port로 바꾸므로 Destination NAT(DNAT)의 한 형태다.

외부 Client → 203.0.113.5:8443
NAT Router  → 192.168.10.50:443으로 DNAT

Port Forwarding Rule이 있어도 Firewall이 Forward Traffic을 허용하고

내부 Server가 Listen하며 Return Route가 성립해야 실제 연결이 된다.


ㅁ SNAT와 DNAT는 방향 이름일까?

SNAT와 DNAT는 단순히 “밖으로 나감”과 “안으로 들어옴”의 이름이라기보다 어느 Address Field를 바꾸는지에 초점을 둔다.

SNAT
→ Source Address를 변환

DNAT
→ Destination Address를 변환

일반적인 Internet Access에서는 내부 Packet의 Source를 Public Address로 바꾸는 SNAT가 사용된다.

Port Forwarding이나 Load Balancing에서는 외부 Packet의 Destination을 내부 Server로 바꾸는 DNAT가 사용될 수 있다.

Return Traffic에는 저장된 State에 따라 반대 변환이 적용된다.

Forward 방향 SNAT
↔ Return 방향에서 Destination 복원

Forward 방향 DNAT
↔ Return 방향에서 Source 복원

Packet 방향만 보고 SNAT와 DNAT를 외우기보다 바뀌는 Header Field를 확인하는 편이 정확하다.


ㅁ 내부 Host가 Public Address로 자기 Server에 접속하면

내부 DNS나 설정이 Server의 Public Address 203.0.113.5:8443을 알려 준다고 하자.

내부 Client가 그 주소로 접속하면 Packet이 NAT Router에 갔다가 다시 내부 Server로 돌아와야 한다.

192.168.10.20
→ 203.0.113.5:8443
→ NAT Router
→ 192.168.10.50:443

이를 Hairpin NAT, NAT Loopback, NAT Reflection이라고 부른다.

장비가 해당 동작을 지원하고 DNAT와 Return Path를 일관되게 처리해야 한다.

지원하지 않으면 외부에서는 Public Address로 접속되지만 같은 내부 Network에서는 실패할 수 있다.

내부 DNS가 내부 Address를 따로 응답하는 Split DNS도 한 가지 설계 방법이다.


ㅁ NAT가 있으면 Firewall은 필요 없을까?

동적 NAPT는 Mapping이 없는 외부 Packet을 어느 내부 Host로 보낼지 모른다.

이 특성 때문에 외부에서 먼저 시작한 연결이 자연스럽게 제한되는 경우가 많다.

하지만 NAT와 Firewall은 목적이 다르다.

NAT
→ Address와 Port를 변환

Firewall
→ Policy에 따라 Traffic을 허용하거나 차단

NAT Rule이 곧 보안 허용 Rule인 것도 아니고,

주소를 변환하지 않는 Routed Network에서도 Stateful Firewall을 사용할 수 있다.

반대로 잘못된 Port Forwarding과 넓은 Firewall 허용 Rule이 있으면 NAT 뒤의 Service도 외부에 노출될 수 있다.

NAT가 있으니 안전하다  (X)
Private Address이니 신뢰해도 된다  (X)

다음 글에서는 Firewall이 Packet의 어떤 정보를 보고 별도의 허용 결정을 내리는지 살펴본다.


ㅁ NAT가 내용을 숨겨 주는 암호화일까?

외부 Server는 내부 Private Address 대신 공유 Public Address를 본다.

그렇다고 Packet 내용이 암호화되는 것은 아니다.

NAT가 숨기는 것
→ 외부 Packet Header에서 원래 Private Address

NAT가 숨기지 않는 것
→ 암호화되지 않은 Application Payload
→ 접속한 Destination
→ Traffic 크기와 시간
→ Cookie와 계정 같은 Application 식별자

하나의 Public Address를 공유한다고 사용자들이 서로 암호학적으로 익명화되는 것도 아니다.

내용의 기밀성, 상대 인증과 무결성은 TLS 같은 별도 보안 Protocol이 맡는다.


ㅁ NAT는 End-to-End 모델을 어떻게 바꿨을까?

원래 IP의 기본 모델에서는 두 Endpoint가 서로 Route 가능한 Address를 사용해 직접 Packet을 주고받는 모습을 생각할 수 있다.

NAPT가 중간에 들어오면 Address와 Port가 경계에서 바뀌고 Mapping State가 생긴다.

End Host ── Stateful NAT ── End Host
              │
              └─ Translation State 필요

이 변화는 여러 문제를 만든다.

  • 외부 Peer가 내부 Host로 먼저 연결하기 어렵다.
  • Return Traffic이 Mapping을 가진 NAT로 돌아와야 한다.
  • Mapping Timeout보다 긴 Idle Connection은 끊길 수 있다.
  • Payload 안에 IP와 Port를 기록하는 Protocol은 Header 변환만으로 동작하지 않을 수 있다.
  • Fragment의 뒤 조각에는 Transport Port가 없어 상태 연결이 복잡하다.
  • NAT가 여러 겹이면 어느 경계에서 Mapping이 만들어졌는지 추적하기 어렵다.

일부 Protocol은 Application Layer Gateway(ALG), Port Mapping, STUN, TURN, ICE 같은

보조 기술로 NAT Traversal을 시도한다.

NAT는 IPv4 주소 공유를 가능하게 했지만 중간 Network가 End-to-End 대화 상태를 기억하게 만들었다.


ㅁ CGNAT를 지나면 무엇이 하나 더 생길까?

CGNAT(Carrier-Grade NAT)인터넷 서비스 제공업체(ISP)가 부족한 공인 IPv4 주소를 아끼기 위해,

여러 명의 사용자에게 하나의 공인 IP를 공유하게 만드는 대규모 네트워크 주소 변환 기술이다. 

가정이나 사무실에서 공유기가 사설 IP를 할당하듯, 통신사(ISP)가 한 번 더 사설 IP를 할당하여 인터넷으로 내보낸다.

 

가정 Router가 한 번 NAT하고 Internet Service Provider가 다시 NAT할 수 있다.

Home Private Address
        ↓ Home NAT
ISP Shared Address
        ↓ Carrier-Grade NAT
Public Internet Address

 

이를 Carrier-Grade NAT(CGNAT) 또는 Large Scale NAT라고 부른다.

CGNAT 내부에서 사용할 수 있도록 100.64.0.0/10 Shared Address Space가 예약되어 있다.

이 범위는 RFC 1918 Private Address 세 범위에 포함되지 않으며 일반 Public Internet용 주소도 아니다.

 

CGNAT 환경에서는 다음 제약이 커질 수 있다.

  • 사용자가 ISP NAT의 Port Forwarding을 직접 설정하기 어렵다.
  • 하나의 Public Address를 더 많은 가입자가 공유해 Port 자원이 제한될 수 있다.
  • 장애와 Abuse 추적에는 Public IP뿐 아니라 Source Port와 정확한 시간이 함께 필요하다.
  • VPN, Game, P2P와 Inbound Service가 NAT Traversal에 더 의존한다.

Public Address만 기록하면 어느 가입자의 어느 Mapping인지 구분하지 못할 수 있다.


ㅁ IPv6에도 주소 공유 NAT가 꼭 필요할까?

IPv6는 매우 큰 Address Space를 제공하므로 IPv4 주소 부족 때문에

여러 Host가 하나의 주소와 Port를 공유해야 했던 이유가 약해진다.

각 Host가 전역적으로 Route 가능한 IPv6 Address를 가질 수 있다.

그렇다고 Firewall이 불필요해지는 것은 아니다.

Address 공유 필요 감소
≠ 모든 Inbound Traffic 허용

Stateful Firewall은 NAT 없이도 내부에서 시작한 Flow의 Return Traffic을 허용하고

외부의 새 연결을 Policy로 제한할 수 있다.

NAT66 같은 IPv6 Address 변환도 존재하지만 IPv4 주소 고갈 완화를 위한 NAPT와 같은 필요성으로 이해하면 안 된다.

Addressing, Routing, Security Policy는 서로 다른 문제다.


ㅁ 우편 비유를 네트워크 용어로 바꾸면

비유를 실제 Header와 State로 다시 연결해 보자.

우편 이야기 실제 용어 정확한 의미
건물 안에서만 사용하는 호수 Private IPv4 Address 내부 Network에서 재사용하는 RFC 1918 주소
외부 우편망에서 보이는 대표 주소 Public IPv4 Address 공용 Internet에서 Route 가능한 주소
봉투의 주소를 대표 주소로 교체 NAT IP Source 또는 Destination Address 변환
대표 주소와 접수 번호를 함께 교체 NAPT / PAT Address와 TCP·UDP Port를 함께 변환
발신 주소를 외부 주소로 변경 SNAT Packet의 Source Address 변환
수신 주소를 내부 Server로 변경 DNAT Packet의 Destination Address 변환
원래 세대와 외부 접수 번호의 대응표 Translation Table 외부 Tuple을 내부 Tuple로 복원할 Mapping State
외부 창구 번호를 내부 Server에 고정 연결 Port Forwarding Public Address와 Port를 Private Endpoint로 DNAT
답장이 같은 번역소로 돌아옴 Path Symmetry Mapping State가 있는 NAT가 Return Traffic 처리
외부 접수 번호가 모두 사용됨 Port Exhaustion 새 동적 Mapping에 사용할 Port나 State 부족
통신사가 한 번 더 대표 주소로 변환 CGNAT 다수 가입자가 ISP의 Public Address Pool을 공유
같은 건물에서 외부 주소로 되돌아 접속 Hairpin NAT 내부 Client가 NAT의 Public Endpoint를 통해 내부 Server 접속

 

핵심 왕복을 한 번 더 정리하면 다음과 같다.

내부에서 나감
192.168.10.20:51514
        ↓ SNAT + Port Translation
203.0.113.5:40001
        ↓
198.51.100.20:443

외부에서 돌아옴
198.51.100.20:443
        ↓
203.0.113.5:40001
        ↓ Translation State 조회
192.168.10.20:51514

ㅁ Packet Capture에서 무엇을 비교할까?

NAT 장비의 내부와 외부 Interface를 동시에 Capture하면 같은 Flow의 변환 전후를 비교할 수 있다.

Inside Capture
192.168.10.20:51514 → 198.51.100.20:443

Outside Capture
203.0.113.5:40001 → 198.51.100.20:443

확인할 Field는 다음과 같다.

ip.src
ip.dst
tcp.srcport 또는 udp.srcport
tcp.dstport 또는 udp.dstport
ip.checksum
tcp.checksum 또는 udp.checksum

Wireshark의 tcp.stream은 하나의 Capture 안에서 관련 TCP Packet을 따라가는 데 유용하지만

NAT 양쪽 Capture를 별도로 열면 같은 End-to-End 대화가 서로 다른 Tuple로 보일 수 있다.

양쪽 Capture의 시간, TCP Sequence Number, Flag와 Payload 길이를 함께 비교한다.

Router에서 any Interface로 Capture하면 같은 Packet이 변환 전후 Interface에서 두 번 보일 수 있다.

이를 Packet 복제로 오해하지 않고 Capture Interface 정보와 Tuple을 확인한다.


ㅁ 격리된 Linux 환경에서 NAT를 관찰해 보기

다음 실습은 ip, iptables, tcpdump, nc가 있는 개인 Linux VM에서 수행한다.

Documentation Address와 Network Namespace만 사용하므로 실제 Network의 Address나 Firewall을 바꾸지 않는다.

nat-client                nat-router                 nat-server
10.21.0.2 ───────── 10.21.0.1 | 198.51.100.1 ───── 198.51.100.2

 

Namespace와 가상 Link를 만든다.

sudo ip netns add nat-client
sudo ip netns add nat-router
sudo ip netns add nat-server

sudo ip link add veth-nc type veth peer name veth-nri
sudo ip link add veth-nro type veth peer name veth-ns

sudo ip link set veth-nc netns nat-client
sudo ip link set veth-nri netns nat-router
sudo ip link set veth-nro netns nat-router
sudo ip link set veth-ns netns nat-server

 

Address와 Interface를 설정한다.

sudo ip -n nat-client addr add 10.21.0.2/24 dev veth-nc
sudo ip -n nat-router addr add 10.21.0.1/24 dev veth-nri
sudo ip -n nat-router addr add 198.51.100.1/24 dev veth-nro
sudo ip -n nat-server addr add 198.51.100.2/24 dev veth-ns

sudo ip -n nat-client link set lo up
sudo ip -n nat-router link set lo up
sudo ip -n nat-server link set lo up
sudo ip -n nat-client link set veth-nc up
sudo ip -n nat-router link set veth-nri up
sudo ip -n nat-router link set veth-nro up
sudo ip -n nat-server link set veth-ns up

 

Route와 IPv4 Forwarding을 설정한다.

sudo ip -n nat-client route add default via 10.21.0.1
sudo ip -n nat-server route add default via 198.51.100.1
sudo ip netns exec nat-router \
  sysctl -w net.ipv4.ip_forward=1

 

내부 Prefix에서 외부 Interface로 나가는 Traffic에 MASQUERADE를 적용한다.

sudo ip netns exec nat-router \
  iptables -t nat -A POSTROUTING \
  -s 10.21.0.0/24 -o veth-nro -j MASQUERADE

 

Router Capture Terminal에서 변환 전후를 함께 저장한다.

sudo ip netns exec nat-router \
  tcpdump -n -vv -i any -s 0 -w /tmp/nat-translation.pcap \
  'tcp port 8080 or tcp port 18080'

 

Server Terminal에서 Listen한다.

sudo ip netns exec nat-server nc -l 8080

 

Client Terminal에서 연결하고 짧은 문장을 입력한다.

sudo ip netns exec nat-client nc 198.51.100.2 8080

 

Capture에서 다음 두 Source를 비교한다.

Router Inside Interface : 10.21.0.2:<client-port>
Router Outside Interface: 198.51.100.1:<translated-port>

 

원래 Port를 그대로 유지할 수도 있으므로 항상 Port가 달라질 것이라고 가정하지 않는다.

NAT Rule Counter를 확인한다.

sudo ip netns exec nat-router \
  iptables -t nat -L POSTROUTING -n -v

 

conntrack 도구가 설치되어 있다면 활성 Flow의 원래 Tuple과 응답 Tuple을 확인한다.

sudo ip netns exec nat-router conntrack -L -p tcp

NAT Rule 목록과 Conntrack Entry가 서로 다른 정보를 보여 주는지 비교한다.


ㅁ 같은 환경에서 Port Forwarding을 관찰해 보기

이번에는 외부 nat-server가 NAT Router의 18080 Port로 연결하면 내부 nat-client의 8080 Port로 전달되게 한다.

DNAT Rule을 추가한다.

sudo ip netns exec nat-router \
  iptables -t nat -A PREROUTING \
  -i veth-nro -p tcp --dport 18080 \
  -j DNAT --to-destination 10.21.0.2:8080

 

내부 Client Terminal에서 Server처럼 Listen한다.

sudo ip netns exec nat-client nc -l 8080

 

외부 Terminal에서 NAT Router의 외부 Address로 연결한다.

sudo ip netns exec nat-server nc 198.51.100.1 18080

 

Capture에서 Destination이 어떻게 바뀌는지 확인한다.

변환 전 Destination: 198.51.100.1:18080
변환 후 Destination: 10.21.0.2:8080

 

실제 운영 환경에서는 DNAT뿐 아니라 Forward Chain의 Firewall 허용 Rule도 필요할 수 있다.

이 Namespace는 기본 Policy가 ACCEPT라는 전제의 관찰용 구성이다.

실습을 마치면 Namespace를 삭제한다. 내부 NAT Rule, Conntrack State와 가상 Interface도 함께 제거된다.

sudo ip netns del nat-client
sudo ip netns del nat-router
sudo ip netns del nat-server

실제 Host의 Firewall이나 NAT Rule을 실습용으로 바꾸지 않는다.


ㅁ 핵심 정리

  • RFC 1918 Private IPv4 범위는 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16이다.
  • Public과 Private은 Routing Scope의 차이이며 보안 등급이나 암호화 여부가 아니다.
  • NAT는 IP Address 변환을 넓게 가리키고 NAPT/PAT는 Address와 TCP·UDP Port를 함께 변환한다.
  • 가정용 Router가 하나의 Public Address를 여러 Host에 공유할 때 실제 핵심은 Port Mapping이다.
  • Translation Table과 Connection Tracking State는 외부 Tuple을 원래 내부 Tuple로 복원한다.
  • NAT는 Address와 Port 변경에 맞춰 IPv4와 TCP·UDP Checksum도 갱신해야 한다.
  • Dynamic Mapping은 TCP State나 UDP Idle Timeout에 따라 생성되고 만료될 수 있다.
  • SNAT는 Source Address를, DNAT는 Destination Address를 바꾸며 Return Traffic에는 State에 따른 역변환이 적용된다.
  • Port Forwarding은 Public Endpoint를 내부 Server에 연결하는 정적 DNAT의 한 형태다.
  • NAT의 외부 Port와 Connection Tracking 자원은 유한하므로 Port Exhaustion이 생길 수 있다.
  • NAT는 주소를 변환하고 Firewall은 Policy로 허용 여부를 결정하므로 같은 기능이 아니다.
  • CGNAT는 ISP 경계에서 가입자들이 Public Address를 다시 공유하며 100.64.0.0/10 Shared Address를 사용할 수 있다.
  • NAT는 Payload를 암호화하거나 사용자를 익명화하지 않으며 End-to-End 연결에 Mapping State와 Traversal 문제를 추가한다.
  • IPv6에서 Address 공유 필요가 줄어도 Stateful Firewall Policy는 별도로 필요하다.

 

핵심 용어: IPv4 Address Exhaustion, RFC 1918, Private Address, Public Address, Network Address Translation, NAT, Network Address and Port Translation, NAPT, Port Address Translation, PAT, SNAT, DNAT, Translation Table, Connection Tracking, Conntrack, Port Mapping, Port Forwarding, MASQUERADE, Hairpin NAT, Port Exhaustion, Carrier-Grade NAT, CGNAT, 100.64.0.0/10, NAT Traversal, End-to-End Principle

 

여러 Host가 하나의 공인 IPv4 주소를 공유할 수 있는 이유는 대표 주소 하나만 붙였기 때문이 아니다.
외부 Port까지 나누어 쓰고, 그 번호가 어느 내부 Socket의 대화인지 Stateful Translation Table에 기억하기 때문이다.


ㅁ 다음 이야기

NAT Router는 주소와 Port의 변환 관계를 기억한다.

하지만 Mapping이 있다는 사실과 Packet을 보안 정책상 허용해야 한다는 판단은 같은 문제가 아니다.

외부에서 온 새 연결과 내부 요청의 정상 응답은 어떻게 구분할까? Source Address와 Destination Port만 보면 충분할까?

다음 글에서는 「방화벽은 편지의 무엇을 보고 문을 열어줄까?」라는 질문을 통해 Stateless ACL, Stateful Firewall, 5-Tuple, Connection State, Default Deny와 최소 권한 원칙을 살펴본다.

반응형
Comments