컴퓨터 구조 운영체제 네트워크 자료구조 알고리즘 데이터베이스 내 학습
network · 13

NAT

공인IP사설IPNAT

집이나 사무실의 컴퓨터, 스마트폰, 노트북은 모두 인터넷에 접속하지만, 그 장치들이 각자 공인 IP 주소를 가지고 있지는 않습니다. 보통 공유기 하나가 통신사에서 받은 공인 IP 주소 하나를 가지고, 안쪽 장치들에는 192.168.0.10 같은 사설 IP 주소를 나눠 줍니다. 사설 주소는 인터넷에서 라우팅되지 않으므로 그대로는 외부 서버와 통신할 수 없는데, 이 둘 사이에서 주소를 바꿔 주는 것이 NAT(Network Address Translation, 네트워크 주소 변환)입니다. NAT 장치는 안에서 밖으로 나가는 패킷의 출발지 주소를 공인 주소로 바꾸고, 밖에서 돌아오는 응답의 목적지를 다시 원래의 사설 주소로 되돌립니다.

여러 내부 장치가 하나의 공인 IP를 함께 쓰려면 주소만 바꿔서는 부족합니다. 같은 공인 IP에서 나가는 연결이 여러 개이면 응답이 어느 장치의 것인지 구분할 수 없기 때문입니다. 그래서 가정 · 사무실의 NAT는 대부분 포트 번호까지 함께 바꾸는 PAT(Port Address Translation, NAPT)로 동작합니다. 이 토픽에서는 주소와 포트가 바뀌는 과정, 변환 표를 이용한 응답 처리와 외부 접속 차단, 외부에서 내부 서버로 접속하게 하는 포트 포워딩을 단계별로 봅니다.

핵심 개념

사설 IP와 공인 IP

사설 IP는 인터넷에서 라우팅되지 않는 내부망용 주소로, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 대역이 RFC 1918에 정해져 있습니다. 공인 IP는 인터넷에서 유일하게 쓰이는 주소입니다.

핵심 개념

NAT

패킷이 지나갈 때 헤더의 IP 주소를 다른 주소로 바꾸는 기술입니다. 내부의 사설 주소를 외부에서 쓰는 공인 주소로 바꿔, 여러 내부 장치가 하나의 공인 IP를 공유하게 합니다.

핵심 개념

PAT (NAPT)

IP 주소와 함께 포트 번호까지 바꾸는 방식입니다. 연결마다 서로 다른 외부 포트를 할당하고 변환 표에 기록해, 하나의 공인 IP로 여러 연결을 구분합니다.

핵심 개념

변환 표 (연결 추적)

"내부 주소:포트 ↔ 외부 포트"의 대응을 기록한 표입니다. 응답이 돌아오면 이 표에서 원래 내부 호스트를 찾아 목적지를 되돌리고, 오래 쓰이지 않으면 항목을 지웁니다.

핵심 개념

포트 포워딩

공인 IP의 특정 포트로 들어오는 패킷을 내부 서버의 주소와 포트로 보내도록 미리 정해 두는 규칙입니다. 외부에서 먼저 시작하는 접속을 받으려면 필요합니다.

핵심 개념

출발지 변환과 목적지 변환

안에서 밖으로 나갈 때 출발지를 바꾸는 것을 SNAT, 밖에서 들어올 때 목적지를 바꾸는 것을 DNAT라고 합니다. PAT는 주로 SNAT이고 포트 포워딩은 DNAT입니다.

주소를 아끼는 기술입니다 — IPv4 주소는 32비트로 약 43억 개뿐이라, 내부에서는 사설 주소를 쓰고 공인 주소는 공유합니다.
포트가 연결을 구분합니다 — 같은 공인 IP에서 나가는 연결을 서로 다른 외부 포트로 구분하므로 내부 호스트가 같은 포트 번호를 써도 충돌하지 않습니다.
안에서 시작한 연결만 표에 남습니다 — 외부에서 먼저 들어오는 패킷은 일반적으로 변환 표에 항목이 없어 버려지고, 받으려면 포트 포워딩 규칙이 필요합니다.
NAT는 보안 장치가 아닙니다 — 외부 접속이 막히는 효과는 부수적이어서, 접근 제어는 방화벽으로 따로 정해야 합니다.
이 시각화에서 확인할 것 — "PAT 변환" 탭에서 주소와 포트가 바뀌는 과정을, "응답과 차단" 탭에서 변환 표의 역할을, "포트 포워딩" 탭에서 외부에서 내부 서버로 접속하는 과정을 STEP으로 확인하세요.

NAT의 배경

1990년대 초 인터넷이 빠르게 커지면서 IPv4 주소가 부족해질 것이라는 우려가 커졌고, 그 대응책 중 하나로 RFC 1631(1994)이 NAT를 제안했습니다. 이후 RFC 2663이 NAT의 용어를 정리했고, RFC 3022가 포트까지 바꾸는 NAPT를 포함한 전통적인 NAT를 설명했습니다. 사설 주소 대역은 RFC 1918이 정합니다. 통신사가 가입자에게 공인 IP를 하나씩 주지 않고 여러 가입자를 하나의 공인 IP 뒤에 두는 방식(CGNAT)을 위한 공유 주소 대역 100.64.0.0/10은 RFC 6598이 정합니다.

