Hole Punching

Program RFC/Algorithm 2011. 8. 31. 15:35 Posted by HisPark

Peer-to-Peer Communication Across Network Address Translators

Bryan Ford
Massachusetts Institute of Technology
baford (at) mit.edu

 

Pyda Srisuresh
Caymas Systems, Inc.
srisuresh (at) yahoo.com

 

Dan Kegel
dank (at) kegel.com

J'fais des trous, des petits trous
toujours des petits trous

- S. Gainsbourg

 

P2P관련된 기술 하나인 펀칭에 대한 아주 좋은 논문을 번역해 봤습니다. 다행히 원작자인 Bryan Ford님이 번역본의 게재를 허락해주셨습니다. 하지만 번역을 너무 믿지 마시고 원문과 함께 읽기를 권해드립니다. 오역된 부분을 발견하시면 이메일로 알려주시길 부탁드립니다.

 

번역자 - 리안 (양영욱)
youngwook.yang (at) gmail.com

http://young2write.wordpress.com/

 

저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 2.0 대한민국 라이선스에 따라 이용할 있습니다. 이용허락조건을 보려면, http://creativecommons.org/licenses/by-nc-nd/2.0/kr/ 클릭하거나, 크리에이티브 커먼즈 코리아에 문의하세요.


원문 : http://www.brynosaurus.com/pub/net/p2pnat/

Abstract:

네트워크 주소 변환 (NAT) P2P통신에 있어서 알려진 어려움들을 야기한다. 이는 관련 Peer들이 임의의 global IP주소와 연결되지 않을 수도 있기 때문이다. 몇몇 NAT 선회 기법들이 알려져 있으나 문서화가 미미하고 또한 그들의 확실성, 상대적인 장점등에 관한 데이터는 더욱 불충분하다. 문서는 이들 기법중 가장 간단하지만 가장 확실하고 실용적인 NAT 선회 기법, " 펀칭" 분석한다. 펀칭은 UDP 통신에 대해서는 어느 정도 이해되어져 있지만, 우리는 이것이 어떻게 TCP 통신에서도 믿을만 하게 이용되는지 살펴 이다. 기법의 신뢰도 데이터를 다양한 NAT들을 상대로 하여 테스트한 결과, 해당 NAT 82% UDP 대한 펀칭을 지원하고 64% TCP 대한 펀칭을 지원했다. NAT 벤더들이 점점 Voice over IP 온라인 게임 프로토콜과 같은 중요한 P2P 어플리케이션의 필요를 알아감에 따라 미래에는 펀칭에 대한 지원이 증가하게 것이다.

 

1. Introduction

인터넷의 거대한 성장과 방대한 보안 과제들이 결합되어 많은 어플리케이션들의 삶을 힘들게 많드는 방향으로 인터넷이 진화하게끔 해왔다. 인터넷 본래의 유니폼 주소 체계, 다시 말해 모든 노드들이 고유의 global IP주소를 가지고 다른 노드들과 직접 통신을 하는 방식은 사실상 지금 현존하는 주소 체계로 바뀌게 되었다. 지금 방식은 global 주소들로 이루어진 세계와 private 주소들로 이루어진 세계들이 네트워크 주소 변환 (NAT) 통하여 연결되는 주소 체계이다. 새로운 주소 체계에서는 그림 1에서 보여지는 바와 같이 오직 "main" 있는 노드들, global 주소 세계에 있는 노드들 만이 네트워크 상의 다른 노드들과 쉽게 연결할 있다. 오직 이들만이 global하게 전달 가능한(routable) IP 주소들을 가지기 때문이다. Private 세계에 있는 노드들은 같은 네트워크 안에 있는 노드들과 연결을 있으며, global주소 세계에 사는 " 알려진" 노드와 TCP 혹은 UDP 연결을 있다. 과정에서 NAT들은 안에서 밖으로 향하는 연결에 대하여 임시적으로 public 종점을 할당하고 세션을 구성하는 패킷들에 있는 주소와 포트를 변환한다. 이와 달리, 일반적으로 밖에서 안으로 향하는 모든 트래픽에 대해선 특별한 설정이 되어있지 않는 차단한다.

Figure 1: Public and private IP address domains

방식은 클라이언트가 private 네트워크에 있고 서버가 global 세계에 존재하는 전형적인 클라이언트/서버 통신에 적합하다. 반면에, 텔레컨퍼런싱이나 온라인 게임에 사용되는 P2P 통신 프로토콜에 중요한, 서로 다른 private 네트워크에 존재하는 노드가 직접적으로 통신하게 하는 것을 어렵게 한다. 당연히 NAT들이 존재하는 상황에서도 이런 프로토콜들을 작동하게 하는 방법이 필요하다.

서로 다른 private 네트워크에 존재하는 호스트들 간의 P2P 연결을 구성하는 가장 효과적인 방법중 하나가 " 펀칭"이라는 이름으로 알려져 있다. 방법은 이미 UDP기반의 어플리케이션들 사이에서 널리 이용되고 있으며 또한 본질적으로 TCP에도 적용된다. 이름이 주는 인상과 달리 펀칭은 private 네트워크의 보안을 해치지 않는다. 대신, 펀칭은 대부분의 NAT들의 기본 보안 정책 안에서 어플레이케이션이 작동하도록 한다. 경로 상의 NAT들에게 효과적으로 신호를 보내 P2P 통신의 세션들을 "요청"하게 함으로써 세션들이 수락되게 한다. 문서는 UDP TCP 대한 펀칭을 위한 것이며 펀칭을 가능하게 하는데 중요한 어플레이케이션의 요소와 NAT 방식에 대해 세세히 살펴볼 것이다.

불행하게도, 모든 NAT에서 작동하는 선회 방법은 없다. 왜냐하면 NAT 작동 방식이 표준화되 있지 않기 때문이다. 문서는 현존하는 NAT들의 펀칭 지원에 대한 실험의 결과를 제공한다. 우리의 데이터는 유저들이 인터넷을 통해 서로 다른 벤더들의 다양한 NAT들을 넘어 우리의 "NAT Check" 툴을 실행하여 제공된 결과에서 나온 것이다. 정보들은 자발적으로 선택된 유저들로 부터 모아진 관계로 실제로 출시된 NAT들의 분포상황을 반영하지는 않는다. 하지만 결과는 전반적으로 고무적이다.

기본적인 펀칭을 알아보는 한편, 우리는 또한 보다 복잡함의 대가를 치루고서 더욱 다양한 NAT들에 대해 펀칭이 작동하도록 하는 변칙들도 짚어 것이다. 하지만 우리의 관심사는 합당한 네트워크망 상에서 " 작동하는" NAT들에 대해 명확하고 안정적으로 작동하는 가장 간단한 펀칭 기법을 개발하는 것이다. 우리는 의도적으로 과도하게 영리한 기법들은 다루지 않았다. 이들이 비록 "깨진" NAT들에 대해 일시적인 호환성을 제공할지 모르나 이는 항상 동작하는 것도 아니거니와 장기적으로 예측 불가능성과 네트워크 취약성을 일으킬 있기 때문이다.

비록 IPv6 [3] 보다 주소 공간이 결국에는 NAT 필요성을 줄일지도 모르나, 단기적으로 오히려 이는 NAT 필요성을 더욱 증가 시킬 것이다. 왜냐하면 NAT 자체가 바로 IPv4 IPv6주소 도메인 사이의 상호 운영성을 이룰 있는 가장 쉬운 방법을 제공하기 때문이다 [24]. 거기다 더해, private 네트워크 상에 있는 호스트들의 익명성과 비접근성은 보안과 비공개의 장점들로 여겨진다. 충분한 IP 주소들이 있다 하여도 방화벽이 사라지진 않을 것이다. IPv6 방화벽들도 내부로 향하는 요청되지 않은 트래픽을 기본적으로 막을 것이고 이는 펀칭을 IPv6 어플리케이션들 에게도 유용하게 만들 것이다.

문서의 나머지는 다음과 같이 정리되어 있다. 섹션 2 기본적이 용어와 NAT 선회에 대한 개념을 소개한다. 섹션 3 UDP 대한 펀칭에 대해 자세히 알아보고 섹션 4 TCP 대한 펀칭을 소개한다. 섹션 5 NAT 펀칭을 위해서 반드시 가져야하는 중요한 특성들을 요약한다. 섹션 6 대중적인 NAT들의 펀칭 지원 여부에 대한 실험 결과를 보여주고 섹션 7 관련된 연구들에 대해 논의하며 섹션 8에서 결론을 짓는다.

2 General Concepts

섹션에서는 문서에서 사용되는 기본적인 NAT 용어들을 소개한다. 그리고 UDP TCP 같이 적용되는 일반적인 NAT 선회기법들을 개괄한다.

2.1 NAT Terminology

문서는 RFC 2663 [21] 정의된 NAT 용어들과 분류법, 그리고 RFC 3489 [19] 최근 추가로 정의된 용어들을 사용한다.

 

특별히 중요한 개념은 세션이다. TCP 혹은 UDP 위한 세션 종점 IP 주소와 포트 번호로 이루어진 하나의 쌍이며 하나의 고유한 세션 개의 세션 종점들로 이루어진다. 연관된 호스트들 호스트의 관점에서 보면, 세션은 4개의 요소(로컬 IP, 로컬 포트, 리모트 IP, 리모트 포트)들로 효과적으로 식별된다. 세션의 방향 보통 세션을 처음 시작한 패킷의 흐름 방향이다. , TCP 경우 초기 SYN 패킷이고 UDP 경우 번째 유저 데이터 그램이다.

 

