네트워크 주소 변환(Network Address Translation, NAT)은 라우터를 지나는 IP 패킷의 출발지·목적지 주소와 TCP/UDP 포트를 고쳐 쓰는 기술이다. 패킷이 바뀌므로 IP 와 TCP/UDP 체크섬도 다시 계산해 넣는다. 대개는 사설 대역(RFC 1918) 호스트 여러 대가 공인 IP 하나로 인터넷에 나가기 위해 쓴다.
리눅스 서버를 NAT 게이트웨이로 쓰면 인터페이스 두 개(외부·내부) 사이에서 패킷을 중계하며 나가는 패킷의 출발지를 외부 인터페이스 주소로 바꾼다(MASQUERADE / SNAT). 되돌아오는 응답은 연결 추적(conntrack) 표를 보고 원래 내부 주소로 되돌려 준다. NAT 는 호스트 간 통신을 복잡하게 만들고 — 외부에서 내부로 먼저 연결할 수 없다 — 변환 비용만큼 성능에도 영향을 준다.
내부 호스트가 한 번 매핑된 외부 (주소, 포트) 를 누가 다시 쓸 수 있느냐로 나눈다. P2P·VoIP·게임처럼 외부에서 들어오는 연결이 필요한 응용에서 차이가 난다.
| 종류 | 동작 | 개념도 |
|---|---|---|
| Full cone NAT (one-to-one) | 내부 (A:p) 가 외부 (X:q) 로 매핑되면 어떤 외부 호스트라도 X:q 로 보내 A 에 닿는다 |
![]() |
| Symmetric NAT | 목적지마다 다른 외부 포트를 쓴다. A 가 먼저 보낸 상대만 그 포트로 답할 수 있다. 가장 제한적 | ![]() |
| Port-restricted cone NAT | A 가 (B:r) 로 보낸 적이 있어야 B:r 에서 온 패킷만 통과 |
![]() |
| (Address-)restricted cone NAT | A 가 B 로 보낸 적이 있으면 B 의 어느 포트에서 오든 통과 | ![]() |
리눅스 netfilter 의 MASQUERADE 는 포트 충돌이 없는 한 같은 내부 (주소, 포트) 에 같은 외부 포트를 유지하며, 통과는 conntrack 항목(목적지 주소·포트까지 포함)이 있을 때만 허용하므로 실무에서는 port-restricted cone 에 가깝게 동작한다.
iproute2 와 nftables(nft) 또는 iptables. 어느 것을 쓸지는 iptables · nftables 를 참고한다. 아래는 두 가지를 모두 적는다 [ 외부 장비 ] [ NAT gateway - Linux ] [ 내부 장비 ]
10.12.13.14 192.168.0.1 ~ .253
| 외부 인터페이스 eth0 : 10.11.12.13 |
+------------------ 내부 인터페이스 eth1 : 192.168.0.254 -------- +
net.ipv4.ip_forward = 1
POSTROUTING -o eth0 -j MASQUERADE
가운데 리눅스 서버가 두 인터페이스 사이에서 패킷을 중계한다. 같은 장비이므로 10.11.12.13 이나 192.168.0.254 어느 쪽으로 접속해서 작업해도 된다. 아래 예에서 외부 = eth0, 내부 = eth1 이다. 실제 인터페이스 이름은 ip -br addr 로 확인해 바꿔 넣는다.
커널은 기본으로 인터페이스 사이의 패킷을 중계하지 않는다. net.ipv4.ip_forward 를 1 로 바꾼다[1].
# 즉시 적용 (재부팅하면 사라진다)
sysctl -w net.ipv4.ip_forward=1
# 영구 적용
echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/90-ip-forward.conf
sysctl --system
# 확인
sysctl net.ipv4.ip_forward
/etc/sysctl.conf 에 net.ipv4.ip_forward = 0 이 이미 있으면 그 줄을 1 로 고치거나 지운다 — sysctl.d 보다 나중에 읽히므로 값을 덮는다.
현행 배포판(RHEL 8+, Debian 10+, Ubuntu 20.10+)의 기본 도구다[2].
# nat 테이블과 postrouting 체인
nft add table ip nat
nft 'add chain ip nat postrouting { type nat hook postrouting priority 100; }'
# 외부 인터페이스로 나가는 패킷의 출발지를 그 인터페이스 주소로
nft add rule ip nat postrouting oifname "eth0" masquerade
# (선택) 포워딩 제한 — 내부에서 시작한 연결과 그 응답만 중계
nft add table ip filter
nft 'add chain ip filter forward { type filter hook forward priority 0; policy drop; }'
nft add rule ip filter forward iifname "eth1" oifname "eth0" accept
nft add rule ip filter forward iifname "eth0" oifname "eth1" ct state established,related accept
# 확인
nft list ruleset
외부 주소가 고정이면 masquerade 대신 snat to 10.11.12.13 을 써도 된다. MASQUERADE 는 매 패킷마다 인터페이스 주소를 읽으므로 DHCP·PPPoE 처럼 주소가 바뀌는 회선에 맞고, SNAT 는 주소가 고정일 때 조금 더 가볍다.
# RHEL 계열
nft list ruleset > /etc/sysconfig/nftables.conf
systemctl enable --now nftables
# Debian · Ubuntu
nft list ruleset > /etc/nftables.conf
systemctl enable --now nftables
같은 내용을 iptables 로 적은 것이다. 최근 배포판의 iptables 는 iptables-nft 이므로 결과는 같은 nf_tables 백엔드에 들어간다.
# forward chain 초기화, 기본 정책 DROP
iptables -F FORWARD
iptables -P FORWARD DROP
# 내부 → 외부 는 허용, 외부 → 내부 는 응답만 허용
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 외부 인터페이스로 나가는 패킷을 마스커레이드
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables-save > /etc/iptables.rules
cat /etc/iptables.rules
저장 파일은 다음과 같은 모양이다 (카운터 값은 환경마다 다르다).
# Generated by iptables-save
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -i eth1 -o eth0 -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
COMMIT
부팅 때 되살리려면 배포판의 저장 서비스(iptables-services · iptables-persistent)를 쓰거나, 다음 스크립트를 rc.local 이나 systemd 유닛에서 실행한다.
#!/bin/bash
/sbin/iptables-restore < /etc/iptables.rules
192.168.0.1 ~ .253)의 기본 게이트웨이가 192.168.0.254 인지 확인한다.10.12.13.14 로 ping 또는 curl 이 되면 정상이다.# conntrack 표 (conntrack-tools 패키지)
conntrack -L | grep 192.168.0.
# 규칙에 카운터가 올라가는지
nft list ruleset
iptables -t nat -L POSTROUTING -n -v
내부에서 외부로 나가지 않으면 순서대로 ip_forward 값 → FORWARD 체인 정책 → POSTROUTING 규칙 → 외부 인터페이스 이름을 확인한다. 외부 장비가 응답은 하는데 돌아오지 않으면 firewalld 나 ufw 가 FORWARD 를 막고 있는 경우가 많다.
Linux kernel ip-sysctl.txt — ip_forward — 2026-09-20 확인. https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt ↩︎
nftables wiki "Performing Network Address Translation (NAT)" — masquerade 는 postrouting 훅의 nat 체인에서만 동작 — 2026-09-20 확인. https://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT) ↩︎