숫자로 확인하기

주소와 포트의 크기 — IPv4 주소는 32비트로 2^32 = 4,294,967,296개이고, 포트 번호는 16비트로 0부터 65535까지입니다.
이 시각화의 변환 — 내부 192.168.0.10:51000은 공인 203.0.113.5:40001로, 내부 192.168.0.20:51000은 203.0.113.5:40002로 바뀝니다. 내부 포트는 같지만 외부 포트는 달라 구분됩니다. 이 예시는 포트 변환을 보이려고 항상 새 포트를 주며, 실제 장비는 충돌할 때만 포트를 바꾸기도 합니다.
변환 표의 크기 — 연결 하나당 표 항목이 하나이므로, 동시에 열린 연결이 많을수록 표가 커지고 사용할 수 있는 외부 포트가 줄어듭니다.
예시 주소 — 시각화의 203.0.113.0/24와 198.51.100.0/24는 문서와 예제용으로 따로 정해 둔 주소 대역(RFC 5737)입니다.

자주 하는 오해

NAT는 방화벽이다 — 일반적인 NAT에서 외부에서 먼저 접속할 수 없는 것은 변환 표에 항목이 없기 때문일 뿐입니다. 접근 정책을 정하는 방화벽과는 목적이 다릅니다.
NAT는 IP 주소만 바꾼다 — 많이 쓰는 PAT는 IP 주소와 함께 포트 번호도 바꿉니다. 포트를 바꾸기 때문에 하나의 공인 IP로 여러 연결을 구분합니다.
NAT 뒤의 서버는 외부에서 쓸 수 없다 — 포트 포워딩으로 공인 IP의 특정 포트를 내부 서버에 연결해 두면 외부에서 접속할 수 있습니다.
NAT가 IPv4 주소 부족을 해결했다 — 부족을 크게 완화했지만 근본 해결은 주소 공간이 훨씬 넓은 IPv6입니다. NAT는 종단 간 직접 통신을 어렵게 하는 부작용도 있습니다.

면접에서 이렇게 물어요

면접 질문

NAT는 무엇이고 왜 쓰나요?

사설 IP와 공인 IP를 서로 변환하는 기술입니다. 여러 내부 장치가 하나의 공인 IP를 공유해 IPv4 주소 부족을 완화하고, 내부 주소 체계가 외부에 드러나지 않는 부수 효과도 있습니다.

면접 질문

PAT는 어떻게 여러 연결을 구분하나요?

연결마다 서로 다른 외부 포트를 할당하고 "내부 주소:포트 ↔ 외부 포트"를 변환 표에 기록합니다. 응답이 오면 목적지 포트로 표를 찾아 원래 내부 호스트로 되돌립니다.

면접 질문

NAT 뒤의 서버에 외부에서 접속하려면?

NAT는 내부에서 시작한 연결만 변환 표에 기록하므로, 외부에서 먼저 들어오는 접속은 포트 포워딩으로 공인 IP의 포트와 내부 서버의 주소 · 포트를 미리 연결해 두어야 합니다.

면접 질문

NAT의 단점은 무엇인가요?

연결 추적 때문에 장비에 상태와 부담이 생기고, 외부에서 내부로 직접 연결하기 어려우며, IP 주소를 페이로드에 넣는 일부 프로토콜은 추가 처리가 필요합니다.

실제 시스템에서는

가정용 공유기 — 가정용 공유기의 NAT는 대부분 PAT로 내부 장치들을 하나의 공인 IP에 묶고, 설정 화면에서 포트 포워딩을 지원합니다.
리눅스 — 커널의 netfilter가 NAT를 처리하며, iptables나 nftables로 MASQUERADE와 DNAT 규칙을 설정하고 conntrack으로 연결 추적 표를 볼 수 있습니다.
클라우드 — 사설 서브넷의 인스턴스가 인터넷으로 나갈 때 NAT 게이트웨이 같은 서비스를 거치는 구성이 흔합니다.
컨테이너 — Docker의 기본 브리지 네트워크는 컨테이너의 외부 통신에 NAT를 쓰고, 포트를 공개할 때(-p) 포트 포워딩 규칙을 만듭니다.

함께 보면 좋은 토픽

TCP/IP — IP 주소와 포트 번호가 하는 일을 봅니다.
라우팅 — 패킷이 라우터를 거쳐 전달되는 방식을 봅니다.
DHCP — 내부 장치에 사설 IP가 나눠지는 방식을 봅니다.
VM vs 컨테이너 — 컨테이너 네트워크가 NAT를 쓰는 환경을 봅니다.

참고 자료

리눅스 — 출발지 NAT(MASQUERADE)로 내부망 공유

# 이 장비가 패킷을 전달(라우팅)하도록 켜기
sudo sysctl -w net.ipv4.ip_forward=1

# eth0(외부 쪽)으로 나가는 패킷의 출발지를 eth0의 주소로 바꾸기
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# nat 표의 규칙 확인
sudo iptables -t nat -L -n -v

