작성일 :

NAT 뒤의 장치끼리 어떻게 통신하는가

Part 1에서 NAT의 기본 동작을 살펴보았습니다.

핵심은 내부에서 먼저 연결을 시작해야 한다는 것이었습니다.


이것이 심각한 문제를 만듭니다.


두 사용자가 모두 NAT 뒤에 있다면?

상대방의 NAT 테이블에 항목이 없기 때문에 어느 쪽도 먼저 연결을 시작할 수 없습니다.


1
2
3
4
5
6
7
8
9
10
11
Alice (NAT 뒤)                     Bob (NAT 뒤)
192.168.1.10                       192.168.1.20

Alice의 공인 IP:                   Bob의 공인 IP:
203.0.113.5                        198.51.100.7

Alice → Bob으로 연결 시도?
→ Bob의 NAT가 차단 (테이블에 항목 없음)

Bob → Alice로 연결 시도?
→ Alice의 NAT가 차단 (테이블에 항목 없음)

P2P 애플리케이션의 어려움

P2P(Peer-to-Peer) 애플리케이션은 직접 연결이 필요합니다.


  • VoIP: 음성/영상 통화
  • 게임: 실시간 멀티플레이어
  • 파일 공유: BitTorrent 등
  • 화상 회의: WebRTC 기반 서비스


모두 NAT 트래버설 문제에 직면합니다.


해결책 1: 모든 트래픽을 서버 경유 → 지연 증가, 서버 비용 증가

해결책 2: NAT를 뚫는 기술 사용


NAT 유형과 트래버설 난이도

모든 NAT가 같지는 않습니다. 동작 방식에 따라 트래버설 난이도가 크게 달라집니다.


Full Cone NAT (1:1 NAT)

가장 개방적인 NAT입니다.


1
2
3
4
5
내부: 192.168.1.10:12345
외부: 203.0.113.5:40001 (매핑됨)

한 번 매핑이 생성되면:
- 어떤 외부 호스트도 40001로 연결 가능


특징:

  • 내부에서 한 번 패킷을 보내면 매핑 생성
  • 그 후 누구나 그 매핑된 포트로 접근 가능


트래버설: 쉬움


Restricted Cone NAT

IP 주소로 제한합니다.


1
2
3
4
5
6
내부: 192.168.1.10:12345
외부: 203.0.113.5:40001

이전에 93.184.216.34로 패킷을 보냈다면:
- 93.184.216.34에서 40001로 오는 패킷 허용
- 다른 IP에서 40001로 오는 패킷 차단


특징:

  • 이전에 통신한 IP 주소에서만 수신 가능
  • 포트는 상관없음


트래버설: 중간


Port Restricted Cone NAT

IP와 포트로 제한합니다.


1
2
3
4
5
6
내부: 192.168.1.10:12345
외부: 203.0.113.5:40001

이전에 93.184.216.34:80으로 패킷을 보냈다면:
- 93.184.216.34:80에서 40001로 오는 패킷만 허용
- 93.184.216.34:443에서 오는 패킷도 차단


특징:

  • 정확히 이전에 통신한 IP:포트에서만 수신 가능
  • 대부분의 가정용 공유기가 이 방식


트래버설: 중간~어려움


Symmetric NAT

가장 제한적인 NAT입니다.


1
2
3
4
5
192.168.1.10:12345 → 93.184.216.34:80
  외부 매핑: 203.0.113.5:40001

192.168.1.10:12345 → 142.250.185.46:443
  외부 매핑: 203.0.113.5:40002  (다른 포트!)


특징:

  • 목적지마다 다른 외부 포트를 사용
  • 예측이 어려움


트래버설: 매우 어려움 (대부분의 기술이 실패)


STUN: 자신의 외부 주소 발견

STUN(Session Traversal Utilities for NAT)은 RFC 5389로 정의됩니다.


목적: NAT 뒤에서 자신의 공인 IP와 포트를 알아내는 것입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────┐                    ┌─────────────┐
│  클라이언트  │                    │ STUN 서버   │
│ (NAT 뒤)    │                    │ (공인 IP)   │
└──────┬──────┘                    └──────┬──────┘
       │                                  │
       │ ─── Binding Request ───────────► │
       │     (출발: 192.168.1.10:12345)   │
       │                                  │
       │     NAT가 변환                    │
       │     (출발: 203.0.113.5:40001)    │
       │                                  │
       │ ◄── Binding Response ────────── │
       │     "당신은 203.0.113.5:40001"   │
       │                                  │


