p2p network

|
<< 머리말 >>
네트워크 응용 수업의 최종과제가 홀펀칭(Hole Punching) 기술로 구현한 에코 클라이언트의 구현이라,
게임프로그래밍이나 여러 P2P 프로그래밍에서 폭넓게 사용되는 기술이라고 한다.
일단은 프로그래밍을 해야 하는데 생소한 정보들이여서 몇몇 관련문서를 보고 이해를 하려고 노력해 보았다.

<< 개념 >>
NAT(Network Address Translator)가 뭔지 알지? 공유기같은거 말하는데,
hole punching은 NAT traversal 알고리즘 중에 하나거든. 이런 traversal 알고리즘 중에
현재 가장 간단하고 강력해서 hole punching을 사용한덴다.

p2p를 이용하려면 이 NAT traversal은 꼭 필요한 기술이야. 유저들의 네트워크 상황은
매우 다양하고 요즈음은 공유기 안에 물려있는 유저들도 많거든.

211.23.49.32:80 이런 주소로 패킷을 보내는 상황을 생각해 보자. 저 IP 주소가 global하게
unique한 IP라면 즉, public address라면 어떤 상황에 있는 호스트라도 저 IP주소를
찾아 갈 수 있어. 저 IP를 가진 컴퓨터는 전세계에 한대 뿐이고, 또 라우터가 다 찾아줄테니까.

공유기를 사용하는 컴퓨터는 IP주소가 10.0.0.1 이런 식으로 공유기가
할당하는 가상 IP를 부여 받게 되잖아. 그럼 다른 컴퓨터는 이 IP를 찾아 갈 수가 없어.
이유는.. 저 IP는 아마 라우팅이 안되게 되있던지.. 뭐 그런식이겠지.
하지만 p2p를 하려면 어쨋든 저쪽 컴퓨터까지 packet을 전송해야돼.
그러기 위해서는 공유기(NAT)의 IP를 알아야하지. 왜냐하면 공유기를 사용하는 컴퓨터들은
NAT에 연결된 public address의 IP,port에 매핑이돼. 매핑되는 방식은 공유기 type마다
다양해서 hole punching이 어려운 공유기도 존재하지..지금은 일반적은 NAT만
생각해 보자.

그림을 그려보면,

----NAT-----
| 211.23.49.32 |
-------------
| |
port: port:
31000 62000
| |
| |
host1 host2
10.0.0.1 10.0.0.2

위 그림은 host1이 가상아이피 10.0.0.1을 부여받고 이는 실제 211.23.49.32:31000의 public address와 매핑되어 있는 그림이야. host2도 비슷한 방식으로 62000port와 매핑되어 있고,

그럼 만약, 다른 host3(210.24.39.22)가 host1에게 packet을 전송하기 위해서는
211.23.49.32:31000으로 전송하면 되겠지... 그럼 NAT가 알아서 패킷을 받아서 알맞은 호스트(host1)로 relay를 해주게 되니까. NAT의 하나의 port에 매핑되는게 host1의 모든 소켓이 하나의 port를 가지느냐? host1이 소켓을 생성할때마다 다른 port를 할당 받느냐는 NAT type마다 달라.

이제 hole punching을 설명하면,
host3이 host1로 packet을 보내는 방법은 이제 알았잖아. host1이 매핑된 NAT의 주소로 packet을 보내면 되니까.(이 주소를 아는 방법은 다른 서버를 둬서 관리하는 방법을 써)
그런데 그냥 packet을 보내면 보안상의 이유로 NAT가 이 packet을 drop시켜. 즉, 일반적으로 NAT는 자신이 보낸 주소에서 오는 packet들만 받아들이게 돼. 이건 NAT안의 host들은
대부분 서버가 되지 않기 때문에, 그렇게 해둔거 같아. 그럼 host1이 host3의 packet을
받기 위해서는 host1이 210.24.39.22로 packet을 보내야돼. dummy packet같은걸.
그러면 NAT는 210.24.39.22 를 table에 등록하고 이곳에서 부터 오는 packet을 drop시키지않고
host1로 전해주게 되지.
여기서 dummy packet을 보내서 host들 간에 연결 구멍(hole)을 만드는 과정을 hole punching
이라고해. 구멍 뚫기지. NAT가 오래동안 안쓴 hole은 다시 막아버리니까 주기적으로 punching을 해주어야해(주기적으로 dummy packet을 보내야해)