리눅스를 공유기처럼 쓰려면 먼저 ip_forward로 패킷 전달을 켭니다. nat 표의 POSTROUTING 사슬은 패킷이 나가기 직전에 적용되고, MASQUERADE 대상은 출발지 주소를 나가는 인터페이스(여기서는 eth0)의 현재 주소로 바꿉니다. MASQUERADE는 출발지 주소를 나가는 인터페이스 주소로 바꾸며, 여러 내부 호스트의 포트가 겹치면 포트도 바꿔 PAT처럼 동작합니다. 외부 주소가 DHCP로 바뀌는 환경에서 편리합니다. 주소가 고정이면 SNAT 대상으로 직접 지정할 수도 있습니다. -o eth0 같은 인터페이스 이름은 환경에 맞게 바꿔야 하고, 위 명령은 재부팅하면 사라지므로 영구 설정은 배포판의 방법을 따라야 합니다.

리눅스 — 포트 포워딩(DNAT)과 변환 표 확인

# 공인 쪽 8080 포트로 오는 TCP를 내부 192.168.0.20:80으로 보내기
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 \
    -j DNAT --to-destination 192.168.0.20:80

# 연결 추적 표 보기 (conntrack 도구 필요)
sudo conntrack -L

nat 표의 PREROUTING 사슬은 패킷이 들어오자마자 적용되어, DNAT 대상이 목적지를 내부 서버의 주소와 포트로 바꿉니다. 응답 패킷의 출발지는 커널의 연결 추적이 자동으로 되돌려 주므로 응답 방향 규칙은 따로 쓰지 않습니다. conntrack -L은 커널이 기억하고 있는 연결 목록을 보여 주며, 각 항목에 원래 방향과 응답 방향의 주소 · 포트가 함께 나와 NAT가 어떻게 바꿨는지 확인할 수 있습니다. 포워딩된 패킷이 통과하도록 FORWARD 사슬의 규칙이 막지 않는지도 확인해야 하며, 위 코드는 개념을 보이는 최소 예시입니다.

Python — PAT 변환 표 흉내 내기

class Nat:
    def __init__(self, public_ip, first_port=40001):
        self.public_ip = public_ip
        self.next_port = first_port
        self.out = {}    # (내부 IP, 내부 포트) -> 외부 포트
        self.back = {}   # 외부 포트 -> (내부 IP, 내부 포트)

    def outbound(self, src_ip, src_port):
        key = (src_ip, src_port)
        if key not in self.out:
            self.out[key] = self.next_port
            self.back[self.next_port] = key
            self.next_port += 1
        return self.public_ip, self.out[key]

    def inbound(self, dst_port):
        return self.back.get(dst_port)   # 표에 없으면 None (버림)

nat = Nat("203.0.113.5")
print(nat.outbound("192.168.0.10", 51000))   # ('203.0.113.5', 40001)
print(nat.outbound("192.168.0.20", 51000))   # ('203.0.113.5', 40002)
print(nat.inbound(40001))                    # ('192.168.0.10', 51000)
print(nat.inbound(40009))                    # None

이 클래스는 PAT의 핵심인 변환 표를 딕셔너리 두 개로 흉내 냅니다. outbound는 안에서 밖으로 나가는 연결에 새 외부 포트를 할당하고 표에 기록하며, 이미 있는 연결이면 같은 외부 포트를 다시 씁니다. inbound는 들어오는 패킷의 목적지 포트로 표를 찾아 원래의 내부 주소와 포트를 돌려주고, 표에 없으면 None을 돌려줍니다. 시각화에서 외부의 먼저 시작한 접속이 버려지는 이유입니다. 실제 NAT는 프로토콜별 상태 추적, 항목 만료, 포트 재사용 같은 처리가 더 있으므로 이 코드는 원리만 보이는 최소 예시입니다.

Q1

NAT(Network Address Translation)의 기본 역할은?

집 공유기가 하는 일 중 하나입니다.
NAT는 내부망의 사설 IP를 외부에서 쓰는 공인 IP로 변환합니다. 덕분에 여러 내부 장치가 하나의 공인 IP를 공유하고, IPv4 주소 부족 문제도 완화됩니다.

Q2

PAT(포트 주소 변환, NAPT)의 특징은?

같은 공인 IP를 쓰는 여러 연결을 구분하려면 무엇이 더 필요할까요?
PAT는 내부 호스트마다 서로 다른 외부 포트 번호를 할당해 변환 테이블에 기록합니다. 그래서 하나의 공인 IP로도 여러 내부 호스트의 연결을 구분해 동시에 처리할 수 있습니다.

Q3

NAT 뒤에 있는 내부 서버에 외부에서 접속할 수 있게 하려면?

외부에서 시작하는 연결은 어느 내부 장치로 가야 할지 NAT가 모릅니다.
NAT는 내부에서 시작한 연결에 대해서만 변환 정보를 만들므로, 외부에서 먼저 들어오는 연결은 포트 포워딩 규칙으로 목적지를 미리 지정해야 합니다.