STUN 동작 과정

  1. Binding Request 전송: 클라이언트가 공인 IP를 가진 STUN 서버로 요청 패킷을 전송합니다.
  2. NAT 주소 변환: 패킷이 NAT를 통과하면서 사설 IP가 공인 IP와 외부 포트로 변환됩니다.
  3. 출발지 주소 확인: STUN 서버는 도착한 패킷의 출발지 IP:포트를 확인합니다. 이것이 바로 NAT가 변환한 공인 주소입니다.
  4. Binding Response 응답: STUN 서버가 확인한 공인 주소를 응답 패킷에 담아 클라이언트에게 전송합니다.
  5. 공인 주소 획득: 클라이언트는 응답을 통해 자신의 NAT 뒤 공인 IP와 포트를 알게 됩니다.


STUN의 한계

STUN만으로는 실제 연결이 성립되지 않는데, 외부 주소를 알았다고 해서 상대방이 해당 주소로 접근할 수 있는 것은 아니기 때문입니다.


특히 Symmetric NAT에서는 STUN 서버에 보낸 패킷의 외부 포트와 다른 호스트에 보낼 패킷의 외부 포트가 달라지므로, STUN으로 알아낸 주소가 무의미해집니다.


홀 펀칭 (Hole Punching)

두 NAT에 동시에 “구멍을 뚫는” 기법입니다.


UDP 홀 펀칭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Alice                 중개 서버              Bob
(NAT 뒤)                                   (NAT 뒤)

1. Alice가 중개 서버에 연결
   Alice의 외부 주소: 203.0.113.5:40001

2. Bob이 중개 서버에 연결
   Bob의 외부 주소: 198.51.100.7:50001

3. 중개 서버가 양쪽에 상대방 주소 전달

4. Alice가 Bob의 외부 주소로 패킷 전송
   → Alice의 NAT에 매핑 생성
   → Bob의 NAT가 차단 (아직 매핑 없음)

5. Bob이 Alice의 외부 주소로 패킷 전송
   → Bob의 NAT에 매핑 생성
   → Alice의 NAT는 허용! (4에서 매핑 생성됨)

6. 이제 양방향 통신 가능


핵심: 양쪽이 거의 동시에 상대방에게 패킷을 보냄.


1
2
3
4
5
6
7
8
시간
 │
 │  Alice → Bob 시도 (차단됨, 하지만 Alice NAT에 구멍)
 │
 │  Bob → Alice 시도 (성공! Alice NAT 구멍 통과)
 │
 │  이제 양방향 가능
 ▼


Port Restricted Cone NAT까지는 대부분 성공합니다.


TCP 홀 펀칭

TCP는 연결 지향적이고 SYN 패킷의 타이밍이 중요하기 때문에 홀 펀칭이 더 어렵습니다.


동시 개방(Simultaneous Open)을 시도합니다.

양쪽이 동시에 SYN을 보내면 TCP 명세상 연결이 수립되지만, 실제로는 타이밍을 맞추기가 매우 어렵습니다.


TURN: 최후의 수단

TURN(Traversal Using Relays around NAT)은 RFC 5766으로 정의됩니다.


홀 펀칭이 실패하면 TURN을 사용하여 릴레이 서버를 경유합니다.


1
2
3
4
5
6
7
8
9
10
Alice                TURN 서버              Bob
(NAT 뒤)            (공인 IP)            (NAT 뒤)

    │                   │                   │
    │ ─────────────────►│◄───────────────── │
    │                   │                   │
    │   모든 트래픽이   │                   │
    │   TURN 서버를     │                   │
    │   경유            │                   │
    │                   │                   │


TURN의 특징

  • 항상 동작: NAT 유형과 무관
  • P2P가 아님: 실제로는 클라이언트-서버-클라이언트
  • 지연 증가: 한 홉이 추가됨
  • 비용: 서버가 모든 트래픽을 중계해야 함


TURN은 직접 연결이 불가능할 때의 폴백(Fallback) 옵션입니다.

가능하면 피하고 싶지만, Symmetric NAT 같은 경우 유일한 방법입니다.


ICE: 최적의 경로 찾기

ICE(Interactive Connectivity Establishment)는 RFC 8445로 정의됩니다.


STUN, TURN, 직접 연결을 모두 시도하여 최적의 경로를 선택합니다.


ICE 후보(Candidate) 수집

각 피어는 가능한 연결 방법을 수집합니다.


  1. 호스트 후보(Host Candidate)
    • 로컬 IP 주소
    • 예: 192.168.1.10:12345
  2. 서버 반사 후보(Server Reflexive Candidate)
    • STUN으로 알아낸 공인 주소
    • 예: 203.0.113.5:40001
  3. 릴레이 후보(Relay Candidate)
    • TURN 서버 주소
    • 예: 198.51.100.1:3478