NAT type마다 hole punching이 안되는 경우도 있고, NAT안에 NAT가 있는 경우등은
글이 넘 길어지는거 같기도하고 귀찮기도 하고 -0-. 담에 궁금하다하면 글 쓸게.

아, UDP와 TCP둘다 hole punching방법은 같은데, UDP가 더 잘 뚫려. 그래서
p2p를 하면 거의 UDP소켓을 써. TCP도 안될 이유는 없는데 NAT내부의 호스트가
TCP Server가 못되도록 packet 자체를 막는 경우가 있는가 보더라.
그래서 UDP로 하면 reliable등 더 신경써 줄게 많아
<< 본문 >>
0. 들어가기 전 알아두어야 할 용어들.
- NAT [Network Address Translation]
OSI 모델의 3계층인 네트워크 계층에서 사설 IP 주소를 공인 IP 주소로 변환하는데 사용하는 통신망의 주소 변환기.
http://100.naver.com/100.nhn?docid=717874
우리가 흔히 말하는 공유기, 라우터 등이 이런 역할을 수행한다고 보면 된다.


1. 개요
Hole Punch 란 종이에 철을 하기 위해 동그란 구멍을 뚫어주는 사무용 기기이다.
그런 개념으로 접근하여 막힌 뭔가를 뻥 뚫어준다는 것으로 이해하고 출발하여 보자.
일단은 P2P 연결을 위한 여러 기술들을 알아보기로 한다. (홀 펀칭은 그 중의 하나이므로..)



2. 이해
- 전제 : 통신을 하기 위한 Client A와 Client B가 존재하며경우에 따라 NAT아래 놓일 수 있다.
이들의 통신을 중계하기 위한 Server S가 존재한다.
NAT과의 P2P 커뮤니케이션하기 위해서는 몇가지의 기술이 있다.
Relaying, Connection Reversal, UDP Hole Punching, UDP Port Number Prediction, Simultaneous TCP Connection Initiation 이 그것이다.
일단 Relaying부터 살펴보도록 하자.


3. 기술
3.1 Relaying

 

Relaying은 간단히 중계 서버를 두고 중계 서버를 통해 통신을 한다.
A가 서버 S에게 메세지를 보내고 서버 S는 B에게 메세지를 보낸다.
A와 B가 서버에 접속이 유효한 동안은 메세지를 계속 주고 받을 수 있다.
하지만 불필요한 대역폭의 낭비와 서버의 리소스를 소모하게 된다.



3.2 Connection Reversal
 

이 경우는 하나의 클라이언트가 NAT뒤에 위치해 있는 경우이다.
B가 A와의 연결을 하고자 할때 A믜 사설IP로는 당연히 접속이 불가능하고, 서버 S가 관찰하는 NAT의 공인 IP로의 접속은 A에서 나가는 것만 허용하기 때문에 역시 접속이 불가능하다.
그래서 중계 서버 S를 이용해 "내가 못가니까 니가 나와라" 고 해서 B의 공인 IP를 서버 S에게 알려 준 다음 역으로 A가 접속을 시도하여 커넥션을 맺게 하는 방식이다.


3.3 UDP Hole Punching
 


이 경우는 두 클라이언트가 전부 NAT 뒤에 있는 경우이다.
여기서 두 클라이언트가 같은 NAT 뒤에 있는가 혹은 다른 NAT 뒤에 있는가로 다시 경우가 나뉘어 진다.