다양한 NAT 방식 가장 일반적인 형은 traditional 혹은 outbound NAT이다. 방식은 private 네트워크와 public 네트워크 사이의 비대칭(asymmetric) 다리를 제공한다. 기본적으로 outbound NAT 오직 외부로 향하는 (outbound) 세션들만이 NAT 선회할 있게 허용한다. 내부로 향하는 패킷들의 경우, NAT 패킷들이 속한 세션이 자신의 private 네트워크에서 시작된 세션이라고 식별하지 않는 차단된다. Outbound NAT P2P 프로토콜들과 충돌을 일으키는데 이는 peer들이 서로 다른 NAT "뒤에" 존재하는 상황에서 서로 통신을 하려할 , 누가 세션을 시작할려고 하든 상대방 peer NAT 이를 거절하기 때문이다. NAT 선회는 양쪽 NAT들에게 P2P 세션들이 "밖으로 향하는" 세션들로 보이도록 만든다.


Outbound NAT
개의 변형을 가진다. Basic NAT 오직 IP 주소만을 변환하고 Network Address/Port Translation (NAPT) 전체 세션 종점을 변환한다. 일반적인 형인 NAPT 가장 보편화가 되었는데 이는 private 네트워크에 있는 호스트들이 하나의 public IP주소를 공유 할수 있게 해주기 때문이다. 문서에서 우리는 NAT NAPT라고 가정할 이나, 우리가 논의할 기본 원리와 기법들은 Basic NAT에도 똑같이 (때때로 차이를 무시해도 상관없이) 적용된다.

2.2 Relaying

NAT 넘나드는 가장 확실한 (그러나 가장 비효과적인) P2P 통신 방법은 중계(relaying) 통해서 간단하게 표준 클라이언트/서버 모델 처럼 만드는 이다. 호스트 A B 알려진 서버 S UDP 혹은 TCP 연결을 시작했다고 하자. S IP 주소는 18.181.0.31, 포트 번호는 1234 하자. 그림 2에서 보이듯, 클라이언트는 서로 다른 private 네트워크 상에 존재하며 각각의 상응하는 NAT 상대 클라이언트와 직접적으로 연결을 시작하는 것을 막고 있다. 직접 연결하는 대신에 클라이언트는 사이의 메세지를 중계해주는 역할로 서버 S 이용할 있다. 예를 들어, 클라이언트 B에게 메세지를 보내려면 클라이언트 A 그냥 메세지를 서버 S 이미 구성된 클라이언트/서버 연결을 통하여 보낸다. 그러면 서버 S 이미 존재하는 B와의 클라이언트/서버 연결을 이용해 이를 클라이언트 B 전달한다.

 

Figure 2: NAT Traversal by Relaying

 

클라이언트가 서버에 연결할 있는 중계는 항상 작동한다. 기법의 단점은 서버의 프로세싱 파워와 네트워크 대역폭을 소모한다는 이다. 또한 아무리 서버가 연결되어 있다 하더라도 클라이언트 사이의 통신 지연이 늘어날 가능성이 있다. 그럼에도 불구하고, 모든 NAT들을 상대로 확실히 동작하는 효과적인 기법이 없기 때문에, 최대의 확실성이 요구된다면 중계는 유용한 대책이다. TURN 프로토콜 [18] 중계를 상대적으로 안전하게 구현하는 법을 정의한다.

2.3 Connection Reversal

어떤 P2P 어플리케이션들은 보다 명확하지만 제한적인 기법을 사용한다. 기법은 "거꾸로 연결"(connection reversal) 이라고 알려져 있는데, 그림 3 나오듯, 호스트가 모두 알려진 랑데뷰 서버 S 연결되어 있고 오직 하나의 피어(peer)만이 NAT 뒤에 있을 경우 통신을 가능케 한다. 만약에 A B 향해 연결을 시작하려 하면 직접 연결 시도는 자동적으로 작동한다. 왜냐하면 B NAT뒤에 있지 않고 A NAT 연결을 밖으로 향하는 세션으로 해석하기 때문이다. 하지만, 만약 B A 향해서 연결을 시작하려 하면, A 향한 어떤 직접 연결 시도든 A NAT 의해 차단 당하게 된다. 대신에 B 알려진 서버 S 통해서 연결 요청을 중계할 있다. 다시 말해 A에게 B 향해 거꾸로 연결을 시도하라고 요청하는 이다. 기법의 명확한 한계와 상관없이, 랑데뷰 서버를 이용해서 P2P 연결의 셋업을 돕는 핵심 아이디어는 다음에 기술되는 일반적인 펀칭 기법의 기본이 된다.


Figure 3: NAT Traversal by Connection Reversal

3 UDP Hole Punching

UDP 펀칭은 클라인언트가 모두 NAT 뒤에 있다고 하더라도 알려진 랑데뷰 서버를 통해서 직접적인 P2P UDP 세션을 구성케 하는 기법이다. 기법은 RFC 3027 5.1 섹션 [10] 언급되었으며, [13]에서 완전히 문서화가 되었고 최근의 실험적인 인터넷 프로토콜들 [17,11]에서 사용되었다. 또한 온라인 게임을 위한 다양한 고유의 프로토콜들도 역시 UDP 펀칭을 사용한다.

 

3.1 The Rendezvous Server

펀칭은 이미 클라인트 A B 랑데뷰 서버 S 활성화된 UDP 세션을 가지고 있다고 가정한다. 클라이언트가 S 등록할 , 서버는 해당 클라이언트를 위한 종점을 기록한다. 하나는 S 이야기하기 위해 클라인트가 믿는 자신의 종점(IP 주소, UDP 포트)이고 다른 하나는 서버가 보는 클라이언트의 종점(IP 주소, UDP 포트)이다. 우리는 번째 종점을 클라이언트의 private 종점이라 하고 번째를 클라이언트의 public 종점이라 한다. 서버는 클라이언트의 private 종점을 클라이언트에서 보내지는 등록 메세지 본체의 필드에서 얻을 있을 이고, public 종점의 경우 등록 메세지의 IP UDP 헤더에 있는 소스 IP 주소와 소스 UDP 포트 필드들로 부터 얻을 있을 것이다. 만악에 클라이언트가 NAT 뒤에 있지 않다면, private public 종점은 반드시 같을 것이다.

불완전한 몇몇 NAT들은 IP 주소처럼 보이는 UDP 데이터그램의 4바이트 필드를 스캔하여 그것이 IP헤더에 있는 IP 주소 인것 처럼 해석하는 것으로 알려져 있다. 이런 동작에 대해 안전하게 대처하기 위해, 어플레이케이션들은 메세지 본체에 들어있는 IP주소를 식별하기 힘들게 만들수도 있다. 예를 들어, IP 주소 자체 대신에 IP주소의 1 보수로 변환하는 식으로 말이다. 물론, 어플레이케이션이 자신의 메세지들을 암호화한다면 이런 동작이 문제가 소지는 없을 것이다.

3.2 Establishing Peer-to-Peer Sessions

클라이언트 A 클라이언트 B 직접적으로 UDP 세션을 구성하고 싶다고 하자. 펀칭은 다음과 같이 진행된다.

1. 처음에 A 어떻게 B 닿아야 할지 모른다. 따라서 A S에게 B UDP 세션을 구성하기 위해 도움을 요청한다.

2. S
A에게 B public private 종점을 담은 메세지로 답한다. 그와 동시에, S B 연결된 UDP 세션을 이용해서 B에게 A public private 종점을 담은 연결 요청 메세지를 보낸다. 메세지들이 수신되고 나면, A B 서로의 public private 종점들을 알게 된다.

3. A
B public private 종점들을 S 부터 받으면, A UDP 패킷을 종점 모두에게 보내기 시작한다. 다음으로 어떤 종점이든 번째로 B 부터 유효한 답변을 이끌어 종점과 연결한다. 이와 비슷하게, S 부터 전될된 연결 요청 메세지에 있는 A public private 종점들을 B 받게 되면, B A 각각의 종점들에게 UDP 패킷을 보내기 시작하며 번째로 동작하는 종점과 연결한다. 메세지들이 비동기적이라는 조건하에 순서와 타이밍은 중요하지 않다.


이제 우리는 UDP 펀칭이 3가지 각각 특정의 네트워크 상황을 어떻게 다루는지 생각할 것이다. "쉬운" 경우라고 있는 첫번째 상황은 바로 클라이언트가 같은 NAT 뒤에 존재하는 경우이다. 두번째 경우는 가장 일반적인 것으로 클라이언트들이 서로 다른 NAT 뒤에 사는 것이다. 세번째 경우는 각각의 클라이언트가 레벨의 NAT 뒤에 있는 상황이다. 인터넷 서비스 제공 업체에서 배치된 일반적인 " 번째 레벨" NAT 네트워크를 위한 별개의 " 번째 레벨" NAT 라우터들이 예가 된다.

어플리케이션 자신이 정확하게 물리적인 네트워크 레이아웃을 판별하기란 대개 어렵거나 불가능하다. 따라서 주어진 시간에 위의 상황들 (혹은 다른 많은 가능한 상황들) 식별하는 것도 마찬가지다. STUN [
19] 같은 프로토콜들이 통신 경로 상의 NAT들에 대한 일정 정보를 제공할 있지만 이런 정보들이 항상 완전하거나 믿을만 것은 아니다. 특히 다중 레벨의 NAT들이 연관되었을 그렇다. 이런 상황에도 불구하고, 펀칭은 모든 경우에 대해 어플리케이션이 특정 네트워크 구성을 필요가 없이 자동적으로 동작한다. , 연관된 NAT들이 합리적인 방식으로 동작할 경우에 한해서다. (NAT "합리적인" 동작들에 대해서 섹션 5에서 설명될 것이다.)

3.3 Peers Behind a Common NAT

 

