외부에서는 5.6.7.8:8080으로 접속했는데 내부 웹 서버에는 아무 요청도 도착하지 않습니다. 포트 포워딩 규칙은 넣었지만 IP forwarding과 FORWARD 체인을 빠뜨렸습니다.
NAT 장애는 한 줄 규칙 문제가 아니라 패킷이 변환되고 전달되는 전체 경로 문제입니다.
NAT와 포트 포워딩 원리
인터넷 공유기 뒤에 있는 내 PC가 어떻게 유튜브를 볼 수 있을까요? 내부 서버를 외부에서 접속 가능하게 만들려면 무엇을 설정해야 할까요? 이 모든 것의 핵심은 **NAT(Network Address Translation)**입니다. 이 챕터에서는 SNAT과 DNAT의 원리를 이해하고, iptables를 사용하여 실제 포트 포워딩을 구성합니다.
- 1NAT(Network Address Translation)의 필요성과 사설 IP 대역(RFC 1918) 개념을 설명할 수 있다
- 2SNAT로 내부 사설 IP를 공인 IP로 변환해 외부 인터넷 통신을 허용할 수 있다
- 3DNAT로 외부 요청의 목적지 IP/포트를 내부 서버로 변환하는 포트 포워딩을 구성할 수 있다
- 4iptables nat 테이블의 PREROUTING / POSTROUTING 체인 역할과 적용 순서를 이해할 수 있다
- 5Masquerade와 SNAT의 차이를 알고 동적 IP 환경에 대응할 수 있다
- 6net.ipv4.ip_forward 커널 파라미터를 설정하고 iptables 규칙을 영구 저장할 수 있다
iptables --versionsudo iptables -t nat -L -n -vsysctl net.ipv4.ip_forward/etc/sysctl.conf에 net.ipv4.ip_forward=1을 추가한 뒤 sudo sysctl -p 로 적용합니다. 규칙 영구 저장은 iptables-save > /etc/iptables/rules.v4를 사용하세요.
NAT 원리 이해
SNAT — 내부에서 외부로 나가는 주소 변환
사무실 내부망 서버(192.168.x.x)에서 인터넷 통신이 됩니다. 그런데 사설 IP는 라우팅이 안 되는 주소입니다. 어떻게 인터넷에 나갔다 돌아오는 걸까요? NAT이 주소를 어떻게 변환하는지 이해하지 못하면 클라우드 VPC에서 NAT Gateway가 왜 필요한지, 포트 포워딩이 어떤 원리로 동작하는지 납득하기 어렵습니다.
확대
NAT가 필요한 이유
IPv4 주소 공간(약 43억 개)은 전 세계 기기 수에 비해 턱없이 부족합니다. 이 문제를 해결하기 위해 사설 IP 대역을 내부에서 사용하고, 게이트웨이에서 공인 IP로 변환합니다.
사설 IP 대역 (RFC 1918):
세 가지 대역이 내부 네트워크에서 사용하도록 예약되어 있습니다. 이 주소들은 인터넷에서 라우팅되지 않으므로 중복 사용해도 충돌이 없습니다.
10.0.0.0/8 (10.x.x.x)
172.16.0.0/12 (172.16.x.x ~ 172.31.x.x)
192.168.0.0/16 (192.168.x.x)
SNAT 동작 흐름
SNAT(Source NAT)은 패킷의 출발지 IP 주소를 변환합니다.
확대
NAT 테이블 (연결 추적):
게이트웨이는 응답 패킷이 돌아왔을 때 어느 내부 호스트로 전달해야 하는지 알기 위해 연결 추적 테이블을 유지합니다. 아래는 두 개의 연결이 동시에 진행될 때 테이블이 어떻게 생겼는지 보여줍니다.
게이트웨이 NAT 추적 테이블:
내부 IP:포트 공인 IP:포트 목적지
10.0.0.10:54321 5.6.7.8:40001 1.2.3.4:80
10.0.0.11:60000 5.6.7.8:40002 8.8.8.8:53
Masquerade — 동적 IP 환경의 SNAT
공인 IP가 고정이면 SNAT에서 --to-source 5.6.7.8처럼 명시합니다. 하지만 DHCP나 PPPoE로 IP가 동적 할당된다면 Masquerade를 사용합니다.
# 실습 디렉토리 준비
mkdir -p /tmp/networking/part2/exam_10 && cd /tmp/networking/part2/exam_10
# SNAT (고정 공인 IP)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 \
-j SNAT --to-source 5.6.7.8
# Masquerade (동적 IP — 가정용 공유기, PPPoE)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o ppp0 \
-j MASQUERADE
- MASQUERADE 룰 확인—iptables -t nat -L POSTROUTING -v 출력에서 MASQUERADE target이 있고 pkts 카운터가 0이 아니면 트래픽이 실제로 NAT를 통과하는 중 — pkts가 계속 0이면 패킷이 해당 체인에 도달하지 않음
- DNAT 목적지 주소 확인—iptables -t nat -L PREROUTING 출력에서 DNAT to: 뒤에 내부 서버 IP:포트가 정확히 기재됐는지 확인 — to:192.168.1.10:80 처럼 IP와 포트가 모두 일치해야 포워딩 동작
- 포트 LISTEN 여부 교차 확인—ss -tlnp로 대상 포트가 LISTEN 상태인지 확인 — DNAT 룰이 있어도 목적지 서버에서 해당 포트가 열려 있지 않으면 연결 거부됨
Masquerade는 ppp0, eth0 등 나가는 인터페이스의 현재 IP를 자동으로 source로 사용합니다.
DNAT와 포트 포워딩 — 외부에서 내부로
사설 IP를 가진 내부 서버를 외부에 공개해야 합니다. 공인 IP는 게이트웨이 한 개뿐이고, 포트 8080으로 오는 요청을 내부의 192.168.1.10:80 서버로 보내야 합니다. 이게 포트 포워딩의 전형적인 사례입니다. DNAT가 어떻게 목적지 주소를 바꾸는지 이해해야 iptables 규칙을 직접 작성하거나 설정 오류를 디버깅할 수 있습니다.
확대
DNAT 동작 흐름
DNAT(Destination NAT)은 패킷의 목적지 IP/포트를 변환합니다. 포트 포워딩이 대표적인 DNAT 활용 사례입니다.
확대
iptables 처리 흐름 전체
iptables에는 여러 테이블과 체인이 있습니다. NAT는 nat 테이블에서 처리됩니다.
확대
DNAT 설정의 핵심 요소
iptables -t nat -A PREROUTING \
-p tcp \ # 프로토콜 (tcp/udp)
--dport 8080 \ # 외부에서 접속하는 포트
-j DNAT \ # 액션: Destination NAT
--to-destination 10.0.0.2:80 # 내부 서버 IP:포트
반드시 필요한 추가 설정: ip_forward가 비활성화되면 NAT 규칙이 있어도 포워딩이 안 됩니다.
이 명령은 시스템 설정 파일을 변경합니다. 기존 파일 백업과 적용 후 검증 방법을 준비하지 않으면 재부팅이나 서비스 재시작 때 장애가 반복될 수 있습니다.
# ip_forward 활성화 (없으면 DNAT 후 패킷이 드랍됨!)
echo 1 > /proc/sys/net/ipv4/ip_forward
# 또는 영구 설정
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
NAT가 주소를 바꾸는 법 — SNAT/DNAT와 conntrack
포워딩 패킷이 iptables 체인을 지나는 순서 — DNAT부터 응답 역변환까지
SNAT과 DNAT를 따로 배웠지만, 실제 포트 포워딩 한 건에서는 두 변환과 conntrack이 한 패킷의 여정 위에서 순서대로 맞물립니다. 외부 요청이 게이트웨이에 도착해 내부 서버까지 갔다가 응답이 되돌아오기까지, 각 단계가 iptables의 어느 체인에서 일어나는지를 순서로 보면 "규칙은 맞는데 왜 안 되지"의 대부분이 풀립니다.
[외부 클라이언트] → 공인 5.6.7.8:8080
│
① 패킷 수신 → [nat] PREROUTING (라우팅 결정 전)
│ DNAT: 목적지 5.6.7.8:8080 → 10.0.0.2:80 변환
│ conntrack 에 '원본↔변환' 매핑 기록 (상태 NEW)
│
② 라우팅 결정 (변환된 목적지 10.0.0.2 기준)
│ 내 것 아님 → 포워딩 경로 (net.ipv4.ip_forward=1 필요)
│
③ [filter] FORWARD (통과 허용 판정)
│ NEW/ESTABLISHED 허용돼야 통과 (정책 DROP 이면 폐기)
│
④ [nat] POSTROUTING (송신 직전)
│ 필요시 SNAT/MASQUERADE 로 출발지 변환 (복귀 경로 확보)
│
⑤ 내부 서버 10.0.0.2:80 도착 → 응답 생성
│
⑥ 응답 복귀 → conntrack 이 기존 연결로 인식
│ 자동 역변환: 출발지를 다시 5.6.7.8:8080 으로
▼
[외부 클라이언트] ← 자기가 접속한 그 주소에서 응답 도착
각 단계의 체인 위치와 어긋났을 때 증상:
| 단계 | iptables 체인·하는 일 | 여기서 막히면 |
|---|---|---|
| ① 수신·DNAT | nat/PREROUTING에서 목적지 변환. 라우팅 결정 전이라 '어디로 보낼지' 정하기 전에 목적지를 바꿈. conntrack에 매핑 기록 | 규칙 오타·잘못된 --to-destination이면 엉뚱한 서버로 / pkts=0이면 룰에 트래픽이 안 닿음 |
| ② 라우팅·ip_forward | 변환된 목적지로 포워딩 판단. net.ipv4.ip_forward=1이어야 다른 NIC로 넘어감 | ip_forward=0이면 DNAT돼도 여기서 폐기 — "룰은 맞는데 안 됨"의 1순위 |
| ③ FORWARD 필터 | filter/FORWARD에서 통과 허용 판정 | 정책 DROP인데 허용 룰 없으면 조용히 드롭 |
| ④ 송신·SNAT | nat/POSTROUTING에서 출발지 변환. 여러 내부 호스트가 공인 IP 하나를 쓰면 출발지 포트를 바꿔 구별(PAT) | 복귀 경로에 SNAT 없으면 내부 응답이 게이트웨이를 안 거쳐 끊김(헤어핀 NAT) |
| ⑤ 응답 역변환 | 응답을 conntrack이 기존 연결로 인식해 자동 역변환 | ESTABLISHED,RELATED 응답을 방화벽이 막으면 못 돌아옴 |
핵심은 conntrack이 연결 단위로 '원본↔변환'을 기억하므로 정방향 규칙만 정의하면 응답은 자동으로 역변환된다는 것입니다. 그래서 역방향 NAT 규칙을 따로 만들 필요가 없습니다. 반대로 이 흐름을 조용히 끊는 두 지점은 늘 정해져 있습니다 — ②의 ip_forward=0과 ③의 FORWARD DROP입니다. 포워딩이 안 되면 sudo iptables -t nat -L -v -n의 pkts 카운터로 트래픽이 각 체인에 닿는지부터 확인하고, ip_forward와 FORWARD 정책을 그다음에 봅니다.
실습 — iptables NAT 구성
NAT를 사용하려면 먼저 커널의 IP 포워딩을 활성화해야 합니다.
# 현재 ip_forward 상태 확인
cat /proc/sys/net/ipv4/ip_forward
# 0 이면 비활성화 상태
# 즉시 활성화 (재부팅 시 초기화됨)
sudo sysctl -w net.ipv4.ip_forward=1
# 또는
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# 영구 활성화 (재부팅 후에도 유지)
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.d/99-ip-forward.conf
sudo sysctl --system
# 확인
sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 1
인터페이스 구성 확인: 어떤 인터페이스가 외부(WAN)/내부(LAN)인지 먼저 확인합니다.
# 네트워크 인터페이스 목록
ip addr show
# 예상 환경:
# eth0: 공인(외부) 인터페이스 - 5.6.7.8
# eth1: 사설(내부) 인터페이스 - 10.0.0.1
# 라우팅 테이블
ip route show
현재 iptables 규칙 확인: 기존에 설정된 NAT 규칙을 먼저 파악합니다.
# nat 테이블 확인
sudo iptables -t nat -L -n -v
# filter 테이블 확인 (FORWARD 체인)
sudo iptables -L FORWARD -n -v
외부에서 게이트웨이의 8080 포트로 들어오는 트래픽을 내부 웹 서버(10.0.0.2:80)로 전달합니다.
이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.
# 1. DNAT 규칙 추가 (PREROUTING 체인)
sudo iptables -t nat -A PREROUTING \
-p tcp \
--dport 8080 \
-j DNAT \
--to-destination 10.0.0.2:80
# 2. FORWARD 체인에서 내부 서버로의 트래픽 허용
sudo iptables -A FORWARD \
-p tcp \
-d 10.0.0.2 \
--dport 80 \
-m state \
--state NEW,ESTABLISHED,RELATED \
-j ACCEPT
# 3. 응답 패킷도 허용 (ESTABLISHED 연결)
sudo iptables -A FORWARD \
-m state \
--state ESTABLISHED,RELATED \
-j ACCEPT
# 4. SNAT/Masquerade (내부 서버가 외부로 응답할 때 출발지 변환)
sudo iptables -t nat -A POSTROUTING \
-s 10.0.0.0/24 \
-o eth0 \
-j MASQUERADE
# 규칙 확인
sudo iptables -t nat -L -n -v
sudo iptables -L FORWARD -n -v
테스트: 외부에서 포트 포워딩이 실제로 동작하는지 확인합니다.
# 외부에서 포트 포워딩 테스트
curl http://5.6.7.8:8080/
# → 10.0.0.2의 웹 서버 응답이 와야 함
# 내부에서 확인 (게이트웨이에서)
curl http://10.0.0.2:80/
여러 포트 포워딩 예시: 서비스별로 다른 포트를 각각 포워딩하는 패턴입니다.
# SSH 포워딩: 외부 2222 → 내부 10.0.0.3:22
sudo iptables -t nat -A PREROUTING \
-p tcp --dport 2222 \
-j DNAT --to-destination 10.0.0.3:22
# HTTPS 포워딩: 외부 443 → 내부 10.0.0.2:443
sudo iptables -t nat -A PREROUTING \
-p tcp --dport 443 \
-j DNAT --to-destination 10.0.0.2:443
# UDP DNS 포워딩: 외부 53 → 내부 DNS 서버 10.0.0.5:53
sudo iptables -t nat -A PREROUTING \
-p udp --dport 53 \
-j DNAT --to-destination 10.0.0.5:53
iptables 규칙은 재부팅 시 사라집니다. 영구 저장 방법을 알아봅니다.
이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.
# 현재 iptables 규칙 저장
sudo iptables-save > /etc/iptables/rules.v4
# 저장된 규칙 확인
cat /etc/iptables/rules.v4
# 규칙 복원
sudo iptables-restore < /etc/iptables/rules.v4
systemd 서비스로 부팅 시 자동 적용 (Ubuntu): iptables 규칙은 재부팅 시 초기화되므로 영구화가 필요합니다.
# iptables-persistent 패키지 설치
sudo apt-get install iptables-persistent
# 현재 규칙을 영구 저장
sudo netfilter-persistent save
# 서비스 상태 확인
sudo systemctl status netfilter-persistent
RHEL/CentOS (firewalld 대신 iptables 직접 사용 시): iptables-save로 규칙을 저장하고 재부팅 시 복원합니다.
# iptables 서비스 설치
sudo yum install iptables-services
# 규칙 저장
sudo service iptables save
# /etc/sysconfig/iptables 에 저장됨
# 부팅 시 자동 시작
sudo systemctl enable iptables
규칙 삭제 방법: 잘못 설정한 규칙은 -D 옵션으로 특정 규칙만 삭제합니다.
# 특정 규칙 삭제 (-D: delete)
sudo iptables -t nat -D PREROUTING \
-p tcp --dport 8080 \
-j DNAT --to-destination 10.0.0.2:80
# 모든 nat 테이블 규칙 초기화
sudo iptables -t nat -F
# 규칙 번호로 삭제
sudo iptables -t nat -L PREROUTING --line-numbers
sudo iptables -t nat -D PREROUTING 2 # 2번 규칙 삭제
트러블슈팅
증상
iptables DNAT 규칙을 추가했는데 외부에서 접속이 되지 않습니다.
# 게이트웨이에서 규칙 확인
sudo iptables -t nat -L PREROUTING -n -v
# Chain PREROUTING (policy ACCEPT)
# target prot opt source destination
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:10.0.0.2:80
# 규칙은 있는데 외부에서 curl 하면?
curl http://5.6.7.8:8080/
# curl: (7) Failed to connect to 5.6.7.8 port 8080: Connection refused
진단
# ip_forward 상태 확인
cat /proc/sys/net/ipv4/ip_forward
# 0 ← 비활성화 상태!
# 패킷이 드랍되는지 확인
sudo iptables -L FORWARD -n -v
# Chain FORWARD (policy DROP) ← DROP 정책!
# → ip_forward=0이거나 FORWARD 체인이 DROP 정책이면 포워딩 안 됨
패킷 흐름 추적: iptables LOG 타겟으로 NAT 규칙을 통과하는 패킷을 기록합니다.
이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.
# iptables 로그 규칙 추가 (진단용)
sudo iptables -t nat -I PREROUTING 1 \
-p tcp --dport 8080 \
-j LOG --log-prefix "NAT-PRE: "
sudo iptables -I FORWARD 1 \
-p tcp \
-j LOG --log-prefix "FWD: "
# 로그 확인
sudo journalctl -f | grep -E "NAT-PRE|FWD"
# 외부에서 접속 시도 후 로그 확인
해결
이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.
# 1. ip_forward 활성화
sudo sysctl -w net.ipv4.ip_forward=1
# 2. FORWARD 체인 정책 또는 규칙 확인
sudo iptables -L FORWARD -n -v
# FORWARD 정책이 DROP이라면 내부 서버로 향하는 트래픽 명시적 허용
sudo iptables -A FORWARD \
-d 10.0.0.2 \
-p tcp \
--dport 80 \
-j ACCEPT
# 3. 영구 설정
echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-forward.conf
sudo sysctl --system
체크리스트
□ net.ipv4.ip_forward = 1 확인
□ iptables FORWARD 체인 정책 및 규칙 확인
□ iptables PREROUTING DNAT 규칙 존재 확인
□ 내부 서버 방화벽에서 해당 포트 허용 확인
□ 내부 서버 서비스가 실제로 실행 중인지 확인
증상
외부에서는 curl http://5.6.7.8:8080/이 정상 동작하는데, 같은 내부망의 다른 서버에서 공인 IP로 접속하면 실패합니다.
# 내부 서버 (10.0.0.10)에서 실행
curl http://5.6.7.8:8080/
# 연결 안 됨 또는 타임아웃
원인
이것은 Hairpin NAT 문제입니다. 내부에서 공인 IP로 나가는 패킷이 게이트웨이에서 DNAT되어 10.0.0.2로 향하지만, 응답 패킷이 게이트웨이를 거치지 않고 직접 10.0.0.10으로 가려 해서 연결이 끊깁니다.
확대
해결 — SNAT 추가 (Hairpin NAT)
# 내부에서 공인 IP로 접속 시 출발지도 게이트웨이 IP로 변환
sudo iptables -t nat -A POSTROUTING \
-s 10.0.0.0/24 \
-d 10.0.0.2 \
-p tcp \
--dport 80 \
-j MASQUERADE
# 이렇게 하면:
# 10.0.0.10 → 5.6.7.8:8080
# DNAT: dst 5.6.7.8:8080 → 10.0.0.2:80
# SNAT: src 10.0.0.10 → 10.0.0.1 (게이트웨이)
# 10.0.0.2 응답: dst 10.0.0.1 → 게이트웨이
# 게이트웨이가 역변환: 10.0.0.10에게 전달
심화 — 공인 IP 하나로 낼 수 있는 연결에는 상한이 있다
심화: SNAT 출발지 포트 고갈 — 대규모 아웃바운드의 숨은 벽
NAT는 평소엔 투명하지만, 대규모 아웃바운드에서 갑자기 '간헐적 연결 실패'로 발목을 잡습니다. 원인은 하나의 공인 IP 뒤에서 동시에 유지할 수 있는 연결 수에 물리적 상한이 있기 때문입니다. conntrack이 연결을 어떻게 구별하는지 알면 이 벽이 왜 생기는지 보입니다.
- 연결은 5-튜플로 구별된다: 프로토콜·출발지 IP·출발지 포트·목적지 IP·목적지 포트. SNAT/MASQUERADE는 출발지 IP를 공인 IP 하나로 통일하면서 겹치지 않게 출발지 포트를 골라 줍니다.
- 같은 목적지로 몰리면 포트가 바닥난다: 목적지 IP·포트가 동일한(예: 외부 API 한 곳) 연결이 수만 개면, 구별에 남는 자유도는 출발지 포트(대략 28k~64k개)뿐입니다. 이게 소진되면 conntrack이 새 연결에 유니크한 매핑을 못 만듭니다.
- 증상이 '간헐적'이라 헷갈린다: 전체가 죽지 않고 일부 새 연결만 SYN 재전송·타임아웃·리셋.
conntrack -S의insert_failed가 증가하고 dmesg에 경고가 뜹니다. - 테이블 크기 문제와는 다르다: conntrack 테이블이 가득 차는 것(nf_conntrack table full)과 특정 목적지에 대한 포트 고갈은 별개입니다 — 후자는 테이블에 여유가 있어도 발생합니다.
해결 방향은 SNAT용 공인 IP를 여러 개로 늘려 포트 풀을 배수로 확장하거나, 애플리케이션 keep-alive·커넥션 풀로 동시 연결 수를 줄이거나, 목적지를 분산하고 conntrack 타임아웃을 낮춰 매핑을 빨리 회수하는 것입니다.
상황
배치·크롤러·푸시 발송처럼 하나의 외부 엔드포인트로 대량 연결을 여는 시간대에만, 요청 일부가 연결 실패(SYN 재전송 후 타임아웃)합니다. CPU·메모리·회선 대역폭은 모두 여유가 있어 자원 지표만 보면 원인이 안 보입니다.
원인
내부 다수 호스트가 MASQUERADE로 공인 IP 하나를 공유하는데, 목적지가 같은 API 한 곳이라 연결 구별에 출발지 포트만 쓸 수 있습니다. 동시 연결이 가용 포트 수를 넘자 conntrack이 새 연결에 겹치지 않는 매핑을 만들지 못해, 삽입 실패로 첫 SYN 단계에서 패킷이 버려졌습니다.
진단
# insert_failed 카운터가 증가하는지
conntrack -S | tr ' ' '\n' | grep insert_failed
# 특정 목적지로 몰린 연결 수 세기
conntrack -L -d 203.0.113.50 2>/dev/null | wc -l
# 커널 경고 확인
sudo journalctl -k | grep -Ei 'nf_conntrack|table full'
같은 목적지 IP:포트로 향하는 연결이 수만 개인데 insert_failed가 함께 오르면 포트 고갈로 확정합니다.
해결
SNAT용 공인 IP를 여러 개로 늘려(--to-source A.B.C.D-A.B.C.G 범위) 출발지 포트 풀을 배수로 확장합니다. 애플리케이션에서 HTTP keep-alive·커넥션 풀로 동시 연결 수 자체를 줄이고, 가능하면 목적지를 여러 엔드포인트로 분산합니다. 단기 처방으로 TIME_WAIT·conntrack 타임아웃을 낮춰 매핑을 빨리 회수할 수 있습니다.
실무 맥락
AWS에서의 NAT
AWS에서는 대부분의 NAT를 관리형 서비스로 처리합니다.
AWS NAT 구성 옵션:
1. NAT Gateway (관리형)
- 고가용성, 자동 스케일
- 시간당 비용 발생
- 권장: 프로덕션 환경
2. NAT Instance (EC2)
- iptables Masquerade 직접 설정
- 비용 절감, 커스터마이징 가능
- 단일 장애점 주의
# NAT Instance 설정 (EC2 Amazon Linux)
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
iptables -t nat -A POSTROUTING \
-s 10.0.0.0/16 \
-o eth0 \
-j MASQUERADE
쿠버네티스에서의 NAT
쿠버네티스 kube-proxy는 서비스 ClusterIP를 실제 Pod IP로 DNAT합니다.
# 쿠버네티스 서비스 포트포워딩과 NAT 확인
sudo iptables -t nat -L -n | grep KUBE
# 예시 출력:
# KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service rules */
# DNAT tcp -- 0.0.0.0/0 10.96.0.1 tcp dpt:443 to:192.168.1.10:6443
포트 포워딩 보안 고려사항
포트 포워딩 설정 시 보안 체크리스트:
□ 필요한 포트만 최소한으로 열기
□ 소스 IP 제한 추가 (-s 203.0.113.0/24)
□ 불필요한 포트는 정기적으로 닫기
□ fail2ban 등 브루트포스 차단 도구 적용
□ 포트 포워딩 목록을 문서화하여 팀 공유
□ VPN으로 대체 가능한지 검토 (더 안전)
실무에서 자주 보는 NAT 시나리오
# 1. 사무실 → 인터넷 (Masquerade)
iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o wan0 -j MASQUERADE
# 2. 외부 → 내부 웹 서버
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 10.0.0.10:80
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to 10.0.0.10:443
# 3. 외부 → 내부 SSH (비표준 포트로 노이즈 줄이기)
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to 10.0.0.5:22
# 4. 소스 IP 제한 포트포워딩 (관리 포트)
iptables -t nat -A PREROUTING \
-s 203.0.113.0/24 \ # 허용된 관리 IP 대역만
-p tcp --dport 8443 \
-j DNAT --to 10.0.0.100:443
정리
NAT 유형
- SNAT (Source NAT) — 내부→외부, 사설 IP→공인 IP, POSTROUTING 체인에서 처리 (Masquerade는 동적 IP 환경용 SNAT)
- DNAT (Destination NAT) — 외부→내부(포트 포워딩), 공인 IP:포트→사설 IP:포트, PREROUTING 체인에서 처리
iptables NAT 핵심 명령어
- DNAT:
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.2:80 - Masquerade:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE - ip_forward:
sysctl -w net.ipv4.ip_forward=1(필수!)
주요 트러블슈팅
- 포워딩 안 됨 →
ip_forward=0확인 - FORWARD 체인 DROP 정책 → 허용 규칙 추가
- Hairpin NAT → 내부망에서 공인 IP 접속 시 SNAT 추가 필요
명령어·단축키 빠른 참조
이 모듈에서 다룬 iptables NAT·포트 포워딩 명령을 실전 옵션과 함께 모았습니다.
| 명령어 | 용도 | 자주 쓰는 예 |
|---|---|---|
sysctl net.ipv4.ip_forward | IP 포워딩 활성 여부 확인/설정 | sudo sysctl -w net.ipv4.ip_forward=1 (0이면 DNAT해도 드랍) |
iptables -t nat -A PREROUTING … -j DNAT | 포트 포워딩(목적지 변환) | --dport 8080 -j DNAT --to-destination 10.0.0.2:80 |
iptables -t nat -A POSTROUTING … -j MASQUERADE | 동적 IP SNAT(내부→외부) | -s 10.0.0.0/24 -o eth0 -j MASQUERADE |
iptables -t nat -A POSTROUTING … -j SNAT | 고정 공인 IP SNAT | -j SNAT --to-source 5.6.7.8 |
iptables -A FORWARD … -j ACCEPT | 포워딩 트래픽 허용(정책 DROP 대비) | -d 10.0.0.2 --dport 80 -m state --state NEW,ESTABLISHED,RELATED |
iptables -t nat -L -n -v | NAT 룰·적중(pkts) 확인 | pkts=0이면 트래픽이 그 체인에 안 닿음 |
iptables -t nat -D / -F | 룰 삭제/초기화 | -D PREROUTING 2(번호 삭제), -F(nat 전체 초기화) |
iptables -t nat -I PREROUTING 1 … -j LOG | 패킷 흐름 추적 | --log-prefix "NAT-PRE: " 후 journalctl -f | grep NAT-PRE |
iptables-save / -restore | 규칙 영구 저장·복원 | iptables-save > /etc/iptables/rules.v4 |
ss -tlnp | 대상 포트 LISTEN 교차 확인 | DNAT 대상 서버에서 해당 포트가 열렸는지 |
conntrack -S / -L -d <IP> | SNAT 포트 고갈 진단 | conntrack -S | grep insert_failed, conntrack -L -d 203.0.113.50 | wc -l |
관련 모듈로 더 깊이:
- 운영 서버 접속 장애 진단: iptables INPUT 체인 완전 분석 — NAT 규칙이 올라가는 같은 iptables의 filter/FORWARD 체인 이해
- 디폴트 라우팅(Default Route)과 게이트웨이 점검 방법 — SNAT/포워딩이 동작하려면 필요한 라우팅·게이트웨이 기초
- 서브넷 마스크 계산과 IP 대역 설계 실무 — 사설 IP 대역과 공인 IP를 구분하는 주소 체계 이해
다음 챕터에서는 VPN과 제로 트러스트 보안 아키텍처를 학습하여, 원격 접속 환경을 안전하게 구축하는 방법을 배웁니다.