3.3.1 두 클라이언트가 다른 NAT 뒤에 있을 때.

클라이언트 A가 B와 커넥션을 맺고 싶을 떄 일반적으로는 3.2의 경우와 같이 커넥션이 맺어지지 않으므로 중계서버 S를 이용하여야 한다.
서버 S에 접속할때 서버는 클라이언트 A의 정보 (사설,공인 IP)를 취득하여 저장하게 되고 B가 접속할때도 이 정보를 저장하게 된다.
그리고 만약 A가 B에 대해서 연결을 요청하게 되면 중계서버 S는 A와 B에게 동시에 서로의 IP 정보를 보내 주게 되고 커넥션 희망여부를 전달받은 각 클라이언트는 각각 연결 시도를 하게 되어 커넥션이 맺어질 수 있게 된다.

- 추가사항 : UDP 커넥션의 경우에는 지속적인 핑퐁 메세지가 없으면 연결이 끊어질수 있기 때문에 일정간격으로 연락을 해 주어야 한다. NAT의 종류에 따라서 되는것도 있고 안되는것도 있다고 한다..(성공 확률 분포 등에 대한 자료는 PDF문서 참조)

일단 기본적인 기술은 여기까지 이해하고 나머지 추가적인 기술과 내용들은 아래의 주소에서 더 확인이 가능하다.
(사실 이거 이해를 하려고 꽤나 머리를 싸맸다. 아직 확실한지는 잘 모르겠지만서도 -_-)


출처: http://devdbref.tistory.com/14 [PHP 및 웹 관련]

 

---------------------------------------------------------------------------

 

https://www.netmanias.com/ko/post/blog/6264/nat-network-protocol-p2p/p2p-nat-nat-traversal-technic-rfc-5128-part-1-relaying-connection-reversal

 

오늘은 사설 IP 주소를 가지는 두 단말 간에 P2P 통신이 가능하도록 하는 기술(NAT Traversal이라 부름)에 대해 소개 해 드리겠습니다.
RFC 5128(State of P2P Communication across NATs - Informational)에서 설명하고 있는 NAT Traversal 기술은 크게 3가지입니다.

  • Relaying
  • Connection Reversal
  • UDP Hole Punching

 

이번 시간에는 Relaying과 Connection Reversal에 대해서 알아보고 다음 시간에 UDP Hole Punching에 대해서 설명 드리도록 하겠습니다.
P2P (NAT Traversal) 입장에서 가장 곤혹스러운 NAT Behavior가 Address and Port-Dependent Mapping(이하 APDM) & Address and Port-Dependent Filtering(이하 APDF) 입니다. 오늘 소개해 드릴 Relaying과 Connection Reversal 모두 적용의 한계(문제점)가 있기는 하지만 위 방식의 NAT Behavior에서도 NAT Traversal이 가능한 기술입니다. 

 

1. Relay​ing

 

 

■ 개념

  • Relaying 방법은 사설 IP 주소를 가지는 두 단말 간에 직접 통신을 할 수 없다면 공인 IP 주소를 가지는 외부 서버를 통해 P2P 데이터 패킷을 Relay하자는 개념입니다.
  • Host A와 Host B는 사설 IP 주소를 가지고 있고, Server S(Relay 서버 혹은 표준에서는 Rendezvous Server라 칭함)는 반드시 공인 IP 주소를 가져야 합니다.

■ 절차

  1.   Host A와 B는 각각 Server S로 TCP 혹은 UDP 연결 메시지(Registry Session)를 보냅니다.
  2.  