첫번째로 생객해 상황은 클라이언트가 (아마도 모르게) 같은 NAT 뒤에 사는 경우이다. 따라서 그림 4에서 보여지듯, 이들은 같은 private IP 주소 세상에 자리하고 있게 된다. 클라이언트 A 서버 S UDP 세션을 구성하였고 NAT 자신만의 public 포트 번호 62000 이에 할당 하였다. 클라이언트 B 비슷하게 S UDP연결을 구성했으며 NAT 이에 public 포트 번호 62005 할당 하였다.

 

Figure 4: UDP Hole Punching, Peers Behind a Common NAT

클라이언트 A 위에서 개괄된 펀칭 기법을 사용하여 서버 S 소개자로 이용, B UDP 세션을 구성한다고 해보자. 클라이언트 A S에게 B 대한 연결 요청 메세지를 보낸다. S A에게 B public private 종점들로 답을 하고 또한 A public private 종점들을 B 전달한다. 이후 양쪽 클라이언트 모두 이들 종점들을 향해서 UDP 데이터그램을 상대방에게 직접적으로 보내길 시도한다. public 종점으로 향하는 메세지들은 그들의 종착지에 수도 있고 갈수도 있는데 이는 해당 NAT 아래 섹션 3.5에서 기술되는 hairpin 변환을 지원하냐 안하냐에 달려있다. 반면에, private 종점들로 향하는 메세지들은 그들의 종착지에 도달한다. 그리고 또한 private 네트워크를 통한 직접 루트가 NAT 통하는 간접 루트 보다 빠를 이므로, 클라이언트들은 이후의 정식 연결을 위해서 십중팔구 private 종점들을 선택할 것이다.

NAT
hairpin 변환을 지원한다고 가정하면, private 종점들에게도 public 종점들과 같이 연결을 시도해야하는 복잡함을 없앨 수도 있다. 이는 어플리케이션이 같은 NAT 뒤에 있는 로컬 연결을 해당 NAT 불필요하게 거쳐가게 하는 것을 대가를 치뤄야한다. 하지만 섹션 6에서 우리의 결과가 보여주듯, hairpin 변환은 다른 "P2P 친근한" NAT 동작들에 비해 아주 적게 퍼져있다. 따라서, 지금 당장은 어플레이케이션들이 public private 종점들을 모두 사용함으로써 실제의 이득을 얻을 같다.

3.4 Peers Behind Different NATs

그림 5에서 나오듯, 클라이언트 A B 서로 다른 NAT 뒤에 private 주소를 가진다고 해보자. A B 각자 그들의 로컬 포트 4321에서 서버 S 포트 1234 UDP 연결을 시작했다. outbound 세션들을 다루기 위해, NAT A S 연결된 A 세션에 포트 62000 자신의 public IP, 155.99.25.11 할당 하였다. NAT B S 연결된 B세션에 포트 310000 자신의 IP주소, 138.76.29.7 할당했다.

Figure 5: UDP Hole Punching, Peers Behind Different NATs


A
자신의 private 종점 10.0.0.1:4321 자신의 등록 메세지를 통해 서버로 보낸다. 이때 10.0.0.1 자신의 private 네트워크 상에서의 IP주소이다. S 전달된 A private 종점과 함께 자신이 보는 A public 종점도 함께 기록한다. 경우에, A public 종점은 155.99.25.11:62000이다. 이는 NAT 의해 해당 세션에 임의로 할당된 종점이다. 이와 비슷하게 B 등록을 경우에 S B private 종점인 10.1.1.3:4321 B public 종점인 138.76.29.7:31000 기록한다.

 

인제 클라이언트 A B와의 직접적인 UDP 통신 세션을 만들기 위해 위에서 설명된 홀펀칭 방식을 따르게 된다. 먼저, A S에게 B와의 연결을 위한 도움을 요청하는 메세지를 보낸다. S 이에 대한 답으로 B public private 종점을 A에게 보낸다. 또한 A public private 종점을 B 보낸다. A B 각각 서로의 종점들을 향해 UDP 데이터그램을 보내기를 시작한다.

 

A B 서로 다른 private 네트워크 상에 있기 때문에 그들 각각의 private IP주소는 전역적으로 전달 가능하지 않다. 따라서 이들 종점으로 보내진 메세지들은 잘못된 호스트에 도달하거나 아니면 어떤 호스트에도 도달하지 않을 것이다. 많은 NAT들이 DHCP서버로서의 역할을 하고 있는데 주로 NAT벤더들에 의해 기본으로 선택된 private 주소 pool 부터 아주 결정론적인 방식으로 IP주소들을 할당하는 식이다. 때문에 실질적으로는, B private 종점으로 향하는 A 메세지는 A private 네트워크 상에 있는 B 같은 private IP주소를 가지게 어떤 다른 호스트로 전달될 것이다. 따라서 어플레케이션은 반드시 모든 메세지들을 무슨 방식으로든 인증함으로써 이런 길잃은 메세지들을 강하게 걸러내야 한다.

 

인제 그림 5에서 보여지듯, B public 종점으로 보내진 A 첫번째 메세지를 생각해보자. 밖으로 향하는 메세지가 A NAT 통과함에 따라, NAT 메세지가 밖으로 향하는 새로운 세션의 첫번째 UDP 패킷임을 알게 된다. 새로운 세션의 시작 종점(10.0.0.1:4321) A S사이에 이미 존재하는 세션과 같다. 하지만 도착 종점은 다르다. 만약 NAT A 작동한다면, A private 종점의 ID 보존한다. 이는 private 시작 종점인 10.0.0.1:4321 주소로 부터 해당되는 pubilc 시작 종점인 155.99.25.11:62000 주소로 일관적으로 변환하는 ID이다. 따라서 B public 종점으로 항하는 A 첫번째 메세지는 사실 A NAT "구멍을 뚫은 것이다." 홀펀칭은 바로 새로운 세션을 위한 것인데, 세션은 A private 네트워크상에서 종점들 (10.0.0.1:4321 - A private 주소, 138.76.29.7:31000 - B public 주소) 정의된다. 또한 세션은 메인 인터넷 상에서 종점들(155.99.25.11:62000 - A public 주소, 138.76.29.7:31000 - B public 주소) 정의된다.

만약 B public 종점으로 향하는 A 메세지가 B NAT 도달했는데 아직 A 향하는 B 첫번째 메세지가 B NAT 건너기 이라고 하자. 경우 B NAT 내부로 향하는 A 메세지를 요청되지 않은 트래픽으로 분류, 걸러낼 것이다. 반면에, A public 주소로 향하는 B 첫번째 메세지는 앞서 설명과 마찬가지로 B NAT 구멍을 열게 된다. 이는 세션을 위한 것으로 B private 네트워크에서 종점들(10.1.1.3:4321 - B private 주소, 155.99.25.11:62000- A public 주소) 정의됨과 동시에 인터넷 상에서는 (138.76.29.7:31000 - B public 주소, 155.99.25.11:62000 - A public 주소) 정의된다. A B 각자 자신들의 NAT들을 한번 건너기만 하면, 구멍들이 각각의 방향으로 열리고 UDP 통신이 정상적으로 진행될 있다. 클라이언트들은 public 종점들이 작동한다는 것을 한번 확인하고 나면 다른 방편이였던 private 종점들로 메세지들을 보내는 것을 멈출 있다.

3.5 Peers Behind Multiple Levels of NAT

다중 NAT 장치들에 연관된 어떤 망들에서는, 클라이언트가 망의 특정한 지식이 없이는 "최적의" P2P연결을 구성을 수가 없다. 그림 6 나와있는 마지막 상황을 생각해보자. 인터넷 서비스 제공 업체 (ISP) 많은 고객들을 적은 public IP주소 만으로 다중 수신하기 위해 기업형 NAT C 설치했다고 해보자. 여기에 해당 인터넷 업체의 고객들이 집에서 그들의 네트워크를 구성하기 위해 각자의 ISP 제공 IP주소에 NAT A B 설치했다고 해보자. 서버 S NAT C만이 오직 전역적으로 전달 가능한 IP 주소를 가지고 있다. NAT A B public 주소는 사실 ISP 주소 세계 안에 있는 private 주소이다. 한편, 클라이언트 A B 주소는 NAT A B 세계에 있는 private 주소인 것이다. 전과 마찬가지로 각각의 클라이언트가 서버를 향해 밖으로 향하는 연결을 시작한다. 이는 NAT A B 각각 하나의 public/private 변환을 생성하며 또한 NAT C 각각의 세션에 해당하는 public/private 세션 구성을 야기한다.

 

Figure 6: UDP Hole Punching, Peers Behind Multiple Levels of NAT

 