1
2
3
4
5
6
7
ICE 후보 목록 예시:

우선순위   유형           주소
───────────────────────────────────────
126        호스트         192.168.1.10:12345
100        서버 반사      203.0.113.5:40001
0          릴레이         198.51.100.1:3478


ICE 연결성 검사

수집된 후보들의 모든 조합을 테스트합니다.


1
2
3
4
5
6
7
Alice 후보          Bob 후보           테스트 결과
────────────────────────────────────────────────────
호스트           ↔ 호스트              실패 (다른 NAT)
호스트           ↔ 서버 반사           실패
서버 반사        ↔ 호스트              실패
서버 반사        ↔ 서버 반사           성공! (홀 펀칭)
릴레이           ↔ 릴레이              성공 (폴백)


가장 우선순위가 높은 성공 조합을 선택합니다.


Trickle ICE

후보를 수집하면서 동시에 검사를 시작하므로 모든 후보를 기다리지 않아도 되어 연결 설정 시간이 단축됩니다.


WebRTC와 ICE

WebRTC는 브라우저에서 실시간 통신을 가능하게 하며, 이때 ICE가 핵심 구성요소로 작동합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
// WebRTC에서 ICE 서버 설정
const configuration = {
  iceServers: [
    { urls: 'stun:stun.example.com:3478' },
    {
      urls: 'turn:turn.example.com:3478',
      username: 'user',
      credential: 'password'
    }
  ]
};

const peerConnection = new RTCPeerConnection(configuration);


WebRTC 연결 과정:

  1. 양쪽이 ICE 후보를 수집
  2. 시그널링 서버를 통해 후보 교환
  3. ICE가 최적 경로 선택
  4. DTLS로 암호화된 연결 수립
  5. 미디어/데이터 전송


실시간 통신 시리즈에서 WebRTC를 자세히 다룹니다.


포트 포워딩

포트 포워딩은 NAT 문제의 수동 해결책으로, 라우터에서 특정 포트를 내부 장비로 고정 매핑합니다.


1
2
3
4
5
라우터 설정:
외부 포트 8080 → 192.168.1.10:80

외부에서 203.0.113.5:8080으로 접속하면
→ 내부의 192.168.1.10:80으로 전달


사용 사례:

  • 홈 서버 운영
  • 게임 서버 호스팅
  • 원격 접속


단점:

  • 수동 설정 필요
  • IP 주소가 바뀌면 재설정 필요
  • 보안 위험 (포트가 항상 열림)

UPnP와 NAT-PMP

UPnP(Universal Plug and Play)는 자동 포트 포워딩을 제공합니다.


애플리케이션이 라우터에 직접 요청합니다.

1
2
3
4
5
애플리케이션 → 라우터:
"외부 포트 12345를 내부 192.168.1.10:12345로 매핑해주세요"

라우터:
"OK, 매핑 생성했습니다"


NAT-PMP(NAT Port Mapping Protocol)는 Apple이 개발한 유사 프로토콜입니다.

후속인 PCP(Port Control Protocol)로 발전했습니다.


보안 문제

UPnP는 인증이 없어서 내부의 어떤 프로그램이든 포트를 열 수 있습니다.


악성코드가 UPnP로:

  • 방화벽 우회
  • 내부 서비스 노출
  • 외부 공격 경로 생성


많은 보안 전문가가 UPnP 비활성화를 권장합니다.


IPv6가 해결책이지만…

IPv6에서는 모든 장비에 고유한 공인 주소를 부여할 수 있으므로 NAT가 필요 없습니다.


따라서 NAT 트래버설 문제가 사라지고 P2P 통신이 간단해집니다.


하지만:

  • IPv6 전환이 느림
  • IPv4와 IPv6 혼용 환경에서 여전히 문제
  • 일부 네트워크는 IPv6에서도 NAT66 사용


당분간 NAT 트래버설 기술은 계속 필요합니다.


정리

NAT 트래버설의 단계:

  1. STUN으로 외부 주소 발견
  2. 홀 펀칭 시도
  3. 실패하면 TURN 릴레이 사용
  4. ICE가 전체 과정을 조율


NAT 유형별 성공률:

1
2
3
4
5
6
NAT 유형               홀 펀칭 성공률
──────────────────────────────────────
Full Cone              높음
Restricted Cone        중간
Port Restricted        중간~낮음
Symmetric              매우 낮음 (TURN 필요)


NAT는 IPv4 주소 고갈을 해결했지만, 새로운 복잡성을 만들었습니다.

실시간 통신, 게임, P2P 애플리케이션은 모두 이 복잡성과 씨름합니다.


관련 글

Tags: ICE, NAT, P2P, STUN, TURN, 네트워크

Categories: ,