이 메시지들은 NAT A/B를 통과해 Server S로 도달하여 Host A와 Server S, Host B와 Server S간에 TCP 혹은 UDP 연결이 이루어집니다. 또한 NAT A/B에는 다음과 같이 Binding Entry와 Filtering Entry가 생성됩니다.

  • NAT A
    • Binding Entry: {Internal IP:Internal Port, External IP:External Port} = {10.1.1.1:4000, 5.1.1.1:60000}
    • Filtering Entry: Allow Inbound Packet if Source info {100.1.1.1:1234}, Destination info {5.1.1.1:60000}
  • NAT B
    • Binding Entry: {Internal IP:Internal Port, External IP:External Port} = {10.2.2.2:5000, 6.2.2.2:30000}
    • Filtering Entry: Allow Inbound Packet if Source info {100.1.1.1:1234}, Destination info {6.2.2.2:30000}
  3.   이제 Server S는 Host A/B의 Public IP/Port 정보(NAT에 의해 변환된 정보)를 알수 있게 됩니다.
  4.   Host A는 2번 과정에서 생성된 연결을 통해 Server S로 P2P 데이터 패킷을 보내는데, 이 때 해당 패킷의 Payload에는 목적지 주소 6.2.2.2가 포함되며 (참고: Peer 목적지 주소 6.2.2.2를 알아내는 방법에 대해서는 표준에 정의되어 있지 않음),
  5.   이 패킷은 NAT A를 통과하여 Server S가 수신합니다.
  6.   Server S는 수신 패킷의 Payload를 통해 목적지 주소를 알아낸 후, 역시 2번 과정에서 생성된 연결을 통해 Host B로 P2P 데이터 패킷을 송신(릴레이)하며 이 때 Host B가 패킷을 수신 할 수 있도록 다음과 같이 패킷 정보를 변경합니다.
  • [IP Header] Destination IP: 100.1.1.1 -> 6.2.2.2, Source IP: 5.1.1.1 -> 100.1.1.1
  • [TCP/UDP Header] Destination Port: 1234 -> 30000, Source Port: 60000 -> 1234
  • [Payload] Peer 정보(6.2.2.2) 필드 제거
  7.   NAT B는 다음과 같은 과정을 거쳐 수신 패킷을 Host B로 전달합니다.
  • Check Filtering Table: 수신 패킷의 정보와 Filtering Entry가 일치하므로 이 패킷을 허용
    • 수신 패킷 정보: Source info {100.1.1.1:1234}, Destination info {6.2.2.2:30000}
    • Filtering Entry: Allow Inbound Packet if Source info {100.1.1.1:1234}, Destination info {6.2.2.2:30000}
  • Check Binding Table: 수신 패킷의 목적지 정보가 Binding Entry와 일치하여 목적지 정보를 {6.2.2.2:30000}에서 {10.2.2.2:5000}으로 변경
    • 수신 패킷의 목적지 정보: {6.2.2.2:30000}
    • Binding Entry: {Internal IP:Internal Port, External IP:External Port} = {10.2.2.2:5000, 6.2.2.2:30000}

■ 장점

  • NAT의 동작 특성(NAT Behavior)에 상관없이 100% NAT 통과 성공율을 자랑합니다.
    • 지원 NAT Mapping Behavior: Endpoint-Independent Mapping, Address-Dependent Mapping, Address and Port-Dependent Mapping
    • 지원 NAT Filtering Behavior: Endpoint-Independent Filtering, Address-Dependent Filtering, Address and Port-Dependent Filtering

■ 단점

  • 모든 P2P 데이터 패킷이 Relay 서버를 거쳐야 하므로 아래와 같은 문제점이 발생할 수 있습니다.
    • Relay 서버의 부하 증가 (server processing power)
    • Relay 서버의 네트워크 대역폭 이슈 발생 (server network bandwidth)
    • Relay 서버가 분산 배치되지 않은 환경에서는 P2P 통신의 지연 발생 (communication latency)

■ 요약

  • 이 방법은 "NAT 통과 성공율 100%"의 NAT Traversal 기법이지만 위와 같은 문제점으로 인해 "최후의 수단"으로 사용해야 하는 기법입니다. (The most reliable, but least efficient)
  • TURN(Traversal Using Relays around NAT, RFC 5766)이 바로 이와 같은 Relay 서버를 통한 NAT Traversal을 정의하고 있습니다.

 