인제 A B 펀칭을 통해서 직접 P2P 연결 구성을 시도한다고 해보자. 아마 최적의 라우팅 방식은 클라이언트 A NAT B 있는 클라이언트 B "semi-public" 주소, 10.0.1.2:55000 (ISP 주소 공간), 으로 메세지를 보내고 클라이언트 B역시 NAT A 있는 클라이언트 A "semin-public" 주소, 10.0.1.2:45000 으로 보내는 방식일 것이다. 하지만 불행히도, A B 주소를 방법은 없다. 왜냐하면 서버 S 오직 클라이언트의 진정한 전역 public 주소만 보기 때문이다. 또한 A B 주소들을 어떻게든 알았다 하여도 이들이 사용가능 할지는 미지수이다. 이는 ISP prviate 주소 세계의 IP주소 할당과 클라이언트의 private 세계에서의 IP 주소 할당이 충돌할 있기 때문이다. (예를 들어서, NAT C에서 NAT A 할당한 IP주소가 NAT B에서 클라이언트 B 할당한 주소인 10.1.1.3 일지도 모르는 것이다. (역주: 이러면 B 자기 자신에게 메세지를 보내는 결과가 나와버린다.)

 

따라서 P2P통신을 위해 클라이언트들은 서버 S에게 보여지는 그들의 전역 public 주소를 이용하는 밖에는 없다. 그리고 NAT C에서 제공하는 hairpin 혹은 loopback 변환에 의존해야한다. A B 전역 종점, 155.99.25.11:62005으로 UDP 데이터그램을 보낼 NAT A 먼저 데이터그램의 시작 종점을 10.0.0.1:4321 10.0.1.1:45000으로 변환한다. 이제 데이터그램은 NAT C 도착하고 데이터그램의 도착 주소가 NAT C 변환된 public 종점들 중에 하나라는 것을 알아차린다. 만약 NAT C 동작한다면, 데이터그램의 시작과 도착 종점을 모두 변환하고 데이터그램을 "돌려서" private 네트워크로 보낸다. 이제 데이터그램의 시작 종점은 155.99.25.11:62000 이고 도착 종점은 10.0.1.2:55000 이다. 끝으로 B private 네트워크로 데이터그램이 들어가면서 NAT B 데이터그램의 도착 주소를 변환, B 도착하게 된다. A 가는 길도 비슷하게 작동한다. 많은 NAT들은 아직 hairpin 변환을 지원하지 않는다. 하지만 NAT 벤더들이 문제를 인지함에 따라서 점점 보편화 것이다.

3.6 UDP Idle Timeouts

UDP 통신 프로토콜은 NAT 가로지르는 세션의 수명을 수있는 어플리케이션 독립적이고 믿을 만한 방법을 NAT에게 제공하지 않는다. 때문에 대부분의 NAT들은 단순하게 UDP 변환들과 타이머를 연관시켜서, 만약 특정 시간동안 어떤 트래픽도 없으면 구멍(hole) 닫아 버린다. 불행히도 특정 시간에 대한 어떤 표준 값도 없다. 어떤 NAT들은 20 정도로 짧은 시간을 가진다. 만약 어플리케이션이 펀칭을 통해서 구성한 세션을 계속해서 살아있게 유지하려면, 반드시 주기적으로 "keep-alive" 패킷들을 보내서 NAT 있는 해당 주소 변환의 상태가 사라지지 않게 해야한다.

 

불행히도 많은 NAT들은 특정한 종점들로 정의된 세션과 UDP Idle 타이머를 연관시키기 때문에, 세션으로만 keep-alive 패킷들을 보내는 것으로 다른 세션들을 살아있게 유지할 없다. 비록 모든 세션들이 같은 private 종점들에서 시작되었다고 하더라도 말이다. 이렇듯 다른 많은 P2P세션들로 keep-alive 패킷을 보내는 대신에, UDP세션이 이상 작동하지 않는 것을 감지하고 "필요에 따라" 다시 원래의 펀칭 방법을 실행하는 것으로 어플레이케이션은 지나친 keep-alive 트래픽을 맊을 있다.

 

4 TCP Hole Punching

NAT 뒤에 있는 호스트들 사이의 P2P TCP 연결을 구성하는 것은 UDP보다 약간 복잡하다. 하지만 프로토콜 레벨에서 보면 TCP 펀칭은 UDP 아주 흡사하다. UDP 펀칭 만큼 널리 알려지지 않았기에, 적은 NAT들만이 TCP 펀칭을 지원한다. 하지만 관련된 NAT들이 이를 지원하기만 한다면, TCP 펀칭 역시 UDP 펀칭 만큼 빠르고 믿을만 하다. 사실 동작하는 NAT 사이를 가로지르는 P2P TCP 연결이 UDP 통신 보다 튼실하다. 왜냐하면 UDP 달리 TCP 프로토콜의 상태 기계가 NAT들에게 특정 TCP 세션의 수명을 정확하게 결정할 있는 표준 방법을 제공하기 때문이다.

4.1 Sockets and TCP Port Reuse

TCP 펀칭을 구현하는데 가장 걸림돌이 되는 것은 프로토콜 문제가 아니라 API 문제이다. 표준 버클리 소켓 API 클라이언트/서버 패러다임을 기반으로 디자인되었기 때문에, API 소켓이 connect() 밖으로 향하는 연결을 시작하거나 혹은 listen() accept() 통해서 안으로 향하는 연결들을 들을 수있다. 하지만 둘다는 안된다. 거기다 더해, TCP 소켓들은 대개 로컬 호스트 상에서 TCP 포트와 일대일 관계를 가진다. 어플리케이션이 소켓에 특정 로컬 TCP 포트를 할당하고 나면, 두번째 소켓을 같은 포트에 할당하려는 시도는 실패한다.

 

하지만 TCP 펀칭이 작동하려면, 우리는 하나의 포트로 안으로 향하는 TCP 연결들을 들어야 함과 동시에 밖으로 향하는 다수의 TCP 연결을 시작해야한다. 다행히도 모든 메이저 운영 체제들이 대개 SO_REUSEADDR라고 불리는 특별한 TCP 소켓 옵션을 지원하는데, 이는 어플리케이션이 다수의 소켓을 같은 로컬 종점으로 바인딩 있게 해준다. , 모든 소켓들이 옵션을 켜놓은 상태여야 한다. BSD 시스템들은 SO_REUSEPORT 옵션을 소개했는데, 이는 주소 재사용과 별개로 포트를 재사용을 제어할수 있게 해준다. 이런 시스템에서는 옵션 모두 받드시 켜져 있어야 한다.

4.2 Opening Peer-to-Peer TCP Streams

클라이언트 A 클라이언트 B TCP 연결을 설정하기를 원한다고 해보자. 우리는 이미 클라이언트 A B 알려진 랑데뷰 서버 S 연결되어 있다고 가정한다. UDP 경우와 마찬가지로, 서버는 각각 클라이언트의 public 종점과 private 종점을 기록하고 있다. 프로토콜 레벨에서 보면 TCP 홀펀칭은 UDP 경우와 거의 동일하게 동작한다.

 

1. 클라이언트 A S 연결된 TCP 세션을 사용하여 S에게 B와의 연결을 위한 도움을 요청한다.

2. S
A에게 B public private TCP 종점들을 보내주고 동시에 A public private 종점들을 B에게 보낸다.

3. S
에게 등록하기위해 사용했단 똑같은 로컬 TCP 포트들로 부터, A B 각자 비동기적으로 S에게 보고되어있던 상대방의 public private 종점들을 향해 밖으로 향하는 연결 만들기를 시도한다. 동시에 그들 각자의 로컬 TCP 포트들에서 안으로 향하는 연결을 듣고 있는다.

4. A
B 밖으로 향하는 연결 시도가 성공하거나 또는 안으로 향하는 연결이 나타날 때까지 기다린다. 만약 밖으로 향하는 연결 시도가 "connection reset" 이나 "host unreachable"등의 에러로 인해 실패하게 되면, 짧은 시간 뒤에 (예를 들어, 1 뒤에) 그냥 다시 연결을 시도한다. 이를 어플리케이션이 정한 최대 timeout 까지 계속한다.

5. TCP
연결이 만들어지면, 호스트들은 각자가 서로 의도했던 호스트와 연결되었는지를 확인하기 위해 인증을 한다. 만약 인증이 실패하면, 클라이언트들은 연결을 종료하고 다른 것들이 성공할 까지 기다린다. 클라이언트들은 과정을 통해서 첫번째로 성공적으로 인증된 TCP 연결을 사용한다.

 

동시에 서버 S 임의의 개수의 상대방과의 통신을 하기 위해 하나의 소켓만을 필요로 하는 UDP 달리. 각각의 TCP 클리언트 어플리케이션은 그림 7 나오듯 하나의 로컬 TCP 포트에 바운드된 여러개의 소켓을 다뤄야한다. 각각의 클라이어트들은 서버 S와의 연결을 나타내는 소켓, 안으로 향하는 연결을 수락하기 위한 수신 소켓, 그리고 상대방의 public private TCP 종점들을 향해 밖으로 향하는 연결을 시작하기 위한 최소한 개이상의 소켓이 필요하다.

Figure 7: Sockets versus Ports for TCP Hole Punching

 

그림 5 나오듯, A B 서로 다른 NAT 뒤에 있는 일반적인 경우를 따져보자. 포트 번호들이 UDP 포트가 아니라 TCP 포트라고 해보자. A B private 종점으로 향하는 연결들은 실패하거나 잘못된 호스트와 연결된다. UDP 경우와 같이, TCP 어플리케이션들도 그들의 P2P 세션들을 인증하는 것이 중요한다. 로컬 네트워크 상에 있는 호스트가 원래 연결하고자 하는 원격 private 네트워크상의 호스트와 똑같은 private IP 가지는 경우에, 실수로 잘못된 연결이 생길수 있는 가능성이 있기 때문이다.

 

반면에 각자의 public 종점으로 향하는 연결들의 경우, 이에 해당하는 NAT들로 하여금 A B 직접적인 TCP연결을 활성화 시켜주는 "구멍" 열게한다. 만약 NAT들이 작동한다면, 그들 사이의 새로운 P2P TCP 연결이 자동적으로 형성된다. 만약 B 첫번째 SYN패킷(A 향하는) B NAT 닿기 전에, A 첫번째 SYN 패킷(B 향하는) B NAT 닿으면, B NAT 이를 요구되지 않은 안으로 향하는 연결로 간주, 패킷을 버린다. 하지만, 이후에 B 첫번째 SYN 패킷(A 향하는) 통과되게 되는데, 이는 A NAT SYN B로의 향하는 연결의 부분으로 간주하기 때문이다. B로의 밖으로 향하는 연결을 A SYN 시작했다고 보는 것이다. (역주: 간단히 말해 A SYN 패킷이 이미 A NAT "구멍" 뚫어 놓은 것이다.)

4.3 Behavior Observed by the Application

TCP 펀칭 와중에,클라이언트 어플리케이션이 보게 되는 그들의 소켓에 벌어질 일들은 타이밍과 더불어 해당 TCP구현에 달려있다. B public 종점으로 향하는 A 첫번째 outbound SYN 패킷이 NAT B 의해 버려졌지만, 뒤에 A public 종점으로 향하는 B 첫번째 SYN 패킷이 A TCP SYN 다시 보내기 전에 A 도착했다고 해보자. 운영 체제에 따라서 가지중 가지가 경우가 일어난다.

 

  • A TCP 구현은 들어오는 SYN 세션 종점들이 A 시작하려 했던 밖으로 향하는 세션들의 그것들과 짝임을 알게된다. 따라서 A TCP 스택은 새로운 세션을 A B 향해 connect() 사용했던 로컬 어플리케이션 상의 소켓에 연관시킨다. 어클리케이션의 비동기 connect() 호출은 성공하고 listen 소켓에서는 아무 일도 일어나지 않는다.

 

수신된 SYN 패킷이 전에 A 보낸 outbound SYN 대한 ACK 포함하고 있지 않기 때문에, A TCP B publc 종점을 향해서 SYN-ACK 패킷을 회신한다. 패킷의 SYN 부분은 단지 똑같은 씨퀀스 번호를 사용하는 A 원래 outbound SYN 반복이다. B TCP A SYN-ACK 받기만 하면, A SYN 위한 자신의 ACK 답변을 하고 TCP 세션은 양쪽 상에 모두 연결된 상태로 돌입하게 된다.

 

  • 다른 경우에는, A TCP 구현이 A 안으로 향하는 연결 시도에 대한 활성화된 listen 소켓이 있다는 것을 감지할 지도 모른다. B SYN 안으로 향하는 연결 시도로 보이기 때문에, A TCP 새로운 TCP 세션과 이와 연관되는 stream 소켓을 생성하고 소켓을 어플리케이션이 자신의 listen 소켓에 accept() 호출하는 것을 통해 전달한다. 다음으로 A TCP B에게 위의 경우와 같이 SYN-ACK 회신하고 TCP연결 설정은 보통의 클라이언트/서버 스타일 형식으로 나아간다.

 

B 향한 A 이전 outbound connect() 사용했던 source destination 종점들이, 이제 아까 accept() 통해서 어플리케이션으로 넘겨진 다른 소켓에 의해 사용되고 있기 때문에, A 비동기 coonect() 반드시 어떤 시점에서 대개 "address in use" 에러와 함께 실패한다. 그럼에도 불구하고 어플리케이션은 B와의 P2P통신을 위한 작동하는 stream 소켓을 가지고 있으므로 실패를 무시한다.

 

첫번째 경우는 대개 BSD 기반으로 하는 운영체제들 상에서 나타나다고, 두번째 경우는 Linux Windows경우에 보다 자주 나타난다.

4.4 Simultaneous TCP Open

펀칭 과정 , 다수의 연결 시도들의 타이밍이 맞아 떨어져서, 클라이언트 모두 밖으로 향하는 최초의 SYN 패킷들이 상대방의 NAT 닿기 전에 자신의 해당 로컬 NAT 당도하였다고 하자. 경우 각각의 NAT 밖으로 향하는 TCP 세션들을 열게 된다. 이런 " 좋은" 경우에는, NAT들은 어떤 초기 (역주 : 안으로 향하는) SYN 패킷도 거절하지 않게 되고 초기 SYN 패킷들은 NAT 사이의 선상을 가로지른다. 경우에, 클라이언트들은 "simultaneous TCP open"이라는 현상을 보게 된다. 이는 각각의 peer들이 모두 SYN-ACK 기다리는 와중에 "생짜(raw)" SYN 받은 것이다. 피어들의 TCP들은 SYN-ACK 회신을 하며, 이때 SYN 이전에 보낸 것과 같은 것이고 ACK 부분은 다른 peer 부터 받은 SYN 대한 수신 확인이다.

 

경우 각각의 어플리케이션들이 격게 상황은 앞에서 설명된 바와 같이 TCP 구현이 어떻게 동작하냐에 따라 달라진다. 만약에 클라이언트 모두 앞에서 설명한 번째 경우와 같이 구현되었다면, 모든 비동기 connect() 함수 호출은 실패할 것이다. 하지만 그럼에도 불구하고 각각의 클라이언트에서 돌아가는 어플리케이션은들은 accept() 통해서 P2P TCP통신이 작동하는 연결을 가진다. 이것은 마치 마법과 같이 TCP 연결이 선상에서 "스스로 만들어져서" 서로의 종점에서 수동적으로 받아들여지기만 것과 같은 것이다! 어플리케이션이 P2P TCP 소켓들이 connect()에서 생겼는지 accept()에서 생겼는지 상관하지 않는다면, 과정은 RFC 793 [23] 명시된 표준 TCP 상태 기계를 제대로 구현한 어떤 TCP에서도 동작하는 결과를 낳게된다.


UDP
위한 섹션 3에서 토의된 여러 다른 네트워크 구성에 따른 시나리오들은 TCP 경우도 똑같이 적용된다. 예를 들어, TCP 펀칭은 그림 6에서 나오는 다중 레벨의 NAT 경우에 동작한다. 관련된 NAT들이 작동한다면 말이다.

4.5 Sequential Hole Punching

위의 TCP 펀칭 방식의 변형으로 NatTrav 라이브러리 [4] 구현한 것은, 클라이언트들이 동시가 아닌 서로 순차적으로 접속을 시도한다. 예를 들어, (1)A S 통해서 B에게 연결하고 싶다고 말하지만 A 로컬 포트로 동시에 연결을 기다리진(listening) 않는다. (2)B A 향해 connect() 시도하고 이는 B NAT 구멍을 연다. 하지만 이후 타임아웃이나 A NAT, 혹은 A 자신으로 부터의 RST 인해 호출은 실패한다. (3)BS 연결을 닫고 자신의 로컬 포트에 listen() 한다. (4)S 다음으로 A와의 연결을 끊고, 이는 A에게 B 직접 connect() 시도하라는 신호가 된다.

 

순차적 방법은 simultaneous TCP open 제대로 구현하지 못한 XP 서비스 2 이전의 윈도우에서 특히 유용할 있다. 혹은 SO_REUSEADDR 기능을 제대로 지원하지 못하는 소켓 API 경우도 마찬가지이다. 하지만, 순차적 방법은 보다 타이밍 의존적이고 일반적인 경우에 느릴 있으며 일반적이지 않은 상황에서는 튼튼하다. 예를 들어, 스텝 (2)에서 B 반드시 "실패하기로 되어있는" connect() 시도에게 충분한 시간을 주어서 적어도 하나의 SYN 패킷이 자신 쪽의 네트워크에 있는 모든 NAT들을 돌아다닐 있게 해야한다. 너무 짧은 지연 시간은 과정을 실패하게 하는 잃어버린 SYN 위험을 초래할 것이고, 너무 지연 시간은 펀칭을 위해 요구되는 전체 시간을 증가 시킬 것이다. 또한 순차적 펀칭 방식은 양쪽 클라이언트에서 서버 S 연결을 "소모"한다. 이는 새로 만들어져야 P2P 연결마다 클라이언트들이 S 향해 새로운 연결을 열어야 하기 때문이다. 반대로, 평행 펀칭 방식은 전형적으로 양쪽 클라이언트가 밖으로 향하는 connect() 시도를 하자마자 완료된다. 또한 각각의 클라이언트가 S와의 단일 연결을 무기한으로 유지하고 재사용할 있게 한다.

 

5 Properties of P2P-Friendly NATs

섹션은 NAT 위에서 설명된 펀칭 기법이 제대로 작동하기 위해서 반드시 가져야하는 주요 속성들에 대해 설명할 것인다. 모든 NAT 구현들이 속성들을 만족시키진 않지만, 많은 NAT 구현들이 그러하다. 또한 NAT 벤더들이 voice over IP 온라인 게임과 같이 P2P 프로토콜의 요구를 알아감에 따라 NAT들이 점차적으로 "P2P 사이 좋게" 되고 있다.

섹션은 NAT들이 "반드시" 이래야 한다는 완벽한 또는 결정적인 명세를 의도하는 것이 아니다. 우리는 단지 P2P 펀칭을 가능하게 하거나 또는 작동하지 않게 하는 가장 일반적으로 관찰되는 방식들에 대한 정보를 제공할 뿐이다. IETF NAT 작동 방식에 대해 공식적인 "현존하는 최고의 방식들" 정의하기 위해 BEHAVE라는 새로운 작업 그룹을 시작했다. 당연히 NAT벤더들은 공식적인 작동 방식 표준이 체계화 됨에 따라 IETF 작업 그룹을 직접 따라야 한다.

5.1 Consistent Endpoint Translation

여기서 설명된 펀칭 기법은 오직 NAT private 네트워크 상에 주어진 TCP혹은 UDP 소스의 종점을 NAT 의해 조정되는 "하나" public 주소로 일관되게 연관을 시킬 경우에만 자동적으로 작동한다. 이렇게 작동하는 NAT cone NAT라고 RFC 3489 [19] 다른 곳에서 일컬어진다. 왜냐하면 NAT 하나의 private 종점에 기반하는 모든 세션을 NAT상의 같은 public 종점으로 "모으기" 때문이다. (역주 : cone = 깔때기)

 

예를 들어, 그림 5 시나리오를 다시 생각해보자. A 처음 알려진 서버 S 연결 , NAT A 자신만의 IP주소인 155.99.25.11 포트 62000 A 종점을 나타내는 임시 public 종점으로 선택했다. 나중에 A 똑같은 local private 종점으로 부터 B public 종점으로 메세지를 보냄으로써 B 향해서 P2P 세션을 구성하려고 시도할 , A NAT A private 종점의 정체성을 유지하며 존재하는 public 종점 155.99.25.11:62000 재사용하는 것에 의존한다. 왜냐하면, A 위햔 public 종점이 바로 B 자신의 답신 메세지들을 보낼 곳이기 때문이다.

 

오직 클라이언트/서버 프로토콜들만을 지원하기 위해 디자인된 NAT들은 이런 방식으로 private 종점들의 정체성을 보존할 필요가 없다. 이런 NAT들이 RFC 3489 용어법에 있는 symmetric NAT이다. 예를 들어, S 연결된 클라이언트 A 세션에 public 종점 155.99.25.11:62000 할당하고 이후에, NAT 155.99.25.11:62001 같은 다른 public 종점을 B 연결을 시작하려는 P2P 세션에 할당할지도 모른다. 이런 경우, 펀칭은 연결성 제공에 실패한다. 이는 이후에 B에서 들어오는 메세지들이 잘못된 포트 번호로 NAT 도착하기 때문이다.

 

많은 symmetric NAT들이 쉽게 예상할 있는 방식으로 연속되는 세션들에 대해서 포트 번호들을 할당한다. 사실을 이용해서, 펀칭 알고리즘들의 변형들이 [9,1] symmetric NAT들까지 넘나들며 "많은 경우에" 작동하게 만들어질 있다. 이는 STUN [19] 같은 프로토콜을 이용해서 먼저 NAT 작동 방식을 탐색하고 이후에 결과를 이용해서 NAT 다음 세션에 할당할 public 포트 번호를 "예측"하는 것이다. 하지만 이런 예측 기법들은 움직이는 대상을 추적하는 것과 매한가지 이고 와중에 많은 것들이 잘못될 있다. 예를 들어, 예측된 포트가 이미 사용중 이라면 NAT 다른 포트 번호로 점프할 것이다. 또는 같은 NAT뒤에 있는 다른 어플리케이션이 잘못된 타이밍에 세션을 시작하여 예측된 포트가 할당될 있다. 예측 기법이 기존에 제대로 작동하지 않는 NAT들을 상대로 최대한의 호환성을 성취하는데 유용할 있지만, 이것이 장기적으로 확실한 답이 되지는 않는다. Symmetric NAT들이 세션당 트래픽 필터링을 하는 cone NAT 보다 높은 보안성을 제공하지 않기 때문에, NAT 벤더들이 P2P 프로토콜들을 지원하기 위한 그들의 알고리즘을 적용함에 따라 symmetric NAT들은 점점 일반적이 되고 있다.

5.2 Handling Unsolicited TCP Connections

NAT 자신의 public 쪽에서 SYN 패킷을 받았는데 이것이 요청되지 않은 내부로 향하는 연결 시도라면, 그냥 조용히 SYN packet 버리는 것이 중요하다. 어떤 NAT들은 대신에 TCP RST (역주 : connection reset) 혹은 ICMP 에러 보고까지 되돌려 보내면서 이런 안으로 향하는 연결을 적극적으로 거부한다. 이는 TCP 펀칭을 방해하게 된다. 섹션 4.2 있는 펀칭 과정의 번째 스텝에 서술된 바와 같이, 이런 방식은 어플리케이션들이 밖으로 향하는 연결을 다시 시도하는 아주 치명적이지는 않다. 하지만 일시적인 에러들이 발생하는 것이 펀칭 과정을 길게 만들 있다.

 

5.3 Leaving Payloads Alone

현재 소수의 NAT들은 IP주소 처럼 보이는 4byte 값을 패킷으로 부터 "맹목적으로" 스캔하고 이를 패킷 헤더에 있는 IP 주소마냥 해석하는 것으로 알려져있다. 사용중인 어플리케이션 프로토콜의 관해서 아무것도 알지 못한체 말이다. 이런 나쁜 방식은 다행히 일반적이지 않고 어플리케이션들이 자신이 보내는 메세지들에 있는 IP 주소들을 알아보지 못하게 만드는 것으로 방어가 가능하다. 예를 들어, 원하는 IP 주소의 2 보수를 보내는 식이다.

 

5.4 Hairpin Translation

섹션 3.5에서 설명했듯이, 어떤 다중 레벨 NAT 경우에 TCP 혹은 UDP 펀칭이 작동하기 위해서는 hairpin 변환 지원을 요구한다. 예를 들어, 그림 6에서 나온 시나리오는 NAT C hairpin 변환을 지원하느냐에 달려있다. 불행히도 현재 NAT 사이에서는 hairpin 변환이 드믈다. 그러나 다행히도 이것을 요구하는 네트워크 시나리오 역시 드물다. 하지만 IPv4 주소 공간 고갈이 계속됨에 따라 다중 레벨 NAT 점점 일반적이 되고있다. 따라서 미래의 NAT 구현에서 hairpin 변환 지원은 중요하다.

6 Evaluation of Existing NATs

문서에서 설명된 TCP UDP 펀칭 기법의 현존하는 다양한 NAT들에 대한 튼실함을 평가하기 위해, 우리는 NAT Check [16]라고 불리는 테스트 프로그램을 개발하고 배포하였다. 또한 인터넷 사용자들에게 그들의 NAT 관한 데이터를 요청하였다.

 

NAT Check 주요 목적은 안정적인 UDP TCP 펀칭을 위해 가장 중요한 가지 행동 속성들을 테스트 하는 것이다. 종점 변환시 일관된 정체성 보존 (섹션 5.1) 요구되지 않은 내부로 향하는 TCP SYN들을

RST ICMP 에러로 거부하는 대신에 그냥 조용히 버리는 (섹션 5.2) 가지이다. 여기다 더해, NAT Check 따로 NAT 헤어핀 변환(섹션 5.4) 지원하는지, 그리고 NAT 요구되지 않은 내부로 향하는 트래픽을 완전히 차단하닌지 여부도 테스트한다. 마지막 속성은 펀청에 영향을 주지는 않지만 NAT 방화벽 규정에 대해 유용한 정보를 제공한다.

 

NAT Check NAT 행동 개개의 모든 면을 테스트하려고 하지 않는다. 이들은 매우 다양하고 미묘한 차이점들이 있음이 알려져 있고, 또한 그중의 어떤 것들은 믿을 만한 테스트를 하기가 어렵다. [12] 대신에, NAT Check 단지 "제안된 펀칭 기법들이 전형적인 네트워크 조건들 아래, 이미 출시된 NAT들서에서 얼마나 일반적으로 작동할 것인가?" 라는 질문에 답변하려고 한다.

 

6.1 Test Method

NAT Check 테스트 하려는 NAT 뒤에 있는 컴퓨터에서 실행되는 클라이언트 프로그램과 각각 다른 전역 IP 주소를 가진 세개의 알려진 서버들로 구성되어있다. 클라이언트는 TCP UDP 펀칭에 관련된 NAT 작동 방식을 체크하기 위해 개의 서버와 협동한다. 클라이언트 프로그램은 작고 상대적으로 이식성이 있다. 현재 Windows, Linux, BSD, 그리고 Mac OS X 에서 실행된다. 알려진 서버들을 실행하는 컴퓨터들은 모두 FreeBSD 사용한다.

 

6.1.1 UDP Test

UDP 위한 NAT 행동 방식을 테스트하기 위해서, 클라이언트는 소켓을 하나 열고 지역 UDP 포트를 할당한다. 그리고 그림 8에서 나온바와 같이 연속해서 ping 같은 요청을 서버 1 서버 2 보낸다. 서버들은 각각 클라이언트의 ping 대한 클라리언트의 public UDP 종점(서버에서 보는 클라이언트의 IP 주소와 UDP 포트 번호) 담은 답변을 회산한다. 만약 서바가 모두 같은 public 종점을 클라이언트에게 보고하면, NAT Check NAT 클라이언트의 private 종점에 대한 정체성을 적절하게 보존하고 있다고 여긴다. 믿을 만한 UDP 펀칭을 위한 주요 선행조건이 만족된다고 말이다.

Figure 8: NAT Check Test Method for UDP

서버 2 UDP 요청을 클라이언트로 부터 받았을 , 클라이언트게 직접 회신하는 것과 함께 해당 요청을 서버 3에게 보낸다. 다음에 서버 3 자신의 IP 주소로 부터 클라이언트로 회신을 한다. 만약 NAT 방화벽이 제대로 각각의 세선에 대해서 "요청되지 않은" 내부로 향하는 트래픽을 차단한다면, 비록 답신이 서버 1 서버 2에서 오는 답신과 똑같은 public 포트로 향한다고 하더라도 클라이언트 절대 서버 3으로부터의 답신을 볼수가 없다.

 

NAT hairpin 변환을 지원하는지 테스트하기 위해서, 클라이언트는 간단히 두번째 UDP 소켓을 다른 포트번호로 열고 이를 사용해서 클라이언트의 첫번째 UDP 소켓의 public 종점 (서버 2 알려준) 으로 향해 메세지를 보낸다. 만약 메세지가 클라이언트의 첫번째 private 종점에 도착하면 이는 NAT hairpin 변환을 지원한다는 것이다.

6.1.2 TCP Test

TCP 테스트도 UDP 비슷한 형식을 취한다. 클라이언트는 하나의 로컬 TCP 포트를 이용하여 서버 1 2에게 밖으로 향하는 세션을 시작한다. 그리고 서버 1 2에서 보고되는 public 종점들이 같은지를 확인한다. 이는 믿을 만한 TCP 펀칭을 위한 첫번째 선행 조건이다.

 

조건을 만족한다고 하여도 안으로 향하는 요청되지 않은 연결 시도에 대해 NAT 반응하는 방식이 TCP 펀칭의 속도와 신뢰성에 영향을 미치기 때문에, NAT Check 또한 테스트한다. 서버 2 클라이언트의 요청을 받았을 , 클라이언트로 바로 답변을 보내는 대신에 요청을 서버 3에게 전달하고 서버 3 "이제 출발" 신호를 보낼 때까지 기디란다. 서버 3 전달된 요청을 받으면 클라이언트의 public TCP 종점을 향해서 안으로 향하는 연결을 시도 하고 연결이 성공하거나 실패할 때까지 5초간 기다린다. 이후 서버 2에게 "이제 출발"이라는 신호를 보내고 최대 20초까지 다시 기다기를 계속한다. 클라이언트가 마침내 서버 2 답변( 서버 2 서버 3 "이제 출발" 신호를 기다리며 지연시킨 ) 받게 되면, 클라이언트는 서버 3에게 밖으로 향하는 연결을 시도하고 이는 결과적으로 서버 3과의 simultaneous TCP oepn 발생시킨다.

 

테스트 과정 중에 어떤 일이 일어나는지는 다음에 나오는 NAT 방식에 따라 달라진다. 만약 NAT 제대로 서버 3 안으로 향하는 "요청되지 않은" SYN 패킷을 버려준다면, 서버 2 클라이언트에게 답신하기 전의 5 동안에 클라이언트의 listen 소켓에서는 아무 일도 일어나지 않는다. 클라이언트가 마침내 서버 3으로 향하는 자신만으 연결을 시작했을때, NAT 통하는 구멍을 열면서 연결 시도는 바로 성공하게 된다. 이와 달리, 만약 NAT 서버 3 SYN 버리지 않고 그냥 통과시켜주면 ( 펀칭을 위해선 좋지만 보안을 위해서는 이상적이지 않다.), 서버 2 답신을 받기 전에 클라이언트는 자신의 listen 소켓에서 안으로 향하는 TCP 연결을 받게 된다. 끝으로, 만약 NAT 적극적으로 서버 3 SYN TCP RST 패킷들을 보내면서 거부하게 되면, 서버 3 포기를 하고 클라아언트의 이어지는 서버 3으로의 연결시도도 실패한다.

 

TCP 경우의 hairpin 변환을 테스트하기 위해, UDP 경우와 동일한 방법으로 클라이언트는 두번째 local TCP port 이용해서 자신의 첫번째 TCP 포트에 해당하는 public 종점을 향해 연결을 시도한다.

6.2 Test Results

우리가 모은 NAT Check 데이터는 68개의 다른 벤더들로부터 나온 다양한 NAT들을 포함하는 380개의 리포트로 구성되어있다. 또한 NAT 기능들은 여러 다른 버전의 8개의 인기있는 운영체제에 구현되어있다. 오직 이중에 335개의 리포트만 UDP hairpin 변환에 대한 결과를 포함하고 있고 286개만이 TCP 위한 결과를 가지고 있다. 이는 우리가 이미 결과들을 모으기 시작한 이후에 기능을 NAT Check 후기 버전에서 구현했기 때문이다. 데이터 결과는 NAT 벤더 별로 테이블 1 정리되어있다. 테이블은 최소 5 이상의 데이터가 유효한 개개의 벤더들만 보여준다. 결과에서 주어진 하나의 벤더에 대한 다양성은 여러가지 요소들로 부터 설명될 있다. 예를 들어, 같은 벤더의 다른 NAT 디바이스 또는 다른 상용 제품 라인, 같은 NAT 구현에 다른 소프트웨어 혹은 다른 펌웨어 버전, 다른 구성, 그리고 혹은 가끔 일어나는 NAT Check 테스트, 보고 에러등이 이런 요소들이다.

   

UDP

TCP

   

Hole

 

Hole

 
   

Punching

Hairpin

Punching

Hairpin

NAT Hardware

               
 

Linksys

45/46

(98%)

5/42

(12%)

33/38

(87%)

3/38

(8%)

 

Netgear

31/37

(84%)

3/35

(9%)

19/30

(63%)

0/30

(0%)

 

D-Link

16/21

(76%)

11/21

(52%)

9/19

(47%)

2/19

(11%)

 

Draytek

2/17

(12%)

3/12

(25%)

2/7

(29%)

0/7

(0%)

 

Belkin

14/14

(100%)

1/14

(7%)

11/11

(100%)

0/11

(0%)

 

Cisco

12/12

(100%)

3/9

(33%)

6/7

(86%)

2/7

(29%)

 

SMC

12/12

(100%)

3/10

(30%)

8/9

(89%)

2/9

(22%)

 

ZyXEL

7/9

(78%)

1/8

(13%)

0/7

(0%)

0/7

(0%)

 

3Com

7/7

(100%)

1/7

(14%)

5/6

(83%)

0/6

(0%)

OS-based NAT

               
 

Windows

31/33

(94%)

11/32

(34%)

16/31

(52%)

28/31

(90%)

 

Linux

26/32

(81%)

3/25

(12%)

16/24

(67%)

2/24

(8%)

 

FreeBSD

7/9

(78%)

3/6

(50%)

2/3

(67%)

1/1

(100%)

All Vendors

310/380

(82%)

80/335

(24%)

184/286

(64%)

37/286

(13%)

 

Table 1: User Reports of NAT Support for UDP and TCP Hole Punching

 

UDP 해당하는 전체 380개의 데이터중 310(82%) 경우에서 NAT 일관적으로 클라이언트의 private 종점을 변환하는 것으로 나타났다. UDP 펀칭과의 기본 호환성을 보여주는 것이다. 하지만 이에 비해 hairpin 변환의 경우 일반성이 매우 떨어지는데, UDP hairpin 변환의 결과를 포함하는 335개의 데이터중에 오직 80 (24%) 만이 hairpin 변환을 지원한다고 나왔다.

 

TCP 해당하는 전체 286개의 데이터중에 184 (64%) TCP 펀칭과의 호한성을 보여준다. 다시 말해서 NAT 일관적으로 클라이언트의 private TCP 종점을 변환하고 안으로 향하는 요청되지 않은 연결에 대해서 RST 패킷을 회신하지 않는 다는 것이다. Hairpin 변환은 역시 일반성이 많이 떨어지는데 오직 37 (13%) 결과만이 TCP 대한 hairpin 지원을 한다고 나왔다.

 

결과들은 자원자들의 "스스로 선택한" 커뮤니티에 의해서 만들어졌기 때문에, 이들은 랜덤한 샘플들로 이루어져 있지도 않고 따라서 일반적으로 쓰이는 NAT들의 분포 상황을 맞게 보여주지도 않는다. 그럼에도 불구하고 결과들은 고무적이다. 대다수의 일반적으로 출시된 NAT들이 이미 적어도 싱글 NAT 레벨의 경우에 UDP TCP 펀칭을 지원하는 것으로 나타나기 때문이다.

6.3 Testing Limitations

NAT Check 현재 테스트 프로토콜은 어떤 경우에 결과를 잘못 이끌수 있는 가지 한계점을 가지고 있다. 먼저 우리는 최근에 몇몇 NAT 구현들이 알지도 못하는 어플리케이션의 메세지에서 맹목적으로 IP 주소를 변환한다는 것을 알게 되었다. 현재 NAT Check 프로토콜은 전달하는 IP 주소를 암호화 하지 않으므로 이런 현상으로 부터 보호되지 않는다.

 

둘째로, NAT Check 현재 hairpin 변환 체크는 불필요하게 부정적인 결과를 초래할 수도 있다. 이는 테스트를 위해 완전한 양방향 펀칭 방식을 이용하지 않기 때문이다. 현재 NAT Check hairpin 변환을 지원하는 NAT NAT public 쪽에서 오는 안으로 향하는 연결을 차단하는 것과 다르게 자신의 private 네트워크에서 오는 hairpin 연결은 차단하지 않는다고 가정한다. 왜냐하면 이런 차단은 보완을 위해 불필요하기 때문이다. 하지만 나중에 우리는 NAT 단순히 모든 자신의 public 포트로 향하는 트래픽을 이것의 진원지와는 상관없이 "믿을 없는" 것으로 여길지도 모른다는 것을 알게 되었다. 우리는 아직 어떤 방식이 보다 일반적인지 모른다.

 

끝으로, NAT 클라이언트가 오직 하나만 있을 때는 클라이언트의 private 종점을 특정한 private 포트로 일관적으로 변환하지만, 만약 두개 혹은 이상의 클랑이언트들이 private 네트워크에서 다른 IP 주소를 가지고 같은 private 포트 번호로 NAT 통해서 통신하려고 할때는 symmetric NAT 혹은 보다 안좋은 방식으로 바뀌는 NAT 구현들이 존재한다. NAT Check 사용자에게 두개 혹은 이상의 클라이언트 호스트를 NAT 뒤에서 동시에 돌릴 것을 요구해야만 이런 방식을 감지할 있다. 하지만 NAT뒤에 하나의 사용가능한 PC 가지고 있는 사용자에게는 불가능한 일이다. 그럼에도 불구하고, 우리는 실험 기능을 미래의 NAT Check 버전에 옵션으로 구현할 계획을 하고 있다.

 

6.4 Corroboration of Results

위에서 나온 것과 같은 테스트의 어려움에도 불구하고, 우리의 결과들은 전체적으로 ISP 의해서 보강되어졌다. ISP 그들의 네트워크에 86% NAT 차지하고 있는 3개의 라우터 NAT 벤더들이 모두 UDP 펀칭과 호환이 되는 NAT들을 생산하고 있다는 것을 발견했다 [25]. UDP 종속적인 STUN 프로토콜 [12] 이것의 TCP 확장 버전인 STUNT [8,9] 사용하여 추가로 얻어진 독립적인 결과들 또한 우리의 결과와 일치하는 것으로 드러났다. 이런 후기 연구들은 NAT Check 하듯이 단순히 기본적인 펀칭 호환성만을 테스트하는 대신에, 보다 넓게 다양한 방식들을 하나 하나 테스트하여, 각각의 NAT 대해 보다 많은 정보를 제공한다. 하지만 이렇게 확장된 테스트들은 다수의 클라이언트들이 NAT뒤에서 협력해야 하고 따라서 실행되기가 어렵기 때문에, 현재까지는 보다 제한된 NAT들에 대해서만 결과들이 유효하다.

7 Related Work

UDP 펀칭은 최초로 Dan Kegel [13] 의해서 조사되어지고 공개적으로 문서화되었으며 이는 지금까지 P2P 어플레이케이션 커뮤니티에 널리 알려져있다. UDP 펀칭의 중요한 면들 역시 여러 실험적인 프로토콜들의 명세서에서 간접적으로 문서화가 되어왔다. 이런 프로토콜들로는 STUN[19], ICE [17] 그리고 Teredo [11] 등이 있다. 하지만 우리는 펀칭을 완전히 분석하거나 다중 레벨 NAT (섹션 3.5)에서의 hairpin 변환 문제등을 지적하는 공개된 작업물은 지금까지 없는 것으로 안다.

 

또한 우리 이전에 TCP 펀칭을 여기서 설명한 것과 같이 symmetric 방식으로 개발한 작업물도 없는 것으로 알고 있다. 심지어 버클리 소켓 API 있는 SO_REUSEADDR/SO_REUSEPORT 옵션들의 중요성조차도 P2P 어플레케이션 개발자들 사이에서 거의 알려지지 않았다. NatTrav [4] 비슷하지만 이는 앞서 섹션 4.5에서 언급한 asymmetric TCP 펀칭을 구현했다. NUTSS [9] NATBLASTER [1] 섹션 5에서 언급 나쁜 NAT 작동 방식에 대해서도 동작이 되는 보다 복잡한 TCP 펀칭을 구현했다. 하지만 이들은 랑데뷰 서버가 소스 IP 주소들을 속여야 하며 또한 클라이언트 어플리케이션들이 "생짜(raw)" 소켓들을 만져야 한다. 이는 대개 오직 루트나 관리자의 특권이 있어야 가능한 것이다.

 

SOCKS [14], UPnP [26], 그리고 MIDCOM [22] 같은 프로토콜들은 명시적으로 NAT 협동을 통해서 어플리케이션들이 NAT 선회할 있게 해준다. 하지만 프로토콜들은 NAT 벤더들에의해 일관적 혹은 널리 지원되지 않고 있다. 또한 증가하고 있는 다중 레벨 NAT 경우를 해결하는 것으로 보이지 않는다. 명시적으로 NAT 조정하는 것은 어플리케이션에게 NAT 찾고, 아마 스스로 인증 것을 요구할 것이다. 이는 대개 사용자 구성과 연관되어있다. 반대로 펀칭이 작동하는 경우에는, 아무런 사용자 간섭없이 작동한다.

 

HIP [15] FARA [2] 같은 최근의 제안들은 호스트의 주체성(identity) 위치의 연관성을 끊는 방식으로 인터넷의 기본 구조를 확장한다 [20]. IPNL [7], UIP [5,6] 그리고 DOA [27] 이런 식의 구조에서 NAT 가로지르는 방식을 제안한다. 길게 보면 아마 이런 확장성들이 필요할 것이지만, 펀칭은 지금 현존하는 네트워크 기반에서 어떤 프로토콜 스택의 업그레이드 없이 어플리케이션이 작동하게 해준다. 그리고 어플리케이션이 정의 하는 "호스트 주체성(identity)"이라는 개념을 남겨둔다.

8 Conclusion

펀칭은 NAT 존재할 P2P 연결을 구성하는 다목적의 기술이다. 연관된 NAT 요구되는 개의 방식만 따라준다면, 펀칭은 TCP UDP 모두의 경우에 일관적이고 튼실하게 작동한다. 그리고 어떤 특별한 권한이나 특수한 네트워크 망과 상관없이 일반적인 어플리케션들에 의해 구현될 있다. 펀칭은 완전한 투명성을 유지하는데 이는 가장 중요한 NAT 특징과 장점들중에 하나다. 또한 다중 레벨의 NAT에서도 작동한다. (비록 몇몇 문제 상황이 아직 널리 구현되어있지 않은 NAT 특성인 hairpin 변환을 요구하지만. )

Acknowledgments

우리 작가들은 섹션 6 나오는 결과들을 모으는데 중요한 지원을 해준 Dave Andersen에게 감사를 전한다. 또한 Henrik Nordstrom, Christian Huitema, Justin Uberti, Mema Roussopoulos 그리고 익명의 USENIX 리뷰어들에게도 문서의 초본에 대해 값진 피드백을 것에 감사한다. 끝으로 NAT Check 사용해서 우리에게 결과를 보내준 많은 자원자들 모두에게 감사한다.

Bibliography


1
Andrew Biggadike, Daniel Ferullo, Geoffrey Wilson, and Adrian Perrig.
NATBLASTER: Establishing TCP connections between hosts behind NATs.
In ACM SIGCOMM Asia Workshop, Beijing, China, April 2005.

2
David Clark, Robert Braden, Aaron Falk, and Venkata Pingali.
FARA: Reorganizing the addressing architecture.
In ACM SIGCOMM FDNA Workshop, August 2003.

3
S. Deering and R. Hinden.
Internet protocol, version 6 (IPv6) specification, December 1998.
RFC 2460.

4
Jeffrey L. Eppinger.
TCP connections for P2P apps: A software approach to solving the NAT problem.
Technical Report CMU-ISRI-05-104, Carnegie Mellon University, January 2005.

5
Bryan Ford.
Scalable Internet routing on topology-independent node identities.
Technical Report MIT-LCS-TR-926, MIT Laboratory for Computer Science, October 2003.

6
Bryan Ford.
Unmanaged internet protocol: Taming the edge network management crisis.
In Second Workshop on Hot Topics in Networks, Cambridge, MA, November 2003.

7
Paul Francis and Ramakrishna Gummadi.
IPNL: A NAT-extended Internet architecture.
In ACM SIGCOMM, August 2002.

8
Saikat Guha and Paul Francis.
Simple traversal of UDP through NATs and TCP too (STUNT).
http://nutss.gforge.cis.cornell.edu/.

9
Saikat Guha, Yutaka Takeday, and Paul Francis.
NUTSS: A SIP-based approach to UDP and TCP network connectivity.
In SIGCOMM 2004 Workshops, August 2004.

10
M. Holdrege and P. Srisuresh.
Protocol complications with the IP network address translator, January 2001.
RFC 3027.

11
C. Huitema.
Teredo: Tunneling IPv6 over UDP through NATs, March 2004.
Internet-Draft (Work in Progress).

12
C. Jennings.
NAT classification results using STUN, October 2004.
Internet-Draft (Work in Progress).

13
Dan Kegel.
NAT and peer-to-peer networking, July 1999.
http://www.alumni.caltech.edu/~dank/peer-nat.html.

14
M. Leech et al.
SOCKS protocol, March 1996.
RFC 1928.

15
R. Moskowitz and P. Nikander.
Host identity protocol architecture, April 2003.
Internet-Draft (Work in Progress).

16
NAT check.
http://midcom-p2p.sourceforge.net/.

17
J. Rosenberg.
Interactive connectivity establishment (ICE), October 2003.
Internet-Draft (Work in Progress).

18
J. Rosenberg, C. Huitema, and R. Mahy.
Traversal using relay NAT (TURN), October 2003.
Internet-Draft (Work in Progress).

19
J. Rosenberg, J. Weinberger, C. Huitema, and R. Mahy.
STUN - simple traversal of user datagram protocol (UDP) through network address translators (NATs), March 2003.
RFC 3489.

20
J. Saltzer.
On the naming and binding of network destinations.
In P. Ravasio et al., editor, Local Computer Networks, pages 311-317. North-Holland, Amsterdam, 1982.
RFC 1498.

21
P. Srisuresh and M. Holdrege.
IP network address translator (NAT) terminology and considerations, August 1999.
RFC 2663.

22
P. Srisuresh, J. Kuthan, J. Rosenberg, A. Molitor, and A. Rayhan.
Middlebox communication architecture and framework, August 2002.
RFC 3303.

23
Transmission control protocol, September 1981.
RFC 793.

24
G. Tsirtsis and P. Srisuresh.
Network address translation - protocol translation (NAT-PT), February 2000.
RFC 2766.

25
Justin Uberti.
E-mail on IETF MIDCOM mailing list, February 2004.
Message-ID: <402CEB11.1060906@aol.com>.

26
UPnP Forum.
Internet gateway device (IGD) standardized device control protocol, November 2001.
http://www.upnp.org/.

27
Michael Walfish, Jeremy Stribling, Maxwell Krohn, Hari Balakrishnan, Robert Morris, and Scott Shenker.
Middleboxes no longer considered harmful.
In USENIX Symposium on Operating Systems Design and Implementation, San Francisco, CA, December 2004.



Edit this page (if you have permission) | Report abuse

Google Docs -- Web word processing, presentations and spreadsheets.

'Program RFC/Algorithm' 카테고리의 다른 글

홀펀칭 화상통화...등등  (0) 2012.01.04
RTCP-SR 에서 ntp timestamp  (0) 2011.11.14
Hole Puching  (0) 2011.08.31