반응형
TURN 이란?
정의
Traversal Using Relays around NAT의 약자이다.
TURN protocol은 STUN 프로토콜의 확장으로 Direct Communication이 불가 한 상황에서, relay를 통해 두 연결을 제공해주는 역할을 가진다.
배경
NAT 뒤의 HOST로 hole punching을 통해 통신이 가능하다. 하지만, 두 host 모두 NAT 뒤에 있으며, 적절한 설정이 없으면 이 또한 불가 하다.
또는 엔터프라이즈 환경에서 UDP 통신 자체가 불가 할 수 도 있다.
이를 해결하기 위해, TURN 서버에서 두 client의 통신을 relay 해주며, 통신이 가능하게 한다.
Overview
Peer A
Server-Reflexive +---------+
Transport Address | |
192.0.2.150:32102 | |
| /| |
TURN | / ^| Peer A |
Client's Server | / || |
Host Transport Transport | // || |
Address Address | // |+---------+
198.51.100.2:49721 192.0.2.15:3478 |+-+ // Peer A
| | ||N| / Host Transport
| +-+ | ||A|/ Address
| | | | v|T| 203.0.113.2:49582
| | | | /+-+
+---------+| | | |+---------+ / +---------+
| || |N| || | // | |
| TURN |v | | v| TURN |/ | |
| Client |----|A|-------| Server |------------------| Peer B |
| | | |^ | |^ ^| |
| | |T|| | || || |
+---------+ | || +---------+| |+---------+
| || | |
| || | |
+-+| | |
| | |
| | |
Client's | Peer B
Server-Reflexive Relayed Transport
Transport Address Transport Address Address
192.0.2.1:7000 192.0.2.15:50000 192.0.2.210:49191
위 그림은 TURN Server를 통한 Client들 간의 communication을 그린 것 이다.
TURN Client는 Peer A 또는 Peer B와 통신이 하고 싶은 상황이다.
TURN Server는 Public 망에 있다.
STUN Message
STUN Message는 STUN Protocol에서 사용되는 message이다.
TURN은 STUN Message를 확장한 프로토콜이기에, 기본적으로 STUN Message 구조를 따른다.
STUN Header
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0| STUN Message Type | Message Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Magic Cookie |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Transaction ID (96 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
STUN Message의 Header는 20 Byte로 구성된다.
STUN Message Type: message의 class 정보이며 request, success response, failuser response, indication 등 있으며, TURN 등 확장 프로토콜에서 추가되기도 한다.
Message Length: Header를 제외한 Message의 size
Transaction ID: STUN은 request ↔︎ response간 transaction을 지원한다. 해당 ID를 올릴 수 있는 부분
STUN Message Type
0 1
2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
Stun의 MessageType은 14bit로 표현된다.
앞 두 bit는 무조건 00이며(prefix, not message Type), Class + Method로 구성되어 있다.
Class는 8, 12 번째 bit이며, 나머지는 Method이다.
Class: 0b00=request, 0b01=indication, 0b10=successResponse, 0b11=errorResponse
EX)
TURN Protocol Create Permission
Class: request(0b00) or successResponse(0b10) or errorResponse(0b11)
Method: 0x008
request: 0000 0000 0000 1000 = 0x0008
sucessResponse: 0000 0001 0000 1000 = 0x0108
errorResponse: 0000 0001 0001 1000 = 0x0118
Protocol | Method | Bytes | Support Class |
STUN | (Reserved) | 0x000 | - |
STUN | Binding | 0x001 | - |
STUN | (Reserved; was SharedSecret) | 0x002 | - |
TURN | Allocate | 0x003 | req / res |
TURN | Refresh | 0x004 | req / res |
TURN | Send | 0x006 | indication |
TURN | Data | 0x007 | indication |
TURN | CreatePermission | 0x008 | req / res |
TURN | ChannelBind | 0x009 | req / res |
STUN Attributes
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Value (variable) ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: Attribute의 구분으로 16bit이다.
Length: value의 length in bytes로 16bit 이다.
value: Attribute의 값
Protocol | Type | Bytes | Desc |
STUN | MAPPED-ADDRESS | 0x0001 | reflexive transport address of the client |
STUN | USERNAME | 0x0006 | identifies the username and password combination used in the message-integrity |
STUN | MESSAGE-INTEGRITY | 0x0008 | contains an HMAC-SHA1 [RFC2104] of the STUN message |
STUN | ERROR-CODE | 0x0009 | errorCode: 300 ~ 699 + α 300: Try Alternate 400: Bad Request 401: Unauthorized 420: Unknown Attribute 438: Stale Nonce 500: Server Error |
STUN | UNKNOWN-ATTRIBUTES | 0x000A | errorResponse에서만 사용되는 type으로, 서버가 이해하지 못한 attribute를 뜻함 |
STUN | REALM | 0x0014 | Attribute가 request에 있는 경우 long-term credential이 사용되고 있음을 나타내며 error response에 있다면 client에게 long-term credential이 필요함을 나타냄 |
STUN | NONCE | 0x0015 | 128 character보다 적은 임의의 값 |
STUN | XOR-MAPPED-ADDRESS | 0x0020 | MAPPED-ADDRESS와 동일하며, 난독화 됨 |
STUN | SOFTWARE | 0x8022 | textual description of the software |
STUN | ALTERNATE-SERVER | 0x8023 | alternate transport address identifying a different STUN server that the STUN client should try |
STUN | FINGERPRINT | 0x8028 | use for identifier |
TURN | CHANNEL-NUMBER | 0x000C | channel을 지정하기 위한 값 |
TURN | LIFETIME | 0x000D | duration of allocation |
TURN | XOR-PEER-ADDRESS | 0x0012 | 난독화된 상대의 address를 의미 |
TURN | DATA | 0x0013 | data |
TURN | XOR-RELAYED-ADDRESS | 0x0016 | Allocate Response로 전달되는 allocated된 address |
TURN | REQUESTED-ADDRESS-FAMILY | 0x0017 | IPv4: 0x01 IPv6: 0x02 |
TURN | EVEN-PORT | 0x0018 | relay port를 even으로 요청 |
TURN | REQUESTED-TRANSPORT | 0x0019 | protocol을 지정하는 attribute (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml) 17 (User Datagram Protocol)로 고정 |
TURN | DONT-FRAGMENT | 0x001A | Allocate시 보내는 attribute로 peer로 데이터 전달 시 fragment를 하지 말라는 의미 value는 없음 |
TURN | RESERVATION-TOKEN | 0x0022 | Server에서 예비로 남긴 relay address를 식별하는 토큰 allocation에서 사용될 수 있음 |
TURN | ADDITIONAL-ADDRESS-FAMILY | 0x8000 | REQUESTED-ADDRESS-FAMILY의 확장, allocate에서 사용될 수 있음 |
TURN | ADDRESS-ERROR-CODE | 0x8001 | address관련 error code |
TURN | ICMP | 0x8004 | UDP Packets이 사라진 이유를 서버에서 알리기 위한 Attribute |
STUN | (Reserved) | 0x0000 | - |
STUN | (Reserved; was RESPONSE-ADDRESS) | 0x0002 | for legacy protocol |
STUN | (Reserved; was CHANGE-ADDRESS) | 0x0003 | for legacy protocol |
STUN | (Reserved; was SOURCE-ADDRESS) | 0x0004 | for legacy protocol |
STUN | (Reserved; was CHANGED-ADDRESS) | 0x0005 | for legacy protocol |
STUN | (Reserved; was PASSWORD) | 0x0007 | for legacy protocol |
STUN | (Reserved; was REFLECTED-FROM) | 0x000B | for legacy protocol |
TURN | Reserved (was BANDWIDTH) | 0x0010 | for legacy protocol |
TURN | Reserved (was TIMER-VAL) | 0x0021 | for legacy protocol |
Sample TURN Sequence Diagram
Client는 TURN Server로 Allocate를 진행하는 참여자이며 Peer는 TURN 서버에서 메시지 전송이 가능한 참여자이다.
따라서 Peer는 public 망에 있거나, 이전에 Allocate 된 상태로 보면 된다.
allocate를 포함하여 대부분의 메시지에 적용되는 인증은 같은 방식으로 진행한다.
일반적인 Flow는 Allocate → (Permission) → Send data 이며 Send data는 indicate와 channel 방식이 있다.
Client는 Allocate를 통해 자신에게 udp 전송이 가능하도록 할당을 받는다.
이후 peer등 다른 참여자는 allocate된 해당 address로 data를 전송하면 TURN Server에서 allocate 된 정보를 바탕으로 Client에게 메시지를 전송한다.
indicate는 메시지마다 peer에 대한 정보를 같이 보내는 방식
channel은 사전에 channel number와 peer를 mapping하여, channel number로만 data를 전송하는 방식이다.
Appendix: UDP Hole Punching
Hole Pubching은 NAT 뒤의 client들의 peer to peer가 가능하도록 하는 방법 중 하나이다.
이는 NAT 뒤의 client끼리 p2p 통신을 시작할 수 없기 때문에 필요하다.
Hole Pubching 를 위해서는 NAT 방식이 EIM(Endpoint-Independent Mapping)일 때 이상적으로 동작한다.
Under EIM-NAT
Server S
192.0.2.128:20001
|
+----------------------------+----------------------------+
| ^ Registry Session(A-S) ^ ^ Registry Session(B-S) ^ |
| | 192.0.2.128:20001 | | 192.0.2.128:20001 | |
| | 192.0.2.1:62000 | | 192.0.2.254:31000 | |
| |
| ^ P2P Session (A-B) ^ ^ P2P Session (B-A) ^ |
| | 192.0.2.254:31000 | | 192.0.2.1:62000 | |
| | 192.0.2.1:62000 | | 192.0.2.254:31000 | |
| |
+--------------+ +--------------+
| 192.0.2.1 | | 192.0.2.254 |
| | | |
| EIM-NAT A | | EIM-NAT B |
+--------------+ +--------------+
| |
| ^ Registry Session(A-S) ^ ^ Registry Session(B-S) ^ |
| | 192.0.2.128:20001 | | 192.0.2.128:20001 | |
| | 10.0.0.1:1234 | | 10.1.1.3:1234 | |
| |
| ^ P2P Session (A-B) ^ ^ P2P Session (B-A) ^ |
| | 192.0.2.254:31000 | | 192.0.2.1:62000 | |
| | 10.0.0.1:1234 | | 10.1.1.3:1234 | |
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234
두 Client가 서로 다른 EIM-NAT 뒤에 있다.
ClientA ↔︎ ClientB는 직접통신은 불가하며, NAT를 거쳐 통신을 하고자 한다.
1. ClientA, B 모두 Server로 Session을 등록하는 과정을 갖는다.
2. EIM-NAT는 Endpoint와 상관없이 각각 192.0.2.1:62000, 192.0.2.254:31000을 ClientA, B와 매핑한다.
3. ClientA, B 모두 Server에게 상대의 NAT public IP를 쿼리한다.
4. ClientA, B 서로 Server를 통해 만든 NAT Table의 포트로 UDP 통신을 한다.
REFERENCE
https://datatracker.ietf.org/doc/html/rfc8656
https://datatracker.ietf.org/doc/html/rfc5389
https://datatracker.ietf.org/doc/html/rfc5128#section-3.3
반응형
'개발 일지' 카테고리의 다른 글
Spring Webflux with EventListener (0) | 2024.03.20 |
---|---|
[Kafka] Parallel Consumer (0) | 2024.03.19 |
ProjectReactor Case Study (0) | 2024.02.22 |
Global Hooks And Context Propagation (Projectreactor Advanced Features) (1) | 2024.02.20 |
Hot vs Cold Publisher (Projectreactor Advanced Features) (0) | 2024.02.19 |