2. Connection Reversal

 

 

■ 개념

  • Connection Reversal 방법은 P2P 통신을 하고자 하는 두 단말 중 하나는 공인 IP 주소를 가지는 경우에 적용이 가능합니다.
  • 위 그림에서 사설 IP 주소를 가지는 Host A가 먼저 공인 IP 주소를 가지는 Host B로 연결을 요청하는 경우(NAT Outbound Traffic이 먼저 발생) 아무 문제 없이 통신이 이루어집니다. (마치 Host A가 웹서버와 통신하는 것과 동일)
  • 그런데 만약 Host B(공인 IP)가 Host A(사설 IP)로 먼저 연결 요청을 하는 경우(NAT Inbound Traffic이 먼저 발생) 상황은 달라집니다. Host A가 먼저 트래픽을 발생하지 않았기 때문에 NAT의 Binding Table/Filtering Table에 세션 엔트리가 생성되지 않았고, 따라서 Host B가 Host A로 보내는 패킷은 NAT에 의해 폐기됩니다.
  • 이와 같이 공인 IP를 가진 Host B가 사설 IP를 가진 Host A로 먼저 연결 요청을 해야 하는 경우, Host B는 Server S를 통해 연결 요청 메시지("Host A야! 내가 너랑 통신하고 싶으니까, 네가 먼저 나한테 연결 요청 메시지를 보내라!")를 Host A로 전달하고, 이후 Host A가 Host B로 연결 요청을 하도록 하는 방법입니다. 결국 NAT Outbound Traffic을 먼저 발생시킴으로써 NAT를 통과하겠다는 개념이지요.

■ 절차

  1.   Host A는 Server S로 TCP 혹은 UDP 연결 메시지(Registry Session)를 보냅니다.
  2.  

