RFC5766
看文档时顺便记录的翻译,仅仅作为参考,码字不易,如有转载,请注明出处,多谢!
有几个图已经乱了,有时间再重新排版。虽然不是所有内容,但是大部分主要内容已经有了。
目前已经实现了 RFC5766,相关内容可以阅读文章 WebRTC服务器,支持STUN/TURN
Abstract If a host is located behind a NAT, then in certain situations it can be impossible for that host to communicate directly with other hosts (peers). In these situations, it is necessary for the host to use the services of an intermediate node that acts as a communication relay. This specification defines a protocol, called TURN (Traversal Using Relays around NAT), that allows the host to control the operation of the relay and to exchange packets with its peers using the relay. TURN differs from some other relay control protocols in that it allows a client to communicate with multiple peers using a single relay address. The TURN protocol was designed to be used as part of the ICE (Interactive Connectivity Establishment) approach to NAT traversal, though it also can be used without ICE.
摘要
如果一个主机位于一个NAT后边,有一情况是不能直接和对端通信。这种情况下,对于主机需要有服务节点可以执行relay通信。这个文档定义了一个协议,叫做TURN(Traversal Using Relays around NAT),这个协议允许主机控制 relay 的操作去和它其他对端交换数据。TURN 和其他转发协议不同在于,TURN 允许一个客户端用一个转发地址和多个对端通信。
1. Introduction
A host behind a NAT may wish to exchange packets with other hosts, some of which may also be behind NATs. To do this, the hosts involved can use "hole punching" techniques (see [RFC5128]) in an attempt discover a direct communication path; that is, a communication path that goes from one host to another through intervening NATs and routers, but does not traverse any relays.
说明
NAT后边的注意可能希望和其他的主机通信,而这些主机也可能再NAT的后面。为了达到这个目的,可以用叫做 “hole punching” 的技术去发现一个可以直接通信的路径;这个通信路径可以让一个主机通过一些NAT到达其他端,而且不需要经过转发。
As described in [RFC5128] and [RFC4787], hole punching techniques will fail if both hosts are behind NATs that are not well behaved. For example, if both hosts are behind NATs that have a mapping behavior of "address-dependent mapping" or "address- and port- dependent mapping", then hole punching techniques generally fail.
按照 RFC5128 和 RFC4787,hole punching 技术可能会失败。比如,两个主机后的 NAT 是 “地址依赖映射” 或者 “地址端口依赖映射” 类型的NAT,这种情况下 hole punching 可能失败。
When a direct communication path cannot be found, it is necessary to use the services of an intermediate host that acts as a relay for the packets. This relay typically sits in the public Internet and relays packets between two hosts that both sit behind NATs.
当一个直接通信的路径不能被发现,必须要有一个转发。relay 应该在公网上,NAT 后边的两个主机通过这个 relay 交换数据。
This specification defines a protocol, called TURN, that allows a host behind a NAT (called the TURN client) to request that another host (called the TURN server) act as a relay. The client can arrange for the server to relay packets to and from certain other hosts (called peers) and can control aspects of how the relaying is done. The client does this by obtaining an IP address and port on the server, called the relayed transport address. When a peer sends a packet to the relayed transport address, the server relays the packet to the client. When the client sends a data packet to the server, the server relays it to the appropriate peer using the relayed transport address as the source.
这个规范定义了一个协议,叫 TURN,它允许NAT后一个主机(叫做 TURN Client)请求另一个主机(叫做 TURN server)作为一个转发。client 可以安排服务器转发数据包到其他主机或者让服务器转发来自其他主机的数据报给自己,并且能够控制转发是如何结束的。 客户端能够做到这些需要通过获取服务器上的一个 IP 和 端口,这个IP和端口叫做 relayed transport address。当对端发送一个包到 relayed transport address,服务器转发这个包给 client。当client发送一个数据包给服务器,服务器用 relayed transport address 转发给对端。
A client using TURN must have some way to communicate the relayed transport address to its peers, and to learn each peer's IP address and port (more precisely, each peer's server-reflexive transport address, see Section 2). How this is done is out of the scope of the TURN protocol. One way this might be done is for the client and peers to exchange email messages. Another way is for the client and its peers to use a special-purpose "introduction" or "rendezvous" protocol (see [RFC5128] for more details).
一个使用 TURN 的 client 必须要有一些办法把自己的 relayed transport address 告诉给对端,并且学习每个对端的 IP地址 和 端口(更准确的说,就是每个对端的 server-reflexive tranpsort address)。如何完成交换 relayed transport address 不是这个协议定义的。一个办法是让 client 和 对端交换email 信息??另一个办法是 client 和 它的对端用一个特殊目的的 "introduction" 或者 “rendezvous”。
If TURN is used with ICE [RFC5245], then the relayed transport address and the IP addresses and ports of the peers are included in the ICE candidate information that the rendezvous protocol must carry. For example, if TURN and ICE are used as part of a multimedia solution using SIP [RFC3261], then SIP serves the role of the rendezvous protocol, carrying the ICE candidate information inside the body of SIP messages. If TURN and ICE are used with some other rendezvous protocol, then [MMUSIC-ICE-NONSIP] provides guidance on the services the rendezvous protocol must perform.
如果 TURN 和 ICE 一起使用,relayed transport address 和 对端的 IP地址 和 端口必须包含在 ICE 的 candidate 信息里。比如,如果 TURN 和 ICE 作为使用 SIP 的多媒体解决方案的一部分,SIP充当汇合协议的角色,SIP消息提包含 ICE candidate 信息。如果 TURN 和 ICE 用来和其他的交汇协议,[MMUSIC-ICE-NONSIP] 里提供的向导必须被执行。
Though the use of a TURN server to enable communication between two hosts behind NATs is very likely to work, it comes at a high cost to the provider of the TURN server, since the server typically needs a high-bandwidth connection to the Internet. As a consequence, it is best to use a TURN server only when a direct communication path cannot be found. When the client and a peer use ICE to determine the communication path, ICE will use hole punching techniques to search for a direct path first and only use a TURN server when a direct path cannot be found.
虽然使用 TURN 服务器一定可以让 NAT 后边的两个主机通信,但是它也会有很高的代价,因为服务器需要一个高带宽。作为结论,最好在直连不成功的情况下使用 TURN。当 client 和 对端通过 ICE 去检测通信路径,首先会用 hole punching 技术去找直连路径,直连路径没有找到就使用 TURN 服务器。
TURN was originally invented to support multimedia sessions signaled using SIP. Since SIP supports forking, TURN supports multiple peers per relayed transport address; a feature not supported by other approaches (e.g., SOCKS [RFC1928]). However, care has been taken to make sure that TURN is suitable for other types of applications.
TURN 最开始发明就是使用SIP支持多媒体会话,因为SIP支持 forking,TURN 支持一个relayed transport address 对应每个对端;有一个特性不支持其他的手段(比如 SOCKS[RFC1928])。无论如何,已经确保 TURN 适合其他各种应用。
TURN was designed as one piece in the larger ICE approach to NAT traversal. Implementors of TURN are urged to investigate ICE and seriously consider using it for their application. However, it is possible to use TURN without ICE. TURN is an extension to the STUN (Session Traversal Utilities for NAT) protocol [RFC5389]. Most, though not all, TURN messages are STUN-formatted messages. A reader of this document should be familiar with STUN.
TURN 被设计成 ICE 穿越 NAT 的一部分。使用 ICE 的程序鼓励实现 TURN 。不用 ICE 使用 TURN 是可能的。TURN 是一 STUN 的扩展。大多数情况下, TURN 消息是 STUN 格式的。本文的读者应该熟悉 STUN。
2. Overview of Operation This section gives an overview of the operation of TURN. It is non- normative. In a typical configuration, a TURN client is connected to a private network [RFC1918
2. 操作概述
这段文档说的是TURN的操作大概流程,并不是一个规范。一个典型的配置就是,一个 client 连接到一个私有网络,并且通过多个 NAT 连接到公网。公网上的是 TURN 服务器。在internet的其他地方是一个或者多个想要和 client 通信的对端。这些对端在不在 NAT 后边不一定。client 通过服务器作为转发发送数据包给对对端并且通过服务器接收来自对端的数据包。
Figure 1 shows a typical deployment. In this figure, the TURN client and the TURN server are separated by a NAT, with the client on the private side and the server on the public side of the NAT. This NAT is assumed to be a "bad" NAT; for example, it might have a mapping property of "address-and-port-dependent mapping" (see [RFC4787
图1是一个典型的部署。在这个图中,TURN 的 client 和 TURN 服务器被 NAT 隔离,client 在私有网络的一侧,服务器在公网的一侧。假如这个这是一个 “bad” NAT;比如,NAT 的映射方式可能是 “地址端口依赖映射”。客户端用来和服务器通信的 IP地址和端口叫做 client 的 HOST TRANSPORT ADDRESS。(IP地址和端口组合叫做 TRANSPORT ADDRESS)。
The client sends TURN messages from its host transport address to a transport address on the TURN server that is known as the TURN SERVER TRANSPORT ADDRESS. The client learns the TURN server transport address through some unspecified means (e.g., configuration), and this address is typically used by many clients simultaneously.
client 从它的主机发送 TURN 消息到 TURN 服务器上的 TURN SERVER TRANSPORT ADDRESS。client 通过一些方式知道 TURN server trasnport address, 典型的用法是多个 client 同时使用这个地址。
Since the client is behind a NAT, the server sees packets from the client as coming from a transport address on the NAT itself. This address is known as the client's SERVER-REFLEXIVE transport address; packets sent by the server to the client's server-reflexive transport address will be forwarded by the NAT to the client's host transport address.
因为 client 在 NAT 后面,服务器看到来自 client 发来过来的数据包的地址是 NAT 上的地址。这个地址就是 client 的 SERVER-REFLEXIVE transport address;服务器通过 client 的 server-reflexive transport address 发送数据包,会被 NAT 转发到 client 的 host transport address。
The client uses TURN commands to create and manipulate an ALLOCATION on the server. An allocation is a data structure on the server. This data structure contains, amongst other things, the RELAYED TRANSPORT ADDRESS for the allocation. The relayed transport address is the transport address on the server that peers can use to have the server relay data to the client. An allocation is uniquely identified by its relayed transport address.
client 用 TURN 命令在服务器上创建和操作 ALLOCATOIN。allocation 是一个服务器上的数据结构。这个数据结构包括一些比较重要的东西,比如 RELAYED TRANSPORT ADDRESS。relayed transport address 是服务器上的一个地址,对端可以使用它让服务器转发数据到 client。allocatoin 的唯一标识就是 relayed transport address。
Once an allocation is created, the client can send application data to the server along with an indication of to which peer the data is to be sent, and the server will relay this data to the appropriate peer. The client sends the application data to the server inside a TURN message; at the server, the data is extracted from the TURN message and sent to the peer in a UDP datagram. In the reverse direction, a peer can send application data in a UDP datagram to the relayed transport address for the allocation; the server will then encapsulate this data inside a TURN message and send it to the client along with an indication of which peer sent the data. Since the TURN message always contains an indication of which peer the client is communicating with, the client can use a single allocation to communicate with multiple peers.
一旦一个 allocation 创建,client 发送数据给服务器并且可以指明发给哪个对端,服务器就会转发这个数据给指定的对端。client 通过TURN消息发送应用程序数据给服务器,在服务器上,数据从 TURN 消息解压出来并且使用 UDP 发送给对端。在反方向,一个对端可以发送 UDP 应用程序数据到 relayed transport address;服务器会把数据放进 TURN 消息 然后指明是谁发送的数据。因为 TURN 消息总是包含一个对端和client通信方向的指示,client 可以用一个单独的 allocation 和多个对端通信。
When the peer is behind a NAT, then the client must identify the peer using its server-reflexive transport address rather than its host transport address. For example, to send application data to Peer A in the example above, the client must specify 192.0.2.150:32102 (Peer A's server-reflexive transport address) rather than 192.168.100.2: 49582 (Peer A's host transport address).
当对端在 NAT 后边,client 要使用 server-reflexive transport address,不要使用 host transport address。比如,上边例子中的发送数据到 peer A,client 必须使用 192.0.2.150:32102(peer A 的 server-reflexive transport address),不能使用 192.168.100.2:49582(Peer A的 host transport address)
Each allocation on the server belongs to a single client and has exactly one relayed transport address that is used only by that allocation. Thus, when a packet arrives at a relayed transport address on the server, the server knows for which client the data is intended. The client may have multiple allocations on a server at the same time.
每一个服务器上的 allocation 的 relayed transport address 对于单独的一个 client 都是唯一的。所以,当一个数据包到达了服务器上的 relayed transport address,服务器知道这个数据包要发给哪一个 client。
client 在一个服务器上同时可能由多个 allocation。
2.1 Transports
TURN, as defined in this specification, always uses UDP between the server and the peer. However, this specification allows the use of any one of UDP, TCP, or Transport Layer Security (TLS) over TCP to carry the TURN messages between the client and the server.
这份规范中的定义的 TURN,在 server 和 peer 之间总是使用 UDP。这个规范允许使用 UDP / TCP 或者 TLS TCP 进行 client 和 服务器之间的通信。
If TCP or TLS-over-TCP is used between the client and the server, then the server will convert between these transports and UDP transport when relaying data to/from the peer. Since this version of TURN only supports UDP between the server and the peer, it is expected that most clients will prefer to use UDP between the client and the server as well. That being the case, some readers may wonder: Why also support TCP and TLS-over-TCP?
如果 client 和 server 之间使用 TCP 或者 TLS-over-TCP,服务器会将发送peer的转换成 UDP,或者收到peer的数据转换成 TCP 或者 TLS-over-TCP。
因为这个版本的 TURN,服务器和peer之间只支持 UDP,最好 client 和 服务器的传输也用 UDP。因为这些原因,一些读者可能会想:为什么要使用 TCP 和 TLS-over-TCP?
TURN supports TCP transport between the client and the server because some firewalls are configured to block UDP entirely. These firewalls block UDP but not TCP, in part because TCP has properties that make the intention of the nodes being protected by the firewall more obvious to the firewall. For example, TCP has a three-way handshake that makes in clearer that the protected node really wishes to have that particular connection established, while for UDP the best the firewall can do is guess which flows are desired by using filtering rules. Also, TCP has explicit connection teardown; while for UDP, the firewall has to use timers to guess when the flow is finished.
TURN 在 client 和 服务器之间 支持 TCP transport 是因为一些防火墙会阻止 UDP。这些防火墙不阻止 TCP,部分是因为 TCP 本身就有被保护的特性。比如,TCP 有 3次握手,可以明确的指明想建立连接,但是对于 UDP,最好的防火墙也只能猜测哪一个流应该被应用过滤规则。同样,TCP 断开连接也非常明确,但是对于 UDP,防火墙只能通过时间去去猜测这个流是否结束。
TURN supports TLS-over-TCP transport between the client and the server because TLS provides additional security properties not provided by TURN's default digest authentication; properties that some clients may wish to take advantage of. In particular, TLS provides a way for the client to ascertain that it is talking to the correct server, and provides for confidentiality of TURN control messages. TURN does not require TLS because the overhead of using TLS is higher than that of digest authentication; for example, using TLS likely means that most application data will be doubly encrypted (once by TLS and once to ensure it is still encrypted in the UDP datagram).
TURN 在 client 和 服务器之间支持 TLS-over-TCP 是因为 TLS 可以提供额外的安全属性,这种安全是 TURN 默认不提供的;这种额外的安全属性有一些客户端需要。
2.2. Allocations
To create an allocation on the server, the client uses an Allocate transaction. The client sends an Allocate request DATADATAto the server, and the server replies with an Allocate success response containing the allocated relayed transport address. The client can include attributes in the Allocate request that describe the type of allocation it desires (e.g., the lifetime of the allocation). Since relaying data has security implications, the server requires that the client authenticate itself, typically using STUN's long-term credential mechanism, to show that it is authorized to use the server.
为了在服务器上创建一个 allocation,客户端要用 allocate 事务。客户端发送一个 allocate 请求 到服务器,服务器回复一个 allocate 成功的响应,并且相应里包含 relayed 地址。客户端可以在 allocate 请求中增加一些属性(比如 lifetime)。因为 relay 数据存在安全隐患,服务器需要客户端进行认证,一般使用 STUN 的 long-term 认证机制。
Once a relayed transport address is allocated, a client must keep the allocation alive. To do this, the client periodically sends a Refresh request to the server. TURN deliberately uses a different method (Refresh rather than Allocate) for refreshes to ensure that the client is informed if the allocation vanishes for some reason.
一旦一个 allocate 成功,客户端需要进行保活。客户端要定时发送 refresh 请求给服务器。TURN 特意使用了不同的方法(用 refresh 替代 allocate)保证客户端能知道 allocation 因为一些原因尔突然消失。
The frequency of the Refresh transaction is determined by the lifetime of the allocation. The default lifetime of an allocation is 10 minutes -- this value was chosen to be long enough so that refreshing is not typically a burden on the client, while expiring allocations where the client has unexpectedly quit in a timely manner. However, the client can request a longer lifetime in the Allocate request and may modify its request in a Refresh request, and the server always indicates the actual lifetime in the response. The client must issue a new Refresh transaction within "lifetime" seconds
of the previous Allocate or Refresh transaction. Once a client no longer wishes to use an allocation, it should delete the allocation using a Refresh request with a requested lifetime of 0.
refresh 的频率取决于 allocation 的 lifetime。默认 allocation 的 lifetime 是 10 分钟 -- 这个值选择的足够大,这样会减轻客户端的负担,当客户意外退出的时候 allocations 可以及时失效。客户端可以可以在 allocate 中请求一个长的 lifetime,也可以通过 refresh 请求修改 lifetime,服务器总是会在回复中指明 lifetime。客户端必须在上一个 allocate 或者 refresh 事务的 lifetime 时间内给服务器发一个新的 reshresh 事务。一旦客户端不再需要 allocation,客户端应该发送一个 lifetime 属性为 0 的 refresh 请求。
Both the server and client keep track of a value known as the 5-TUPLE. At the client, the 5-tuple consists of the client's host transport address, the server transport address, and the transport protocol used by the client to communicate with the server. At the server, the 5-tuple value is the same except that the client's host transport address is replaced by the client's server-reflexive address, since that is the client's address as seen by the server.
服务器和客户端都保持着一个5元组。在客户端,5元组是 客户端的 host 地址,服务器的地址,客户端和服务器通信的协议。在服务器端,这个5元组是一样的,只是客户端的 host 地址被地换成 客户端的 server-reflexive,因为这个地址是服务器看到的客户端的地址。
Both the client and the server remember the 5-tuple used in the Allocate request. Subsequent messages between the client and the server use the same 5-tuple. In this way, the client and server know which allocation is being referred to. If the client wishes to allocate a second relayed transport address, it must create a second allocation using a different 5-tuple (e.g., by using a different client host address or port).
客户端和服务器端在 allocate 请求中使用记住的5元组。后续在客户端和服务器端的消息用相同的5元组。用这种方式,客户端和服务器端知道 allocation 关联的是哪一个。如果客户端希望 allocate 第二个 relayed 地址,它必须用不同的5元组创建第二个 allocation。(比如,用不同的客户端 host 地址和端口)
TURN TURN Peer Peer client server A B |-- Allocate request --------------->| | | | | | | |<--------------- Allocate failure --| | | | (401 Unauthorized) | | | | | | | |-- Allocate request --------------->| | | | | | | |<---------- Allocate success resp --| | | | (192.0.2.15:50000) | | | // // // // | | | | |-- Refresh request ---------------->| | | | | | | |<----------- Refresh success resp --| | | | | | | Figure 2
In Figure 2, the client sends an Allocate request to the server without credentials. Since the server requires that all requests be authenticated using STUN's long-term credential mechanism, the server rejects the request with a 401 (Unauthorized) error code. The client then tries again, this time including credentials (not shown). This time, the server accepts the Allocate request and returns an Allocate success response containing (amongst other things) the relayed transport address assigned to the allocation. Sometime later, the client decides to refresh the allocation and thus sends a Refresh request to the server. The refresh is accepted and the server replies with a Refresh success response.
在 图2 里,客户端不用任何凭证给服务器发送一个 allocate 请求。因为服务器需要所有的请求应该用 STUN 的 long-term 认证机制,服务器拒绝这个请求并生一个一个 401 (Unauthorized)的错误码。客户端这时再试一次,这次请求包含凭证。这次服务器接受了 allocate 请求并且返回了一个带有 relayed 地址的成功响应。过了一会,客户端决定刷新 refresh并且发送了一个 refresh请到服务器。这个 refresh 被服务器接受了,并且返回了一个成功响应。
2.3. Permissions
To ease concerns amongst enterprise IT administrators that TURN could be used to bypass corporate firewall security, TURN includes the notion of permissions. TURN permissions mimic the address-restricted filtering mechanism of NATs that comply with [RFC4787].
为了缓解企业的IT管理人员对于 TURN 可以绕过防火墙的困扰,TURN 包含了一个 权限概念。TURN 权限模仿 NAT的地址显示过滤机制,这机制是符合[RFC4787]
An allocation can have zero or more permissions. Each permission consists of an IP address and a lifetime. When the server receives a UDP datagram on the allocation's relayed transport address, it first checks the list of permissions. If the source IP address of the datagram matches a permission, the application data is relayed to the client, otherwise the UDP datagram is silently discarded.
一个 allocation 可以没有 permission 或者有多个 permission。每个 permission 由 IP 地址和 lifetime 组成。当服务器在转发地址上收到一个 UDP 数据,应该先检查 permission 列表。如果数据的源地址匹配到了权限,应用数据可以被转发到 client,否则服务器不会处理这个 UDP 数据。
A permission expires after 5 minutes if it is not refreshed, and there is no way to explicitly delete a permission. This behavior was selected to match the behavior of a NAT that complies with [RFC4787].
如果不刷新,permission 会在 5分钟后过期,这里没有办法明确的删除 permission, 因为这个行为会按照 [RFC4787] 里的 NAT 行为。(可能是不确定过期时间)
The client can install or refresh a permission using either a CreatePermission request or a ChannelBind request. Using the CreatePermission request, multiple permissions can be installed or refreshed with a single request -- this is important for applications that use ICE. For security reasons, permissions can only be installed or refreshed by transactions that can be authenticated; thus, Send indications and ChannelData messages (which are used to send data to peers) do not install or refresh any permissions.
client 可以用 CreatePermisson 或者 ChannelBind 安装或者刷新 permission。多个 permission 可以用一个 CreatePermission 安装或者刷新 -- 这对于使用 ICE 的应用很重要。出于安全原因,permission 安装或者刷新只能有通过认证才能进行;所以,send indication 和 ChannelData 不安装刷新任何 permission。
Note that permissions are within the context of an allocation, so adding or expiring a permission in one allocation does not affect other allocations.
注意 permission 属于 allocation 的上下文内,所以添加或者过期一个 allocation 中的 permission 不会影响其他的 allocation。
2.4. Send Mechanism
There are two mechanisms for the client and peers to exchange application data using the TURN server. The first mechanism uses the Send and Data methods, the second way uses channels. Common to both ways is the ability of the client to communicate with multiple peers using a single allocated relayed transport address; thus, both ways include a means for the client to indicate to the server which peer should receive the data, and for the server to indicate to the client which peer sent the data.
有两种机制可以让两端通过 TURN SERVER 交换数据。第一种是用 send 和 data 方法,第二种方式使用 channels。两种方式的共同点是 客户端有能力 和 多个对端通过一个 单独的 转发地址相互通信;两种方式都包括 客户告诉服务器,指明哪个对端应该收到数据,以及服务器指明客户端,哪个对端发送的数据。
The Send mechanism uses Send and Data indications. Send indications are used to send application data from the client to the server, while Data indications are used to send application data from the server to the client.
发送机制用 send 和 data indications。send indications 用来发送客户端到服务器的数据,data indications 用来发送服务器到客户端的数据。
When using the Send mechanism, the client sends a Send indication to the TURN server containing (a) an XOR-PEER-ADDRESS attribute specifying the (server-reflexive) transport address of the peer and (b) a DATA attribute holding the application data. When the TURN server receives the Send indication, it extracts the application data from the DATA attribute and sends it in a UDP datagram to the peer, using the allocated relay address as the source address. Note that there is no need to specify the relayed transport address, since it is implied by the 5-tuple used for the Send indication.
当使用 send 机制,客户端发送 send indication 给服务器,并且 send indication 有一个 XOR-PEER-ADDRESS 属性,这个属性指明 (server-reflexive)对端的传输地址,还有一个 data 属性,包含要发送的数据。当 turn 服务器收到 send indication,服务器解开 data 属性中的数据,并且通过 udp 使用 allocated 转发地址作为 源地址 发送给对端。注意,不需要指明 relayed 传输地址,因为有一个 5 元组可以给 send indication 使用。
In the reverse direction, UDP datagrams arriving at the relayed transport address on the TURN server are converted into Data indications and sent to the client, with the server-reflexive transport address of the peer included in an XOR-PEER-ADDRESS attribute and the data itself in a DATA attribute. Since the relayed transport address uniquely identified the allocation, the server knows which client should receive the data.
在反方向,udp包到达 turn 服务器的 relayed transport address,turn 服务器把 udp 包 转换成 data indications 并且发给客户端,data indications 包含 对端的 server-reflexive transport address,这个地址放在 XOR-PEER-ADDRESS 属性里。因为 allocation 的 relayed transport address 是唯一的,服务器知道哪个客户端应该收到数据。
Send and Data indications cannot be authenticated, since the long- term credential mechanism of STUN does not support authenticating indications. This is not as big an issue as it might first appear, since the client-to-server leg is only half of the total path to the peer. Applications that want proper security should encrypt the data sent between the client and a peer.
send 和 data indications 不能被 认证,因为 stun 的 long-term 认证方式 不支持 认证 indications。这个问题不大,因为 client 到 server 仅仅是 到对端 整个路径的一半。应用程序想要更安全一点应该在 客户端 和 对端 传输数据的时候加密。
Because Send indications are not authenticated, it is possible for an attacker to send bogus Send indications to the server, which will then relay these to a peer. To partly mitigate this attack, TURN requires that the client install a permission towards a peer before sending data to it using a Send indication.
因为 send indications 不能认证,可能会有 攻击者 发送伪造的 send indications 到 服务器,然后 服务器 转发到 对端。为了部分缓解这个攻击,turn 要求 客户端用 send indication 发送数据之前需要安装权限。
TURN TURN Peer Peer client server A B | | | | |-- CreatePermission req (Peer A) -->| | | |<-- CreatePermission success resp --| | | | | | | |--- Send ind (Peer A)-------------->| | | | |=== data ===>| | | | | | | |<== data ====| | |<-------------- Data ind (Peer A) --| | | | | | | | | | | |--- Send ind (Peer B)-------------->| | | | | dropped | | | | | | | |<== data ==================| | dropped | | | | | | | Figure 3
In Figure 3, the client has already created an allocation and now wishes to send data to its peers. The client first creates a permission by sending the server a CreatePermission request specifying Peer A's (server-reflexive) IP address in the XOR-PEER- ADDRESS attribute; if this was not done, the server would not relay data between the client and the server. The client then sends data to Peer A using a Send indication; at the server, the application data is extracted and forwarded in a UDP datagram to Peer A, using the relayed transport address as the source transport address. When a UDP datagram from Peer A is received at the relayed transport address, the contents are placed into a Data indication and forwarded to the client. Later, the client attempts to exchange data with Peer B; however, no permission has been installed for Peer B, so the Send indication from the client and the UDP datagram from the peer are both dropped by the server.
在 Figure 3,客户端已经创建了 allocation,希望 发送数据到对端。客户端首先通过给服务器发送一个 CreatePermission 请求,创建一个权限,请求指明 PEER A 的 (server-reflexive)ip 地址,这个地址在 XOR-PEER-ADDRESS 属性中;如果没有这个请求,服务器不会转发客户端的数据。客户端用 send indication 发送数据到 PEER A;在服务器上,应用数据被解析出来并且通过 UDP 转发给对端 PEER A,转发的时候用 relayed transport address 作为源传输地址。当来自 PEER A 的 UDP 数据在 relay transport address上被接收,内容被转成 data indication 并且转发给客户端。之后,客户端尝试和 PEER B 交换数据。无论如何,PEER B没有安装权限,所以来自 客户端的 send indication 和 来自对端的 udp 数据都被服务器丢弃。
2.5 Channels
For some applications (e.g., Voice over IP), the 36 bytes of overhead that a Send indication or Data indication adds to the application data can substantially increase the bandwidth required between the client and the server. To remedy this, TURN offers a second way for the client and server to associate data with a specific peer.
对于一些应用程序(比如 Voice over IP)来说,Send inidcation 或者 Data indication 36个字节的头会增加流量,为了解决这个问题,TURN 提供了第二种方式让 client 通过 server 转发到 peer
This second way uses an alternate packet format known as the ChannelData message. The ChannelData message does not use the STUN header used by other TURN messages, but instead has a 4-byte header that includes a number known as a channel number. Each channel number in use is bound to a specific peer and thus serves as a shorthand for the peer's host transport address.
第二种方式就是用叫做 ChannelData 的消息格式。ChannelData 消息不同使用其他 STUN 消息的头,用 4个字节 代替 STUN 头,这 4个字节 包含了 channel number。每个 channel number 用来绑定指定的 peer,所以可以当成是一个 peer 的地址的快捷方式。
To bind a channel to a peer, the client sends a ChannelBind request to the server, and includes an unbound channel number and the transport address of the peer. Once the channel is bound, the client can use a ChannelData message to send the server data destined for the peer. Similarly, the server can relay data from that peer towards the client using a ChannelData message.
一个 channel 绑定到 一个 peer, client 发送 ChannelBind 请求到 server,请求包括一个没有绑定的 channel number 和 peer 的地址。一旦 channel 绑定,client 就可以用 ChannelData 去发送服务器数据到 peer。类似的,server 可以使用 ChannelData 转发 peer 向 client 发送的数据。
Channel bindings last for 10 minutes unless refreshed -- this lifetime was chosen to be longer than the permission lifetime. Channel bindings are refreshed by sending another ChannelBind request rebinding the channel to the peer. Like permissions (but unlike allocations), there is no way to explicitly delete a channel binding; the client must simply wait for it to time out.
如果不刷新,Channel bindings 可以持续 10分钟 -- 这个 lifetime 比permission 的 lifetime 长。Channel bindings 通过发送另外一个 ChannelBind 请求重新绑定 channel 到 peer来刷新,这里没办法明确的删除一个 channel binding;client 只能等待超时。
TURN TURN Peer Peer client server A B | | | | |-- ChannelBind req ---------------->| | | | (Peer A to 0x4001) | | | | | | | |<---------- ChannelBind succ resp --| | | | | | | |-- [0x4001] data ------------------>| | | | |=== data ===>| | | | | | | |<== data ====| | |<------------------ [0x4001] data --| | | | | | | |--- Send ind (Peer A)-------------->| | | | |=== data ===>| | | | | | | |<== data ====| | |<------------------ [0x4001] data --| | | | | | | Figure 4
Figure 4 shows the channel mechanism in use. The client has already created an allocation and now wishes to bind a channel to Peer A. To do this, the client sends a ChannelBind request to the server, specifying the transport address of Peer A and a channel number (0x4001). After that, the client can send application data encapsulated inside ChannelData messages to Peer A: this is shown as
Figure 4 展示了 channel 机制。client 已经创建了一个 allocation 并且想要绑定一个 channel 到 peer。为了达到这个目的,client 发送一个 ChannelBind 请求到 server,指定 Peer A 的地址 和 一个 channel number(0x4001)。然后,client 可以将应用程序数据放到 ChannelData 中发送给 Peer A:图中展示的
"[0x4001] data" where 0x4001 is the channel number. When the ChannelData message arrives at the server, the server transfers the data to a UDP datagram and sends it to Peer A (which is the peer bound to channel number 0x4001).
“[0x4001] data” 中的 0x4001 就是 channel number。当 ChannelData 消息到达 server,server 通过 udp 报文将数据发给 Peer A(这个 peer 绑定了 channel number 0x4001)
In the reverse direction, when Peer A sends a UDP datagram to the relayed transport address, this UDP datagram arrives at the server on the relayed transport address assigned to the allocation. Since the UDP datagram was received from Peer A, which has a channel number assigned to it, the server encapsulates the data into a ChannelData message when sending the data to the client.
在反方向,当 Peer A 发送 UDP 数据报到转发地址,这个 UDP 数据报到达服务器上跟 allocation 相关联的转发地址。因为 UDP 数据报文是从 Peer A 接收的,有一个 channel number 和它关联,server 将数据放到 ChannelData 消息中发给 client。
Once a channel has been bound, the client is free to intermix ChannelData messages and Send indications. In the figure, the client later decides to use a Send indication rather than a ChannelData message to send additional data to Peer A. The client might decide to do this, for example, so it can use the DONT-FRAGMENT attribute (see the next section). However, once a channel is bound, the server will always use a ChannelData message, as shown in the call flow.
一旦一个 channel 被绑定,client 可以自由的使用 ChannelData 消息和 Send indications。在图中,client 使用 Send indication 替代 Channel Data 发送数据到 Peer A。client 可能决定这样做,比如,它可以使用 DONT-FRAGMENT 属性(看下一章)。无论如何,一旦一个 channel 绑定了,server 永远都会用 ChannelData 消息,就像调用流程图中的一样。
Note that ChannelData messages can only be used for peers to which the client has bound a channel. In the example above, Peer A has been bound to a channel, but Peer B has not, so application data to and from Peer B would use the Send mechanism.
注意,ChannelData 消息仅仅能用在 client 绑定 channel 的 peer。上边的例子中,Peer A 绑定了一个 channel,但是 Peer B 没有绑定,所以应用程序数据到 Peer B或者来自PeerB都用 send 机制。
2.9 Anycast Discovery of Servers
This version of TURN has been designed to permit the future specification of a method of doing anycast discovery of a TURN server over UDP. Specifically, a TURN server can reject an Allocate request with the suggestion that the client try an alternate server. To avoid certain types of attacks, the client must use the same credentials with the alternate server as it would have with the initial server.
这个版本 TURN 协议被设计成未来会兼容 anycast discovery 。
一般来说,turn 服务器能拒绝 allocate 请求建议 client 访问备用服务器。为了杜绝这种攻击,client 必须要对备用服务器使用和初始服务器一样的认证。
4. General Behavior
This section contains general TURN processing rules that apply to all TURN messages. TURN is an extension to STUN. All TURN messages, with the exception of the ChannelData message, are STUN-formatted messages. All the base processing rules described in [RFC5389] apply to STUN-formatted messages. This means that all the message-forming and message- processing descriptions in this document are implicitly prefixed with the rules of [RFC5389].
本段包含了正常的 TURN 处理规则,规则适用于所有的 TURN 消息。
TURN 是 STUN 的扩展,所有 TURN 消息,除了 ChannelData 消息,都是 STUN 格式的消息。所有的基本处理规则按照 [RFC5389] ,并且适用于 STUN 格式消息。这就意味着所有的消息格式和消息处理流程都以 [RFC5389] 的规则为前提。
[RFC5389] specifies an authentication mechanism called the long-term credential mechanism. TURN servers and clients MUST implement this mechanism. The server MUST demand that all requests from the client be authenticated using this mechanism, or that a equally strong or stronger mechanism for client authentication is used.
[RFC5389] 描述了一个叫做 long-term credential mechanism 的认证机制。TURN SERVER 和 Client 必须实现这个机制。SERVER 必须要求所有来自 client 的请求都是用这个机制认证过的,或者用一种同样强大或者更强大的认证方式来认证。
Note that the long-term credential mechanism applies only to requests and cannot be used to authenticate indications; thus, indications in TURN are never authenticated. If the server requires requests to be authenticated, then the server's administrator MUST choose a realm value that will uniquely identify the username and password combination that the client must use, even if the client uses multiple servers under different administrations. The server's administrator MAY choose to allocate a unique username to each client, or MAY choose to allocate the same username to more than one client (for example, to all clients from the same department or company). For each allocation, the server SHOULD generate a new random nonce when the allocation is first attempted following the randomness recommendations in [RFC4086] and SHOULD expire the nonce at least once every hour during the lifetime of the allocation.
注意 long-term credential 机制仅仅适用于请求,不能用于认证 indication;所以,indications 不需要认证。如果 server 要求请求要认证,server 的管理员必须选择一个 realm,这个 realm 标识唯一的 username 和 password 组合给 client 使用,即使 client 在不同的服务器下不同的管理员下。server 的管理员可能选择一个唯一的 username 给每一个 client,也可能用相同的 username 给多个 client(比如,所有的 client 都来自相同公司或者相同部门)。对于每一个 allocation,server 生成一个新随机 nonce 时建议按照 [RFC4086] 随机性原则生成,并且在 alloction 生命周期内应该至少过期 nonce 一次。
All requests after the initial Allocate must use the same username as that used to create the allocation, to prevent attackers from hijacking the client's allocation. Specifically, if the server requires the use of the long-term credential mechanism, and if a non- Allocate request passes authentication under this mechanism, and if the 5-tuple identifies an existing allocation, but the request does not use the same username as used to create the allocation, then the request MUST be rejected with a 441 (Wrong Credentials) error.
所有初次 allocate 之后的请求都必须与创建 allocation 使用的 username 相同,特别的,如果 server 要求使用 long-term credential 机制,并且如果一个非 allocate 请求在这种机制下传递这种认证,并且如果 5-tuple 标识了一个存在的 allocation,但是请求不用和创建 allocation 使用一样的 username,这个请求必须要被拒绝,并返回一个 441 的错误。
When a TURN message arrives at the server from the client, the server uses the 5-tuple in the message to identify the associated allocation. For all TURN messages (including ChannelData) EXCEPT an Allocate request, if the 5-tuple does not identify an existing allocation, then the message MUST either be rejected with a 437 Allocation Mismatch error (if it is a request) or silently ignored (if it is an indication or a ChannelData message). A client receiving a 437 error response to a request other than Allocate MUST assume the allocation no longer exists.
当 TURN 消息从 client 到达 server,server 用这个消息的 5-tuple 去关联 allocatoin。对于所有的 TURN 消息(包括 ChannelData)除了 allocate 请求,如果 5-tuple 不能标识一个存在的 allocation,这个消息必须被拒绝,并返回一个 437 allocation missmatch 错误(如果这是一个请求),或者忽略这个消息(如果是 indication 或者是 ChannelData 消息)。client 收到一个 437的错误响应,只要不是 allocatie 产生的,client 必须假设 allocation 不存在。
[RFC5389] defines a number of attributes, including the SOFTWARE and FINGERPRINT attributes. The client SHOULD include the SOFTWARE attribute in all Allocate and Refresh requests and MAY include it in any other requests or indications. The server SHOULD include the SOFTWARE attribute in all Allocate and Refresh responses (either success or failure) and MAY include it in other responses or indications. The client and the server MAY include the FINGERPRINT attribute in any STUN-formatted messages defined in this document.
[RFC5389]定义了一些属性,包括 SOFTWARE / FINGERPRINT 属性。client 应该包含 SOFTWARE 属性在所有的 allocate 和 refresh 请求里,在其他请求或者 indications 也应该包含。server 应该包含 SOFTWARE 属性在所有的 allocate 和 refresh 响应中(无论成功或者失败),在其他响应或者 indications 也应该包含。client 和 server 可能包含 FINGERPRINT 属性在这个文档定义的任何 STUN 格式消息里。
TURN does not use the backwards-compatibility mechanism described in [RFC5389]. TURN, as defined in this specification, only supports IPv4. The client's IP address, the server's IP address, and all IP addresses appearing in a relayed transport address MUST be IPv4 addresses.
TURN 不用向后兼容 [RFC5389]
TURN 在这个规范中的定义,仅仅支持 IPV4。client 的 IP,server 的 IP,relayed transport 的 IP 必须是 IPV4。
By default, TURN runs on the same ports as STUN: 3478 for TURN over UDP and TCP, and 5349 for TURN over TLS. However, TURN has its own set of Service Record (SRV) names: "turn" for UDP and TCP, and "turns" for TLS. Either the SRV procedures or the ALTERNATE-SERVER procedures, both described in Section 6, can be used to run TURN on a different port.
作为默认,TURN 运行在和 STUN 一样的端口 3478,如果使用了 TLS 就运行在 5349。TURN 有它自己的 服务记录集合(SRV)名称:”turn“ 就是基于 UDP 或者 TCP,”turns“ 就是基于 TLS。无论是 SVR 程序还是 备用服务器程序,两个都有在 Section6 中描述,都能在运行在不同的端口。
To ensure interoperability, a TURN server MUST support the use of UDP transport between the client and the server, and SHOULD support the use of TCP and TLS transport.
为了确保交互,TURN 服务器必须支持 client 和 server 使用 UDP,也应该支持使用 TCP 和 TLS 。
When UDP transport is used between the client and the server, the client will retransmit a request if it does not receive a response within a certain timeout period. Because of this, the server may receive two (or more) requests with the same 5-tuple and same transaction id. STUN requires that the server recognize this case and treat the request as idempotent (see [RFC5389]). Some implementations may choose to meet this requirement by remembering all received requests and the corresponding responses for 40 seconds. Other implementations may choose to reprocess the request and arrange that such reprocessing returns essentially the same response. To aid implementors who choose the latter approach (the so-called "stateless stack approach"), this specification includes some implementation notes on how this might be done. Implementations are free to choose either approach or choose some other approach that gives the same results.
当 client 和 server 之间使用 UDP,如果 client 在超时时间没有收到回复,client 会进行重传。因为这个原因,server 可能会收到 多个相同 5-tuple 和 相同 transcation id 的请求。STUN 要求 server 能够识别这种状况(参考 [RFC7389])。一些实现可能会通过记住 40秒 内所有到达的请求和响应的响应来满足此要求。其他实现可能会选择重新处理请求并且安排这样处理流程返回同样的响应。为了帮助选择后一种方法的实现者(所谓的 ”stateless stack approac“),这个规范包含了一些实现内容告诉他们如何做到。实现可以自由选择一种方法只要能给出相同结果就可以。
When TCP transport is used between the client and the server, it is possible that a bit error will cause a length field in a TURN packet to become corrupted, causing the receiver to lose synchronization with the incoming stream of TURN messages. A client or server that detects a long sequence of invalid TURN messages over TCP transport SHOULD close the corresponding TCP connection to help the other end detect this situation more rapidly.
当 server 和 client 使用 TCP,一个 bit 错误就能引起 TURN 数据包的长度不正确,从而导致接收方和数据与传入 TURN消息失去同步。通过 TCP 传输校验检测到 TURN 消息不合法的 server 和 client 应该关闭连接以便其他端可以检测到错误。
To mitigate either intentional or unintentional denial-of-service attacks against the server by clients with valid usernames and passwords, it is RECOMMENDED that the server impose limits on both the number of allocations active at one time for a given username and on the amount of bandwidth those allocations can use. The server should reject new allocations that would exceed the limit on the allowed number of allocations active at one time with a 486 (Allocation Quota Exceeded) (see Section 6.2), and should discard application data traffic that exceeds the bandwidth quota.
为了减少有意或者无意的服务器拒绝攻击,client 应该带有合法的用户明和密码,推荐 server 限制一个用户名一次 allocatoin 的数量,以及 allocation 能使用的带宽。如果达到了 allocation 数量限制, server 应该拒绝新的 allcation 并返回一个 486 错误(参考 Section 6.2),如果应用数据传输量到达了限制的最大带宽,应该丢第应用数据。
5. Allocation
All TURN operations revolve around allocations, and all TURN messages are associated with an allocation. An allocation conceptually consists of the following state data: o the relayed transport address; o the 5-tuple: (client's IP address, client's port, server IP address, server port, transport protocol); o the authentication information; o the time-to-expiry; o a list of permissions; o a list of channel to peer bindings.
TURN 的所有操作都是围绕着 allocations,所有的 turn 消息都和 allocation 关联。allocation 概念由以下状态数据组成:
relayed transport 地址
5-tuple:(client 的 ip,client 端口,server ip,server port,传输协议)
认证信息
过期时间
权限列表
channel 绑定 peer 列表
The relayed transport address is the transport address allocated by the server for communicating with peers, while the 5-tuple describes the communication path between the client and the server. On the client, the 5-tuple uses the client's host transport address; on the server, the 5-tuple uses the client's server-reflexive transport address.
relayed transport addresss 是 server 上申请的和 peer 通信传输地址,5-tuple 描述了 client 和 server 的通信路径。在 client 端,5-tuple 用的是 client 的主机地址;在服务端,5-tupe 用 client 的 server-reflexive 地址。
Both the relayed transport address and the 5-tuple MUST be unique across all allocations, so either one can be used to uniquely identify the allocation.
relayed transport address 和 5-tupe 在所有 allocaioins 中必须是唯一的,任何以一个都可以标示唯一的 allocation。
The authentication information (e.g., username, password, realm, and nonce) is used to both verify subsequent requests and to compute the message integrity of responses. The username, realm, and nonce values are initially those used in the authenticated Allocate request that creates the allocation, though the server can change the nonce value during the lifetime of the allocation using a 438 (Stale Nonce) reply. Note that, rather than storing the password explicitly, for security reasons, it may be desirable for the server to store the key value, which is an MD5 hash over the username, realm, and password (see [RFC5389]).
认证信息(比如,用户名,密码,realm, nonce)用来校验后续请求和计算 response 的 message integrity。username realm nonce 的值就是 创建 allocate 认证的值,尽管 server 可以用 438(stale nonce) 回复 在 allocation 生命周期内改变 nonce。 注意,相比显示的存储 password,处于安全原因,server 更希望存储一个 key 值,这个值就是基于 username realm password 的 MD5 Hash。
The time-to-expiry is the time in seconds left until the allocation expires. Each Allocate or Refresh transaction sets this timer, which then ticks down towards 0. By default, each Allocate or Refresh transaction resets this timer to the default lifetime value of 600 seconds (10 minutes), but the client can request a different value in the Allocate and Refresh request. Allocations can only be refreshed using the Refresh request; sending data to a peer does not refresh an allocation. When an allocation expires, the state data associated with the allocation can be freed.
time -to-expiry 就是 allocatioin 按秒计算的剩余时间。每一个 allocation 或者 refresh 都设置一个 timer,这个 timer 一直减到 0。默认的,每一个 allocate 或者 refresh 都会重置 timer 到 600秒(10分钟),但是 client 可以在 allocate 和 refresh 中请求一个不同的值。allocations 只能用 refresh 刷新;发送数据到 peer 不能刷新 allocation。当一个 alocation 过期,和 allocation 相关的状态都会被释放。
The list of permissions is described in Section 8 and the list of channels is described in Section 11.
permission 列表描述在 Section8,channel 列表描述在 Section 11
6. Creating an Allocation
An allocation on the server is created using an Allocate transaction.
6.1. Sending an Allocate Request
The client forms an Allocate request as follows. The client first picks a host transport address. It is RECOMMENDED that the client pick a currently unused transport address, typically by allowing the underlying OS to pick a currently unused port for a new socket.
客户端按如下步骤组合一个 allocate 请求。
客户端收到拿到 host 的传输地址。推荐客户端取一个当前没有其他人用的传输地址,通常用底层系统为一个 新的 socket 选择一个没使用的 port。(这里说的传输地址应该主要是指端口)
The client then picks a transport protocol to use between the client and the server. The transport protocol MUST be one of UDP, TCP, or TLS-over-TCP. Since this specification only allows UDP between the server and the peers, it is RECOMMENDED that the client pick UDP unless it has a reason to use a different transport. One reason to pick a different transport would be that the client believes, either through configuration or by experiment, that it is unable to contact any TURN server using UDP. See Section 2.1 for more discussion.
客户端选择一个传输协议用于客户端和服务器之间的通信。这个协议应该是 UDP,TCP,TLS-OVER-TCP 其中的一个。因为这个文档只允许服务器和各个端之间使用 UDP,推荐客户端选择 UDP,除非有原因让我们去选择其他协议。一个原因可能是客户端相信,通过配置和试验用 UDP 都不能和 TURN 服务器通信。
The client also picks a server transport address, which SHOULD be done as follows. The client receives (perhaps through configuration) a domain name for a TURN server. The client then uses the DNS procedures described in [RFC5389], but using an SRV service name of "turn" (or "turns" for TURN over TLS) instead of "stun" (or "stuns"). For example, to find servers in the example.com domain, the client performs a lookup for '_turn._udp.example.com', '_turn._tcp.example.com', and '_turns._tcp.example.com' if the client wants to communicate with the server using UDP, TCP, or TLS-over-TCP, respectively.
client 也应该有一个 server 传输地址,应该按照下面步骤去完成。client 收到 (也许是通过配置拿到)TURN server 域名。client 用 DNS 流程解析域名 按照 [RFC5389],但是 用 “turn” (或者 turns ,就是 TLS 的 TURN ) 代替 “stun” (或者 stuns)。比如,在 example.com 域名中查找 servers,client 如果想分别和 server 使用 UDP / TCP / TLS-OVER-TCP 通信,client 应该使用域名 '_turn._udp.example.com' 和 '_tun._tcp.example.com' 和 ' turns.tcp.example.com'。
The client MUST include a REQUESTED-TRANSPORT attribute in the request. This attribute specifies the transport protocol between the server and the peers (note that this is NOT the transport protocol that appears in the 5-tuple). In this specification, the REQUESTED- TRANSPORT type is always UDP. This attribute is included to allow future extensions to specify other protocols.
客户端必须在请求中包含 REQUESTED-TRANSPORT 属性。这个属性指定了服务器和客户端之间的传输协议(这个传输协议不是5元组中的传输协议)。在这个文档中,REQUESTED-TRANSPORT 永远是 UDP。这个属性以后允许扩展到指定其他协议。
If the client wishes the server to initialize the time-to-expiry field of the allocation to some value other than the default
lifetime, then it MAY include a LIFETIME attribute specifying its desired value. This is just a request, and the server may elect to use a different value. Note that the server will ignore requests to initialize the field to less than the default value.
如果客户端希望服务器初始化 allocation 的过期时间为默认值以外的其他值,客户端可以包含一个 LIFETIME 属性并且指定希望的值。这仅仅是一个请求,服务器可能选择一个不同值。注意,如果初始化的值小于服务器的默认的值,服务器会忽略这个请求。
If the client wishes to later use the DONT-FRAGMENT attribute in one or more Send indications on this allocation, then the client SHOULD include the DONT-FRAGMENT attribute in the Allocate request. This allows the client to test whether this attribute is supported by the server.
如果 client 希望稍后在 allocation 使用多个 send indications 并且使用 DONT-FRAGMENT 属性,client 应该包含 DONT-FRAGMENT 属性在 allcation 请求中。这样可以测试 server 是否支持这个属性。
If the client requires the port number of the relayed transport address be even, the client includes the EVEN-PORT attribute. If this attribute is not included, then the port can be even or odd. By setting the R bit in the EVEN-PORT attribute to 1, the client can request that the server reserve the next highest port number (on the same IP address) for a subsequent allocation. If the R bit is 0, no such request is made.
如果 client 要求 relayed transport address 的端口号是偶数,client 要有 EVEN-PORT 属性。如果没有这个属性,端口可以是偶数或者奇数。通过设置 EVEN-PORT 属性 R bit 为 1,client 可以请求 server 保留下一个最高的端口(在相同的IP上)给接下来的 allocation。如果 R bit 是 0, 没有这个请求。
The client MAY also include a RESERVATION-TOKEN attribute in the request to ask the server to use a previously reserved port for the allocation. If the RESERVATION-TOKEN attribute is included, then the client MUST omit the EVEN-PORT attribute. Once constructed, the client sends the Allocate request on the 5-tuple.
client 可能包含一个 RESERVATION-TOKEN 属性让 server 用 上一个 allocation 保留的端口。如果 有 RESERVATION-TOKEN 属性,client 必须忽略 EVEN-PORT 属性。
一旦创建成功,client 基于 5-tuple 发送 allocate 请求。
6.2. Receiving an Allocate Request
When the server receives an Allocate request, it performs the following checks:
当 server 收到 allocate 请求,应该执行如下检查:
1. The server MUST require that the request be authenticated. This authentication MUST be done using the long-term credential mechanism of [RFC5389] unless the client and server agree to use another mechanism through some procedure outside the scope of this document.
server 必须要求 请求都是被认证的。认证必须使用 long-term credential 机制 [RFC5389] 除非 client 和 server 同意用本文档之外的其他机制。
2. The server checks if the 5-tuple is currently in use by an existing allocation. If yes, the server rejects the request with a 437 (Allocation Mismatch) error.
2. server 检查当前的 5-tupe 是否是已经存在的 allocation,如果是,server 拒绝请求 并返回 437 (allocation missmatch)错误。
3. The server checks if the request contains a REQUESTED-TRANSPORT attribute. If the REQUESTED-TRANSPORT attribute is not included or is malformed, the server rejects the request with a 400 (Bad Request) error. Otherwise, if the attribute is included but specifies a protocol other that UDP, the server rejects the request with a 442 (Unsupported Transport Protocol) error.
3. server 检查 请求是否有 REQUESED-RANSPORT 属性。如果 REQUESTED-TRANSPORT 属性没有或者不正确,server 拒绝请求并返回 400 (bad request)错误码。如果有这个属性,但是指定一个 UDP 以外的协议,server 拒绝 请求返回以恶 442 错误(unsupport Transport protocol)。
4. The request may contain a DONT-FRAGMENT attribute. If it does, but the server does not support sending UDP datagrams with the DF bit set to 1 (see Section 12), then the server treats the DONT- FRAGMENT attribute in the Allocate request as an unknown comprehension-required attribute.
4. 请求可能含有 DONT-FRAGMENT 属性。如果有,但是服务器不支持设置 UDP DF BIT为1(参考 Section 12),server 对待这个属性就按照不认识的属性对待。
5. The server checks if the request contains a RESERVATION-TOKEN attribute. If yes, and the request also contains an EVEN-PORT attribute, then the server rejects the request with a 400 (Bad Request) error. Otherwise, it checks to see if the token is valid (i.e., the token is in range and has not expired and the corresponding relayed transport address is still available). If the token is not valid for some reason, the server rejects the request with a 508 (Insufficient Capacity) error.
5. server 检查是否有 RESERVATION-TOKEN 属性。如果有,请求包含一个 EVENT-PORT 属性,server 拒绝请求返回 400(bad request) 错误。另外,server 检查 token 是否合法(比如,token 在范围内,并且还没有过期,相关的 relayed transport address 还是可用的)。如果 token 因为某些原因不合法,服务器拒绝请求 返回 508(insufficient capacity)错误。
6. The server checks if the request contains an EVEN-PORT attribute. If yes, then the server checks that it can satisfy the request (i.e., can allocate a relayed transport address as described below). If the server cannot satisfy the request, then the server rejects the request with a 508 (Insufficient Capacity) error.
6. server 检查是否含有 EVENT-PORT 属性,如果有,server 检查是否能满足这个请求(比如,按照下面描述的是否能分配以恶 relayed transport address)。如果 server 不能满足请求,server 拒绝请求返回 508 错误 (insufficient capacity)。
7. At any point, the server MAY choose to reject the request with a 486 (Allocation Quota Reached) error if it feels the client is trying to exceed some locally defined allocation quota. The server is free to define this allocation quota any way it wishes, but SHOULD define it based on the username used to authenticate the request, and not on the client's transport address.
7. 在任何时间点,server 可能选择拒绝请求返回 486 错误(allocation quota reached),因为 server 感觉 client 的尝试已经达到了 server 本地定义的 allocation 配额限制。server 可以自由的定义这些配额,但是应该基于认证的 username 定义,而不是 client 的 transport address。
8. Also at any point, the server MAY choose to reject the request with a 300 (Try Alternate) error if it wishes to redirect the client to a different server. The use of this error code and attribute follow the specification in [RFC5389].
8. server 可以选择拒绝请求返回300错误(try alternate),因为 server 希望 client 去链接其他的 server 。这个错误码和属性在 [RFC5389]。
If all the checks pass, the server creates the allocation. The 5-tuple is set to the 5-tuple from the Allocate request, while the list of permissions and the list of channels are initially empty.
如果所有的检测通过,server 创建一个 allocatioin。5-tupe 设置成功 来自 allocate 请求的 5-tuple,permisson 列表和 channel 列表组开始是空的。
The server chooses a relayed transport address for the allocation as follows:
server 给一个 allocation 选择一个 relayed tranpsort address 按照如下步骤:
o If the request contains a RESERVATION-TOKEN, the server uses the previously reserved transport address corresponding to the included token (if it is still available). Note that the reservation is a server-wide reservation and is not specific to a particular allocation, since the Allocate request containing the RESERVATION-TOKEN uses a different 5-tuple than the Allocate request that made the reservation. The 5-tuple for the Allocate request containing the RESERVATION-TOKEN attribute can be any allowed 5-tuple; it can use a different client IP address and port, a different transport protocol, and even different server IP address and port (provided, of course, that the server IP address and port are ones on which the server is listening for TURN requests).
如果请求包含一个 RESERVATION-TOKEN,server用一个和请求中包含的 token(如果还是合法的) 相关的之前保留的 transport address。 注意,预定是一个 服务器范围的预定,不是特定的 allocation ,因为 包含 RESERVATION-TOKEN 的 allocate 请求用一个 与 一个 allocate 使用不同的 5-tuple。包含 RESERVATION-TOKEN 属性的 allocate 请求的 5-tuple 可以是任意被允许的 5-tuple;可以用不同 client ip 和 端口,一个 不同的传输协议,甚至是不同的 server ip 和 端口(当然,server ip 和 端口 也监听着 TRUN 端口)。
o If the request contains an EVEN-PORT attribute with the R bit set to 0, then the server allocates a relayed transport address with an even port number.
如果 请求 包含 EVEN-PORT 属性并且 R bit 设置为 0, server 分配一个 relayed trasnport address 用一个偶数端口号
o If the request contains an EVEN-PORT attribute with the R bit set to 1, then the server looks for a pair of port numbers N and N+1 on the same IP address, where N is even. Port N is used in the current allocation, while the relayed transport address with port N+1 is assigned a token and reserved for a future allocation. The server MUST hold this reservation for at least 30 seconds, and MAY choose to hold longer (e.g., until the allocation with port N expires). The server then includes the token in a RESERVATION- TOKEN attribute in the success response.
如果请求含有 EVEN-PORT 属性并且 R bit 设置为 1,这时 server 在相同得 IP 地址上查找一对 端口 N 和 N+1, N 是偶数。端口 N 用于当前的 allocation,而 端口是 N + 1 的 relayed 地址被关联到一个 TOKEN 并且会为以后的 allocation 保留。server 必须保持这个保留至少 30 秒,或者更长时间(比如。直到 port N 的 allocation 过期)。这时 server 返回一个成功响应,响应中包含一个 RESERVATION-TOKEN 属性。
o Otherwise, the server allocates any available relayed transport address.
否则 server 分配任意合法的 relayed 地址
In all cases, the server SHOULD only allocate ports from the range 49152 - 65535 (the Dynamic and/or Private Port range [Port-Numbers]), unless the TURN server application knows, through some means not specified here, that other applications running on the same host as the TURN server application will not be impacted by allocating ports outside this range. This condition can often be satisfied by running the TURN server application on a dedicated machine and/or by arranging that any other applications on the machine allocate ports before the TURN server application starts. In any case, the TURN server SHOULD NOT allocate ports in the range 0 - 1023 (the Well- Known Port range) to discourage clients from using TURN to run standard services.
在所有的情形中,server 应该仅仅 分配 49152-65535 范围的端口 (动态/或者私有端口范围),除非 TURN server 应用程序知道,通过其他的方法,运行在相同主机上作为 TURN server 应用程序的其他应用程序不会收到分配范围外端口的影响。这个条件可以通过在专用的机器上运行 TURN server 应用程序来满足,或者在机器上让其他的应用程序在 TURN server 应用程序启动前先分配到端口来满足。在任意case中,TURN server 不应该分配 0 - 1023(知名端口范围)端口,进而阻止 client 用 TRUN 运行标准服务。
NOTE: The IETF is currently investigating the topic of randomized port assignments to avoid certain types of attacks (see [TSVWG-PORT]). It is strongly recommended that a TURN implementor keep abreast of this topic and, if appropriate, implement a randomized port assignment algorithm. This is especially applicable to servers that choose to pre-allocate a number of ports from the underlying OS and then later assign them to allocations; for example, a server may choose this technique to implement the EVEN-PORT attribute.
注意:IETF 正在调查随机化端口主题去避免攻击(参考 [TSVWG-PORT])。强烈建议 TURN 实现者持续关注这个主题,合适的时候实现一个随机端口的算法。从底层操作系统预先分配好端口然后再分配给 allocations 特别适合 servers;比如,server 选择这种技术实现 EVEN-PORT 属性。
The server determines the initial value of the time-to-expiry field as follows. If the request contains a LIFETIME attribute, then the server computes the minimum of the client's proposed lifetime and the server's maximum allowed lifetime. If this computed value is greater than the default lifetime, then the server uses the computed lifetime as the initial value of the time-to-expiry field. Otherwise, the server uses the default lifetime. It is RECOMMENDED that the server use a maximum allowed lifetime value of no more than 3600 seconds (1 hour). Servers that implement allocation quotas or charge users for allocations in some way may wish to use a smaller maximum allowed lifetime (perhaps as small as the default lifetime) to more quickly remove orphaned allocations (that is, allocations where the corresponding client has crashed or terminated or the client connection has been lost for some reason). Also, note that the time- to-expiry is recomputed with each successful Refresh request, and thus the value computed here applies only until the first refresh.
server 按照下面的方式检查 time-to-expiry 的初始值。如果请求又 LIFETIME 属性,server 计算 client 提供的 lifetime 的最小值 和 server 的 lifetime 的最大值。如果 计算的值 大于默认 lifetime,server 用计算的 lifetime 作为 time-to-expiry 的初始值。强烈建议 server 使用的最大值不超过 3600 秒(1个小时)。那些实现了 allocation 配额或者 allocation 向用户收费的 server 希望用一个小的最大生命周期(也许像默认生命周期那么小)去快速的移除 allocations(也就是,allocations 相关联的 client 已经崩溃或者终止或者 client 的连接因为某些原因已经丢失);另外注意,time-to-expiry 每次都会被成功的 refresh 请求重置,所以这里的计算仅仅适用于第一次刷新。
Once the allocation is created, the server replies with a success response. The success response contains:
一旦一个 allocation 创建,server 回复一个成功响应,这个成功响应包含:
o An XOR-RELAYED-ADDRESS attribute containing the relayed transport address. o A LIFETIME attribute containing the current value of the time-to- expiry timer. o A RESERVATION-TOKEN attribute (if a second relayed transport address was reserved). o An XOR-MAPPED-ADDRESS attribute containing the client's IP address and port (from the 5-tuple).
一个 XOR-RELAYED-ADDRESS 属性包含 relayed 地址
一个 LIFETIME 属性包含当前的生命周期过期时间
一个 RESERVATION-TOKEN 属性(如果 第二个 relayed 地址被保留)
一个 XOR-MAPPED-ADDRESS 属性 包含 client 的 IP 地址和端口 (来在 5-tuple)。
NOTE: The XOR-MAPPED-ADDRESS attribute is included in the response as a convenience to the client. TURN itself does not make use of this value, but clients running ICE can often need this value and can thus avoid having to do an extra Binding transaction with some STUN server to learn it.
注意:XOR-MAPPED-ADDRESS 属性在响应中是为了方便 client。TURN server 不需要用这个值,但是 clients 执行 ICE 经常需要这个值,而且可以避免用额外的 binding 事务去学习这个值。
The response (either success or error) is sent back to the client on the 5-tuple.
响应(无论成功或者失败)通过 5-tuple 发会给 client。
NOTE: When the Allocate request is sent over UDP, section 7.3.1 of [RFC5389] requires that the server handle the possible retransmissions of the request so that retransmissions do not cause multiple allocations to be created. Implementations may achieve this using the so-called "stateless stack approach" as follows. To detect retransmissions when the original request was successful in creating an allocation,
注意:allocation 请求基于 UDP 的时候,[RFC5389] 7.3.1 要求服务器处理重传的请求,不能引起多个allocaion建立。实现按照下面说的 “stateless stack approach”去做。为了检测一个 allocation 原始请求已经成功但是还有重传,
the server can store the transaction id that created the request with the allocation data and compare it with incoming Allocate requests on the same 5-tuple. Once such a request is detected, the server can stop parsing the request and immediately generate a success response. When building this response, the value of the LIFETIME attribute can be taken from the time-to-expiry field in the allocate state data, even though this value may differ slightly from the LIFETIME value originally returned. In addition, the server may need to store an indication of any reservation token returned in the original response, so that this may be returned in any retransmitted responses.
服务器可以存储已经成功请求的 transacation id 并且和到来的 allocate 请求对比 5元组。一旦一个请求被检测到,服务器应该停止解析请求并且立即生成一个成功的响应。创建这个响应的时候,LIFETIME 属性的值可以用 allocate 状态数据中过期字段,及时有些不同也没关系。另外,服务器可能需要存储原始响应的任何 token, 以便于能返回给重传的请求。
For the case where the original request was unsuccessful in creating an allocation, the server may choose to do nothing special. Note, however, that there is a rare case where the server rejects the original request but accepts the retransmitted request (because conditions have changed in the brief intervening time period). If the client receives the first failure response, it will ignore the second (success) response and believe that an allocation was not created. An allocation created in this matter will eventually timeout, since the client will not refresh it. Furthermore, if the client later retries with the same 5-tuple but different transaction id, it will receive a 437 (Allocation Mismatch), which will cause it to retry with a different 5-tuple. The server may use a smaller maximum lifetime value to minimize the lifetime of allocations "orphaned" in this manner.
对于原始 allocation 请求创建失败的情况,服务器可以选择不做任何事情。有一种少见的情况,服务器拒绝原始请求,但是接收重传的请求(因为条件可能已经改变了)。如果 client 收到第一个失败响应,client 会忽略第二个响应(成功响应),并且认为 allocaion 没有创建。这种情况下 allocation 创建会超时,因为客户端不会刷新。如果 client 后来用相同的 5元组不同的 transacation id 去重试,将会返回 437(allocation missmatch),这会引起client 用不同的 5元组 去重试。服务器可以用一个小一点的 最大声明周期去最小化 allocation 的 lifetime。
7. Refreshing an Allocation
A Refresh transaction can be used to either (a) refresh an existing allocation and update its time-to-expiry or (b) delete an existing allocation. If a client wishes to continue using an allocation, then the client MUST refresh it before it expires. It is suggested that the client refresh the allocation roughly 1 minute before it expires. If a client no longer wishes to use an allocation, then it SHOULD explicitly delete the allocation. A client MAY refresh an allocation at any time for other reasons.
一个 Refresh 事务既可以刷新存在的 allocation 的过期时间,也可以删除一个存在的 allocation。
如果 client 希望继续使用一个 allocation, client 必须要在过期前刷新 allocation。建议 client 在 allocation 过期前 1分钟刷新。如果 client 不再使用 allocation,client 应该明确的删除 allocation。client 可能在任何时间因为任何理由刷新 allocation。
7.1. Sending a Refresh Request
If the client wishes to immediately delete an existing allocation, it includes a LIFETIME attribute with a value of 0. All other forms of the request refresh the allocation. The Refresh transaction updates the time-to-expiry timer of an allocation. If the client wishes the server to set the time-to- expiry timer to something other than the default lifetime, it includes a LIFETIME attribute with the requested value. The server then computes a new time-to-expiry value in the same way as it does for an Allocate transaction, with the exception that a requested lifetime of 0 causes the server to immediately delete the allocation.
如果 client 希望立即删除一个 allocation,LIFETIME 属性应该为 0. 所有其他形式的 refresh 请求都是刷新 allocation。
Refresh 事务更新一个 allocation 的过期时间。如果 client 想要设置一个过期时间,而不是用服务器的默认事件,refresh 需要包含一个 LIFETIME 属性,值为 client 期望的时间。服务器会立即给 allocation 计算一个新的过期时间,如果 refresh 中的 lifetime 是 0,将会引起服务器立即删除 allocation。
7.2. Receiving a Refresh Request
When the server receives a Refresh request, it processes as per Section 4 plus the specific rules mentioned here. The server computes a value called the "desired lifetime" as follows: if the request contains a LIFETIME attribute and the attribute value is 0, then the "desired lifetime" is 0. Otherwise, if the request contains a LIFETIME attribute, then the server computes the minimum of the client's requested lifetime and the server's maximum allowed lifetime. If this computed value is greater than the default lifetime, then the "desired lifetime" is the computed value. Otherwise, the "desired lifetime" is the default lifetime.
当服务器收到 refresh 请求,按照 section 4 加上这里提及的规则处理。服务器计算按以下步骤计算一个叫做 “desired lifetime” 的值:如果请求中的 LIFETIME 属性的值是 0,“desired lifetime” 是 0。如果请求包含一个 LIFETIME 属性,服务器计算 client 请求的最小 lifetime 和 服务器的最大的允许的 lifetime。如果计算值大于默认的 lifetime,“desired lifetime” 就是计算的值。否则,“desired lifetime” 就是默认的 lifetime。
Subsequent processing depends on the "desired lifetime" value: o If the "desired lifetime" is 0, then the request succeeds and the allocation is deleted. o If the "desired lifetime" is non-zero, then the request succeeds and the allocation's time-to-expiry is set to the "desired lifetime". If the request succeeds, then the server sends a success response containing: o A LIFETIME attribute containing the current value of the time-to- expiry timer.
接下来的处理依靠 “desired lifetime”:
如果 “desired lifetime” 是 0, 并且请求成功,allocation 删除。
如果 “desired lifetime” 不是 0, 并且请求成功,allocation 的过期时间被设置成 “desired lifetime”。
如果请求成功,服务器发送一个成功的响应,响应中包含:
LIFETIME 属性,值就是当前的过期时间。
NOTE: A server need not do anything special to implement idempotency of Refresh requests over UDP using the "stateless stack approach". Retransmitted Refresh requests with a non-zero "desired lifetime" will simply refresh the allocation. A retransmitted Refresh request with a zero "desired lifetime" will cause a 437 (Allocation Mismatch) response if the allocation has already been deleted, but the client will treat this as equivalent to a success response (see below).
注意:服务器不做什么特殊的操作处理重传的 refresh 请求。带有非零的 “desired lifetime” 重传 refresh 请求只是简单的刷新 allocation。如果这个 allocation 已经被删除,一个带有 0值的 “desired lifetime” 重传的 refresh 请求会引起服务器返回一个 437 的错误响应,但是 client 还是当场一个成功的响应。
7.3. Receiving a Refresh Response
If the client receives a success response to its Refresh request with a non-zero lifetime, it updates its copy of the allocation data structure with the time-to-expiry value contained in the response. If the client receives a 437 (Allocation Mismatch) error response to a request to delete the allocation, then the allocation no longer exists and it should consider its request as having effectively succeeded.
如果 client 发送的 refresh 请求有一个带有 非0 liefetime 的成功响应,client 会用响应中的数据过期时间更新 allocatoin 数据结构。
如果 client 发送删除 allocation 请求收到了一个 437 错误响应,应该当成 allocation 已经不存在,并且把 437 这个错误响应当成成功响应。
8. Permissions
For each allocation, the server keeps a list of zero or more permissions. Each permission consists of an IP address and an associated time-to-expiry. While a permission exists, all peers using the IP address in the permission are allowed to send data to
the client. The time-to-expiry is the number of seconds until the permission expires. Within the context of an allocation, a permission is uniquely identified by its associated IP address.
对于每一个 allocation, 服务器保存一个权限列表。每一个权限由一个 IP 地址和一个 过期时间。当一个权限存在,所有使用这个权限中的IP的对端被允许发送数据到客户端的。time-to-expiry 是以秒为单位的时间。allocation 的上下文内,权限应该由关联的 IP 地址 表示其是唯一的。
By sending either CreatePermission requests or ChannelBind requests, the client can cause the server to install or refresh a permission for a given IP address. This causes one of two things to happen:
对给定的 IP 地址发送 CreatePermission 或者 ChannelBind 会引起 服务器 安装 或者 刷新 权限。这个情况下有 2个 事情发生:
o If no permission for that IP address exists, then a permission is created with the given IP address and a time-to-expiry equal to Permission Lifetime. o If a permission for that IP address already exists, then the time- to-expiry for that permission is reset to Permission Lifetime.
如果 IP 存在并且没有权限,会给这个 IP 创建一个权限和一个过期时间,过期时间就是 Permission 的生命周期。
如果 IP 存在并且有权限,过期时间会更新成 Permisson 生命周期。
The Permission Lifetime MUST be 300 seconds (= 5 minutes). Each permission's time-to-expiry decreases down once per second until it reaches 0; at which point, the permission expires and is deleted. CreatePermission and ChannelBind requests may be freely intermixed on a permission. A given permission may be initially installed and/or refreshed with a CreatePermission request, and then later refreshed with a ChannelBind request, or vice versa.
Permisson 的生命周期必须是 300 秒。
每一个 permisson 的 time-to-expiry 是 一秒一秒 递减的,直到最后为0;这个时候,permisson 过期并且删除这个权限。CreatePermisson 和 ChannelBind 可能用一个权限。一个权限可能开始是通过 CreatePermisson 安装,后来可能通过 ChannelBind 进行刷新。
When a UDP datagram arrives at the relayed transport address for the allocation, the server extracts the source IP address from the IP header. The server then compares this address with the IP address associated with each permission in the list of permissions for the allocation. If no match is found, relaying is not permitted, and the server silently discards the UDP datagram. If an exact match is found, then the permission check is considered to have succeeded and the server continues to process the UDP datagram as specified elsewhere (Section 10.3). Note that only addresses are compared and port numbers are not considered.
当一个 udp 数据包到达 allocation 的 relayed transport address,服务器能够拿到 源 的 IP 地址。服务器比较这个地址 和 每一个权限关联的 IP 地址。如果没有匹配上,转发就被允许,服务器直接丢弃这个 udp 包。如果匹配到了,permission 检查就认为是成功的,并且服务器继续处理 UDP 数据包。注意 permisson 检查 只对比 地址就可以,不需要对比端口。
The permissions for one allocation are totally unrelated to the permissions for a different allocation. If an allocation expires, all its permissions expire with it.
一个 allocation 的 permisson 和 另一个 allocation 的 permisson 是没有关联的。如果一个 allocation 过期,和这个 allocation 相关的所有 permisson 都过期。
NOTE: Though TURN permissions expire after 5 minutes, many NATs deployed at the time of publication expire their UDP bindings considerably faster. Thus, an application using TURN will probably wish to send some sort of keep-alive traffic at a much faster rate. Applications using ICE should follow the keep-alive guidelines of ICE [RFC5245], and applications not using ICE are advised to do something similar.
注意:虽然 TURN permisson 过期时间是 5分钟,许多已经存在的 NAT 的 UDP binding 过期时间却很快。因此,使用 TURN 的应用程序应该用一个快的频率发送少量数据用来保活。用 ICE 的应用程序应该按照 ICE [RFC 5245] 来做,不用 ICE 的应用程序也建议这样做。
9. CreatePermission
TURN supports two ways for the client to install or refresh permissions on the server. This section describes one way: the CreatePermission request. A CreatePermission request may be used in conjunction with either the Send mechanism in Section 10 or the Channel mechanism in Section 11.
TURN 支持 2种方式 客户端在服务器端安装或者刷新权限。这个章节描述了一个方式:CreatePermission 请求。CreatePermission 请求是结合 Send 机制 或者 Channel 机制 使用的,Send 机制在 Section10,Channel 机制在 Section11.
9.1. Forming a CreatePermission Request
The client who wishes to install or refresh one or more permissions can send a CreatePermission request to the server. When forming a CreatePermission request, the client MUST include at least one XOR-PEER-ADDRESS attribute, and MAY include more than one such attribute. The IP address portion of each XOR-PEER-ADDRESS attribute contains the IP address for which a permission should be installed or refreshed. The port portion of each XOR-PEER-ADDRESS attribute will be ignored and can be any arbitrary value. The various XOR-PEER-ADDRESS attributes can appear in any order.
客户端可以通过发送一个 CreatePermission 请求到服务器 安装或者刷新 一个或者多个 权限。
当组建一个 CreatePermission 请求的时候,客户端必须包含至少一个 XOR-PEER-ADDRESS 属性,可能包含多于 1个 属性。XOR-PEER-ADDRESS 属性包含的 IP 地址部分就是 要给安装或者刷新的 IP。XOR-PEER-ADDRESS 的 port 部分,可以忽略。XOR-PEER-ADDRESS 属性没有任何顺序的要求。
9.2. Receiving a CreatePermission Request
When the server receives the CreatePermission request, it processes as per Section 4 plus the specific rules mentioned here.
当服务器接收到 CreatePermission 请求,服务器处理的过程按照 Section4 描述的规则处理。
If the message is valid and the server is capable of carrying out the request, then the server installs or refreshes a permission for the IP address contained in each XOR-PEER-ADDRESS attribute as described in Section 8. The port portion of each attribute is ignored and may be any arbitrary value.
如果消息合法,并且服务器有能力处理请求,服务器就会按照 Section8 给每一个 XOR-PEER-ADDRESS 属性的 IP 地址安装或者刷新权限。XOR-PEER-ADDRESS 属性中 port 部分忽略,它是任何值都可以。
The server then responds with a CreatePermission success response. There are no mandatory attributes in the success response.
这时服务器一个 CreatePermission 成功的响应,相应里没有什么必要的属性。
NOTE: A server need not do anything special to implement idempotency of CreatePermission requests over UDP using the "stateless stack approach". Retransmitted CreatePermission requests will simply refresh the permissions.
注意:服务器针对 基于 UDP 的 CreatePermission 的幂等性实现,不用做任何事情。重复的 CreatePermission 请求直接简单的刷新权限就好了。(idemotency 幂等性,就是多次重复的网络请求只有一个响应)
9.3. Receiving a CreatePermission Response
If the client receives a valid CreatePermission success response, then the client updates its data structures to indicate that the permissions have been installed or refreshed.
如果客户端接收到一个合法的 CreatePermission 成功响应,这时客户端应该更新数据结构,表示权限已经安装或者刷新。
10.1. Forming a Send Indication
The client can use a Send indication to pass data to the server for relaying to a peer. A client may use a Send indication even if a channel is bound to that peer. However, the client MUST ensure that there is a permission installed for the IP address of the peer to which the Send indication is being sent; this prevents a third party from using a TURN server to send data to arbitrary destinations. When forming a Send indication, the client MUST include an XOR-PEER- ADDRESS attribute and a DATA attribute. The XOR-PEER-ADDRESS attribute contains the transport address of the peer to which the data is to be sent, and the DATA attribute contains the actual application data to be sent to the peer. The client MAY include a DONT-FRAGMENT attribute in the Send indication if it wishes the server to set the DF bit on the UDP datagram sent to the peer.
客户端使用 Send indication 发送数据到服务器,让服务器转发给对端。一个客户端即时绑定了对端也可能使用send indication。无论如何,客户端必须要确认对端的ip地址已经安装了权限;这样可以防止第三方通过TURN服务器发送数据到任意地方。
生成一个send indicaiton的时候,客户端必须有 XOR-PEER-ADDRESS 属性和 DATA 属性。XOR-PEER-ADDRESS属性包含对端的传输地址,DATA属性包含要发给对端的数据。
客户端可能在 send indication 里包含一个 DONT-FRAGMENT 属性,如果他希望服务器发送给对端的UDP设置DF位
(XOR-PEER-ADDRESS 就是告诉服务器要发给谁)
10.4. Receiving a Data Indication
When the client receives a Data indication, it checks that the Data indication contains both an XOR-PEER-ADDRESS and a DATA attribute, and discards the indication if it does not. The client SHOULD also check that the XOR-PEER-ADDRESS attribute value contains an IP address with which the client believes there is an active permission, and discard the Data indication otherwise. Note that the DATA attribute is allowed to contain zero bytes of data.
当客户端收到一个 data indication,先检查是否有 XOR-PEER-ADDRESS 和 DATA 属性,如果没有,不处理这个 data indication。客户端应该检查 XOR-PEER-ADDRESS 属性值是否包含 IP 地址,并且 客户端相信已经有了一个激活的权限,如果没有或者没有权限,不处理这个 data indication。注意 DATA 属性长度可以是 0。
NOTE: The latter check protects the client against an attacker who somehow manages to trick the server into installing permissions not desired by the client.
注意:后一种检测(就是权限的检测)可以保护客户端免受攻击,攻击者会诱导服务器安装 客户端 不需要的权限。
If the Data indication passes the above checks, the client delivers the data octets inside the DATA attribute to the application, along with an indication that they were received from the peer whose transport address is given by the XOR-PEER-ADDRESS attribute.
如果 data indication 通过上述检测,客户端把 属性 data 的数据发给应用程序,地址就是收到的 data indication 中 XOR-PEER-ADDRESS 属性表示的地址。
11. Channels
Channels provide a way for the client and server to send application data using ChannelData messages, which have less overhead than Send and Data indications.
Channels 提供了一个用 ChannelData 消息在 client 和 server 之间发送应用程序数据的方法,这个方法的 head 比 send 和 data indication 少。
The ChannelData message (see Section 11.4) starts with a two-byte field that carries the channel number. The values of this field are allocated as follows:
ChannelData 消息(参考 Section 11.4)以2个字节开始携带 channel number。这个域的值如下:
0x0000 through 0x3FFF: These values can never be used for channel numbers. 0x4000 through 0x7FFF: These values are the allowed channel numbers (16,383 possible values). 0x8000 through 0xFFFF: These values are reserved for future use.
0x0000 - 0x3FFF: 不能用
0x4000 - 0x7FFF: 可以使用的 channel number(16383 个 值)
0x8000 - 0xFFFF: 保留
Because of this division, ChannelData messages can be distinguished from STUN-formatted messages (e.g., Allocate request, Send indication, etc.) by examining the first two bits of the message:
因为这种划分,通过检查消息的前2个字节可以将 ChannelData 和 STUN 格式的消息区分开来(比如,allocation,send indication 。。。)
0b00: STUN-formatted message (since the first two bits of a STUN- formatted message are always zero).
0b01: ChannelData message (since the channel number is the first field in the ChannelData message and channel numbers fall in the range 0x4000 - 0x7FFF). 0b10: Reserved 0b11: Reserved
0b00: STUN 格式消息(因为 STUN 格式消息前2个字节永远是0)
0b01: ChannelData 消息(ChannelData 消息中第一个域就是 channel number,并且 channel number 在 0x4000 - 0x7FFF 之间)
0b10: 保留
0b11: 保留
The reserved values may be used in the future to extend the range of channel numbers. Thus, an implementation MUST NOT assume that a TURN message always starts with a 0 bit.
保留值用来未来扩展 channel number。实现不能断言 TURN 消息总是以 0 bit 开始。
Channel bindings are always initiated by the client. The client can bind a channel to a peer at any time during the lifetime of the allocation. The client may bind a channel to a peer before exchanging data with it, or after exchanging data with it (using Send and Data indications) for some time, or may choose never to bind a channel to it. The client can also bind channels to some peers while not binding channels to other peers.
Channel bindings 总是由 client 发起。client 可以在 allocation 生命周期任何时间绑定一个 channel 到 peer。client 可能在交换数据之前就绑定一个 channel 到 peer(用 send 和 data indications),或者选择不绑定 channel。client 也可以绑定 channel 给某些 peer, 同时不将 channel 绑定给其他 peer。
Channel bindings are specific to an allocation, so that the use of a channel number or peer transport address in a channel binding in one allocation has no impact on their use in a different allocation. If an allocation expires, all its channel bindings expire with it.
Channel bindings 是指定给一个 allocation的,因此在一个 allocation 中的 channel binding 使用 channel number 或者 peer transport address 跟不同的 allocation 是没有影响的。如果一个 allocation 过期,这个 allocation 的所有 channel bindings 都过期。
A channel binding consists of: o a channel number; o a transport address (of the peer); and o A time-to-expiry timer. Within the context of an allocation,
一个 channel binding 包括:
channel number;
peer 的 transport address;
过期时间 timer
Within the context of an allocation, a channel binding is uniquely identified either by the channel number or by the peer's transport address. Thus, the same channel cannot be bound to two different transport addresses, nor can the same transport address be bound to two different channels.
在一个 allocation 上下文内,一个 channel binding 的唯一标识符可以是 channel number 也可以是 peer’s transport address。所以,相同的 channel 不能绑定到 2个 不同的 transport,或者相同的 transport 不能被绑定到不同的 channel。
A channel binding lasts for 10 minutes unless refreshed. Refreshing the binding (by the server receiving a ChannelBind request rebinding the channel to the same peer) resets the time-to-expiry timer back to 10 minutes.
一个 channel binding 至少需要 10 分钟刷新一次。刷新 binding(server 收到一个 ChannelBind 请求重新绑定 channel 到相同的 peer)复位过期时间为 10 分钟。
When the channel binding expires, the channel becomes unbound. Once unbound, the channel number can be bound to a different transport address, and the transport address can be bound to a different channel number. To prevent race conditions, the client MUST wait 5
minutes after the channel binding expires before attempting to bind the channel number to a different transport address or the transport address to a different channel number.
当 channel binding 过期,channel 变成未绑定状态。一旦未绑定,channel number 可以被绑定到一个不同的 transport address,这个 transport address 可以绑定到一个不同的 channel number。为了防止竞争,client 在 channel binding 过期后必须等待 5分钟,然后再绑定 channel number 给一个不同的 transport address,或者 transport address 被绑定给一个 不同的 channel number。
When binding a channel to a peer, the client SHOULD be prepared to receive ChannelData messages on the channel from the server as soon as it has sent the ChannelBind request. Over UDP, it is possible for the client to receive ChannelData messages from the server before it receives a ChannelBind success response.
当绑定一个 channel 到 peer,client 应该准备接收这个通道上的 ChannelData,由于 UDP 的原因,client 可能先收到 ChannelData 消息,后收到 ChannelBind 成功响应。
In the other direction, the client MAY elect to send ChannelData messages before receiving the ChannelBind success response. Doing so, however, runs the risk of having the ChannelData messages dropped by the server if the ChannelBind request does not succeed for some reason (e.g., packet lost if the request is sent over UDP, or the server being unable to fulfill the request). A client that wishes to be safe should either queue the data or use Send indications until the channel binding is confirmed.
在另一个方向,client 可能在收到 ChannelBind 成功响应之前选择发送 ChannelData。然后这样做 ChannelData 可能被 server 丢弃,这种情况发生在,如果 ChannelBind 因为某些原因没有成功(比如,UDP 丢包,或者 server 无法处理这个请求)。一个希望安全的 client 应该排队数据或者使用 send indications 直到 channel binding 被确认。
11.2. Receiving a ChannelBind Request
When the server receives a ChannelBind request, it processes as per Section 4 plus the specific rules mentioned here. The server checks the following:
当服务器收到 ChannelBind 请求,按照 secion4 加上这里的规则处理。服务器检查下面的内容。
o The request contains both a CHANNEL-NUMBER and an XOR-PEER-ADDRESS attribute;
请求需要包含 CHANNEL-NUMBER 和 XOR-PEER-ADDRESS 属性。
o The channel number is in the range 0x4000 through 0x7FFE (inclusive); o The channel number is not currently bound to a different transport address (same transport address is OK); o The transport address is not currently bound to a different channel number.
channel number 范围 [0x4000 - 0x7FFE];
channel number 不能绑定到不同的地址(相同的地址可以)
地址当前不能绑定到其他的 channel number
If any of these tests fail, the server replies with a 400 (Bad Request) error. The server MAY impose restrictions on the IP address and port values allowed in the XOR-PEER-ADDRESS attribute -- if a value is not allowed, the server rejects the request with a 403 (Forbidden) error. If the request is valid, but the server is unable to fulfill the request due to some capacity limit or similar, the server replies with a 508 (Insufficient Capacity) error. Otherwise, the server replies with a ChannelBind success response. There are no required attributes in a successful ChannelBind response.
如果这些测试失败,服务器返回一个 400 的错误。
服务器可能强制管理 XOR-PEER-ADDRESS 属性中的 IP 地址和端口 -- 如果 IP地址和端口不被允许,服务器拒绝并产生以恶 403 错误。
如果请求合法,但是服务器没有能力处理,服务器返回一个 508(Insufficient Capacity)错误。
否则,服务器返回 ChannelBind 成功回复。成功的 ChannelBind 回复没有强制的属性。
If the server can satisfy the request, then the server creates or refreshes the channel binding using the channel number in the CHANNEL-NUMBER attribute and the transport address in the XOR-PEER- ADDRESS attribute. The server also installs or refreshes a permission for the IP address in the XOR-PEER-ADDRESS attribute as described in Section 8.
如果服务器满足请求,服务器创建或者刷新 channel binding 中的 channel number 和 xor-peer-address。服务器也按照 secion8 中描述的,创建或者刷新 XOR-PEER-ADDRESS 属性IP地址的权限。
NOTE: A server need not do anything special to implement idempotency of ChannelBind requests over UDP using the "stateless stack approach". Retransmitted ChannelBind requests will simply refresh the channel binding and the corresponding permission. Furthermore, the client must wait 5 minutes before binding a previously bound channel number or peer address to a different channel, eliminating the possibility that the transaction would initially fail but succeed on a retransmission.
注意:服务器不需要做任何事情就可以用 sateless stack approach 方式 通过UDP处理 channelbind 多次请求(应该是这个意思)。重复的 ChannelBind 请求应该简单刷新 channel binding 和 相应的权限。
此外,客户端必须等5分钟之后才能绑定上一个绑定的 channel number 或者 绑定对端地址到一个不同的 channel,这样消除了刚开始失败但是重传又成功的可能性。
11.4. The ChannelData Message
The ChannelData message is used to carry application data between the client and the server. It has the following format: 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Channel Number | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | / Application Data / / / | | | +-------------------------------+ | | +-------------------------------+ The Channel Number field specifies the number of the channel on which the data is traveling, and thus the address of the peer that is sending or is to receive the data. The Length field specifies the length in bytes of the application data field (i.e., it does not include the size of the ChannelData header). Note that 0 is a valid length. The Application Data field carries the data the client is trying to send to the peer, or that the peer is sending to the client.
ChannelData message 用来在 客户端 和 服务器 转发应用程序数据。它的格式如下:
Channel Number 域指定了数据在那个通道上传输,所以 对端地址 是 发送或者 接受数据。
长度域指定了应用程序数据域的长度,单位是字节,(它不包括 ChannelData 的头)。注意,0也是合法的长度。
应用程序数据域装载的数据是 client 发送到 peer,或者 peer 发送到 client。
11.6 Receiving a ChannelData Message
The receiver of the ChannelData message uses the first two bits to distinguish it from STUN-formatted messages, as described above. If the message uses a value in the reserved range (0x8000 through 0xFFFF), then the message is silently discarded.
ChannelData 的接收者使用前2个bit区分其他的 stun 消息。如果消息的值在保留的范围(0x8000 - 0xffff),消息应该被丢弃
If the ChannelData message is received in a UDP datagram, and if the UDP datagram is too short to contain the claimed length of the ChannelData message (i.e., the UDP header length field value is less than the ChannelData header length field value + 4 + 8), then the message is silently discarded.
如果 ChannelData 消息是在 UDP 数据包中收到的,并且如果 UDP 报文太短不能包含 ChannelData 消息的长度(比如,UDP 头长度域的值小于 ChannelData 头长度域 +4 +8),消息应该被丢弃。
If the ChannelData message is received over TCP or over TLS-over-TCP, then the actual length of the ChannelData message is as described in Section 11.5. If the ChannelData message is received on a channel that is not bound to any peer, then the message is silently discarded.
跟 TCP 相关,不用了解。
On the client, it is RECOMMENDED that the client discard the ChannelData message if the client believes there is no active permission towards the peer. On the server, the receipt of a ChannelData message MUST NOT refresh either the channel binding or the permission towards the peer. On the server, if no errors are detected, the server relays the application data to the peer by forming a UDP datagram as follows:
在 client 这一端,如果 client 相信没有转发到 peer 的权限,推荐 client 丢弃 ChannelData。在 服务器这一端,收到 ChannelData 消息一定不能刷新 channel binding 或者 转发到 peer 的权限。
o the source transport address is the relayed transport address of the allocation, where the allocation is determined by the 5-tuple on which the ChannelData message arrived; o the destination transport address is the transport address to which the channel is bound; o the data following the UDP header is the contents of the data field of the ChannelData message.
源传输地址是 allocation 的 relay 地址,具体是哪一个 allocation 要看 ChannelData 到了哪一个 allocation 上
目的传输地址是 绑定的 channel 对应的地址
UDP 头后面的数据就是 ChannelData 的数据域。
The resulting UDP datagram is then sent to the peer. Note that if the Length field in the ChannelData message is 0, then there will be no data in the UDP datagram, but the UDP datagram is still formed and sent.
生成的 UDP 数据随后被发送到 peer。注意如果 ChannelData 消息的长度域是 0, 就表示没有数据,但是 UDP 报文仍然可以生成和发送。
14.4. DATA
The DATA attribute is present in all Send and Data indications. The value portion of this attribute is variable length and consists of the application data (that is, the data that would immediately follow the UDP header if the data was been sent directly between the client and the peer). If the length of this attribute is not a multiple of 4, then padding must be added after this attribute.
data 属性在 send indaication 和 data indication 中。属性值长度是可变得,并且由应用程序数据组成(应用程序数据就是:如果 两端 是直接发送数据,数据就是跟随在 UDP 头后边的数据)(应该就是 stun 命令,自己的理解)。如果属性的长度不是 4 的倍数,这个属性应该补齐到 4 的倍数。