이 메시지는 NAT A를 통과하여 Server S로 도달하여 Host A와 Server S간에 TCP 혹은 UDP 연결이 됩니다. 또한 NAT A에는 다음과 같이 Binding Entry 및 Filtering Entry가 생성됩니다.

  • Binding Entry: {Internal IP:Internal Port, External IP:External Port} = {10.1.1.1:4000, 5.1.1.1:60000}
  • Filtering Entry: Allow Inbound Packet if Source info {100.1.1.1:1234}, Destination info {5.1.1.1:60000}
  3.   이제 Server S는 Host A의 Public IP/Port 정보(NAT에 의해 변환된 정보)를 알수 있게 됩니다.
  4.   Host A와 통신을 하려는 Host B는 Server S로 연결 요청 메시지(Reverse Connection Request)를 보내고, 이 메시지에는 자신의 주소/포트 정보(200.1.1.1:2000)와 연결을 원하는 목적지(Host A) 정보가 포함됩니다 (참고: Peer 목적지 주소 5.1.1.1을 알아내는 방법에 대해서는 표준에 정의되어 있지 않음).
  5.   연경 요청 메시지를 수신한 Server S는 2번에서 생성한 TCP 혹은 UDP 연결을 통해 이 메시지를 Host A로 전송하는데, 이 때 패킷 정보는 다음과 같이 변경됩니다.
  • [IP Header] Destination IP: 100.1.1.1 -> 5.1.1.1, Source IP: 200.1.1.1 -> 100.1.1.1
  • [TCP/UDP Header] Destination Port: 1234 -> 60000, Source Port: 2000 -> 1234
  • [Payload] Reverse Connection을 요청한 Host B의 정보(200.1.1.1:2000) 추가
  6.   NAT A는 다음과 같은 과정을 거쳐 수신 패킷을 Host A로 전달합니다.
  • Check Filtering Table: 수신 패킷의 정보와 Filtering Entry가 일치하므로 이 패킷을 허용
    • 수신 패킷 정보: Source info {100.1.1.1:1234}, Destination info {5.1.1.1:60000}
    • Filtering Entry: Allow Inbound Packet if Source info {100.1.1.1:1234}, Destination info {5.1.1.1:60000}
  • Check Binding Table: 수신 패킷의 목적지 정보가 Binding Entry와 일치하여 목적지 정보를 {5.1.1.1:60000}에서 {10.1.1.1:4000}으로 변경
    • 수신 패킷의 목적지 정보: {5.1.1.1:60000}
    • Binding Entry: {Internal IP:Internal Port, External IP:External Port} = {10.1.1.1:4000, 5.1.1.1:60000} 
  7.   이제 Host A는 Host B로 연결 요청(Connection Request)을 합니다. 이 때 목적지 정보(200.1.1.1:2000)는 6번 메시지의 Payload에 포함된 값을 이용합니다.
  8.   이 메시지는 NAT A를 통과하여 Host B로 전달이 되고, 이를 통해 Host A와 Host B간에 TCP 혹은 UDP 연결이 생성됩니다.  또한 그 과정 중에 NAT A에는 아래와 같이 Binding Entry 및 Filtering Entry가 생성 됩니다.
  • Binding Entry: {Internal IP:Internal Port, External IP:External Port} = {10.1.1.1:5000, 5.1.1.1:70000}
  • Filtering Entry: Allow Inbound Packet if Source info {200.1.1.1:2000}, Destination info {5.1.1.1:70000}
  9.   이제 Host B는 이 연결을 통해 Host A로 P2P 데이터 패킷을 보내면,
  10.   NAT A는 다음과 같은 과정을 거쳐 수신 패킷을 Host A로 전달합니다.
  • Check Filtering Table: 수신 패킷의 정보와 Filtering Entry가 일치하므로 이 패킷을 허용
    • 수신 패킷 정보: Source info {200.1.1.1:2000}, Destination info {5.1.1.1:70000}
    • Filtering Entry: Allow Inbound Packet if Source info {200.1.1.1:1234}, Destination info {5.1.1.1:70000}
  • Check Binding Table: 수신 패킷의 목적지 정보가 Binding Entry와 일치하여 목적지 정보를 {5.1.1.1:70000}에서 {10.1.1.1:5000}으로 변경
    • 수신 패킷의 목적지 정보: {5.1.1.1:70000}
    • Binding Entry: {Internal IP:Internal Port, External IP:External Port} = {10.1.1.1:5000, 5.1.1.1:70000}

■ 장점

  • Relaying 방식과의 가장 큰 차이점(장점)은 P2P 데애터 패킷이 Sever를 통하지 않는다는 점입니다.
  • Relaying 방식과 같이 모든 NAT Behavior (Mapping & Filtering)에서 NAT 통과가 가능합니다.

■ 단점

  • P2P 단말 중 하나는 반드시 공인 IP 주소를 가져야 하는 환경적인 제약이 있습니다. 즉, 두 단말 모두 사설 IP 주소를 가지는 환경에서는 적용이 불가능한 방법입니다.

■ 요약

  • 위와 같은 제약 사항으로 인해 Connection Reversal 기법도 최선의 NAT Traversal 솔루션은 아니며, Relaying 기법을 사용하기 전에 시도해 볼 만한 방법 정도로 생각하시면 될 듯 합니다. (Because connection reversal is not a general solution to the problem, it is NOT recommended as a primary strategy)

-----------------------------------------------

 

 

 

 

 

 

 

 

----------------------------------------------------------------

 

 

 

'개발/활용정보' 카테고리의 다른 글

대학1,2학년때 만들었던 snakewar  (0) 2018.03.10
delegate  (0) 2017.07.07
Oauth  (0) 2013.07.18
UML 기본편  (0) 2011.12.05
ClearCase  (0) 2011.08.11
And