-
Notifications
You must be signed in to change notification settings - Fork 12
/
draft-uberti-behave-turn-rest.xml
executable file
·246 lines (244 loc) · 15.1 KB
/
draft-uberti-behave-turn-rest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<!DOCTYPE rfc SYSTEM 'rfc2629.dtd'>
<?rfc toc='yes' ?>
<?rfc symrefs='yes' ?>
<?rfc sortrefs='yes'?>
<?rfc iprnotified='no' ?>
<?rfc strict='yes' ?>
<?rfc compact='yes' ?>
<rfc category='std' docName='draft-uberti-behave-turn-rest-00' ipr="trust200902">
<front>
<title abbrev='TURN Server REST API'>
A REST API For Access To TURN Services
</title>
<author initials='J.' surname='Uberti' fullname='Justin Uberti'>
<organization abbrev='Google'>Google</organization>
<address>
<postal>
<street>747 6th St S</street>
<city>Kirkland</city>
<region>WA</region>
<code>98033</code>
<country>USA</country>
</postal>
<email>[email protected]</email>
</address>
</author>
<date />
<abstract>
<t>
This document describes a proposed standard REST API for obtaining access to TURN services via ephemeral (i.e. time-limited) credentials. These credentials are vended by a web service over HTTP, and then supplied to and checked by a TURN server using the standard TURN protocol. The usage of ephemeral credentials ensures that access to the TURN server can be controlled even if the credentials can be discovered by the user, as is the case in WebRTC where TURN credentials must be specified in Javascript.
</t>
</abstract>
</front>
<middle>
<section title='Introduction'>
<section title='Problem Statement'>
<t>
TURN <xref target="RFC5766"/> is a protocol that is often used to improve the connectivity of P2P applications. By providing a cloud-based relay service, TURN ensures that a connection can be established even when one or both sides is incapable of a direct P2P connection. However, as a relay service, it imposes a nontrivial cost on the service provider. Therefore, access to a TURN service is almost always access-controlled.
</t>
<t>
TURN provides a mechanism to control access via <xref target="RFC5389"/> long-term credentials that are provided to the server as part of the TURN protocol. However, use of traditional login usernames and passwords for these credentials poses several problems, many of which are outlined in <xref target="I-D.reddy-behave-turn-auth"/>, Section 4. The list below summarizes the major issues:
<list style="symbols">
<t>The TURN password must be kept secret, which is difficult or impossible for web applications.</t>
<t>The TURN password is vulnerable to offline dictionary attacks against MESSAGE-INTEGRITY.</t>
<t>The TURN server must consult a password database to verify MESSAGE-INTEGRITY, increasing the complexity of the TURN server.</t>
<t>The TURN username value is passed in the clear, and can be used to determine who is talking to whom.</t>
</list>
</t>
</section>
<section title='Proposed Solution'>
<t>
To address these problems, this document proposes an API that can be used to retrieve ephemeral TURN credentials from a web service. These credentials can then be used as long-term credentials with a standard TURN server, requring only a custom authentication module. For simplicity, the design has been kept intentionally stateless; the only interaction needed between the web service and the TURN service is to share a secret key. Because of this, the authentication check can be done entirely on the TURN server without needing to consult any external service.
</t>
<t>This design directly addresses the issues mentioned above:
<list style="symbols">
<t>The TURN password is ephemeral (i.e. time-limited), so even if it is discovered, its usefulness is limited.</t>
<t>The TURN password is machine-generated with high entropy, making it resistant to dictionary attacks.</t>
<t>The TURN server can validate the password trivially, using a pre-configured secret key.</t>
<t>The TURN username value does not need to contain any externally-identifying information.</t>
</list>
</t>
<t>
Note that while <xref target="RFC5389"/> also supports the concept of short-term credentials, they are not useful for TURN. Since a nonce is not used with short-term credentials, they are completely vulnerable to replay attacks.
</t>
</section>
</section>
<section title='HTTP Interactions'>
<t>
To retrieve a new set of credentials, the client makes a HTTP GET request, specifying TURN as the service to allocate credentials for, and optionally specifying a user id parameter. The purpose of the user id parameter is to simplify debugging on the TURN server, as well as provide the ability to control the number of credentials handed out for a specific user, if desired. The TURN credentials and their lifetime are returned as JSON, along with URIs that indicate how to connect to the server using the TURN protocol.
</t>
<t>
To avoid the need for state passing between the web service and TURN server, the returned credentials consist of a TURN username that encodes all the necessary state (expiry time and application user id), and a TURN password that is a digest of this state, signed with the shared secret key.
</t>
<t>
Since the returned credentials are ephemeral, they will eventually expire. This does not affect existing TURN allocations, as they are tied to a specific 5-tuple, but requests to allocate new TURN ports will fail after the expiry time. This is significant in the case of an ICE restart, where the client will need to allocate a new set of candidates, including TURN candidates. To get a new set of ephemeral credentials, the client can simply re-issue the original HTTP request with the same parameters, which will return the new credentials in its JSON response.
</t>
<t>
To prevent unauthorized use, the HTTP requests can be ACLed by various means, e.g. IP address (if coming from a server), Origin header, User-Agent header, login cookie, API key, etc.
</t>
<section title='Request'>
<t>
The request includes the following parameters, specified in the URL:
<list style="symbols">
<t>service: specifies the desired service (turn)</t>
<t>username: an optional user id to be associated with the credentials</t>
<t>key: if an API key is used for authentication, the API key </t>
</list>
</t>
<t>
Example:
<figure>
<artwork>
GET /?service=turn&username=mbzrxpgjys
</artwork>
</figure>
</t>
</section>
<section title="Response">
<t>
The response is returned with content-type "application/json", and consists of a JSON object with the following parameters:
<list style="symbols">
<t>username: the TURN username to use, which is a colon-delimited combination of the expiration timestamp and the username parameter from the request (if specified). The timestamp is intended to be opaque to the web application, so its format is arbitrary, but for simplicity, use of UNIX timestamps is recommended.</t>
<t>password: the TURN password to use; this value is computed from the a secret key shared with the TURN server and the returned username value, by performing base64(hmac(secret key, returned username)). HMAC-SHA1 is one HMAC algorithm that can be used, but any algorithm that incorporates a shared secret is acceptable, as long as both the web server and TURN server use the same algorithm and secret.</t>
<t>ttl: the duration for which the username and password are valid, in seconds. A value of one day (86400 seconds) is recommended.</t>
<t>uris: an array of TURN URIs, in the form specified in <xref target="I-D.petithuguenin-behave-turn-uris"/>. This is used to indicate the different addresses and/or protocols that can be used to reach the TURN server. These URIs SHOULD specify a hostname, IPv4, or IPv6 address for the TURN server, as well as the port and transport to use; this avoids the need for a DNS SRV or S-NAPTR lookup as specified in <xref target="RFC5928"/>.</t>
</list>
</t>
<t>
Example:
<figure>
<artwork>
{
"username" : "12334939:mbzrxpgjys",
"password" : "adfsaflsjfldssia",
"ttl" : 86400,
"uris" : [
"turn:1.2.3.4:9991?transport=udp",
"turn:1.2.3.4:9992?transport=tcp",
"turns:1.2.3.4:443?transport=tcp"
]
}
</artwork>
</figure>
</t>
</section>
</section>
<section title="WebRTC Interactions">
<t>
The returned JSON is parsed into an RTCIceServer object, and supplied as part of the RTCConfiguration object that is used when creating a RTCPeerConnection.
</t>
<t>
Example:
<figure>
<artwork>
var iceServer = {
"username": response.username,
"credential": response.password,
"uris": response.uris
};
var config = {"iceServers": [iceServer]};
var pc = new RTCPeerConnection(config);
</artwork>
</figure>
</t>
<t>
When the credentials are updated (e.g. because they are about to expire), a new RTCConfiguration with the updated credentials can be supplied to the existing RTCPeerConnection via the updateIce method. This update must not affect existing TURN allocations, because TURN requires that the username stay constant for an allocation, but the new credentials will be used for any new allocations.
</t>
<t>
[TODO: make sure this behavior is specified in the W3C API spec]
</t>
</section>
<section title="TURN Interactions">
<section title="Client">
<t>
The WebRTC client will perform a standard TURN allocation sequence using the long-term credentials mechanism specified in <xref target="RFC5389"/>, Section 10.2, using the "username" value from the returned JSON for its USERNAME attribute, and the "password" value for the password input to the MESSAGE-INTEGRITY hash.
</t>
</section>
<section title="Server">
<t>The TURN server will process the request using the long-term credentials mechanism specifed in <xref target="RFC5389"/>. Note that the REALM value supplied by the server is not meaningful in this context, and can be set to any valid value.</t>
<t>
When processing ALLOCATE requests, the TURN server MUST split the USERNAME attribute into its timestamp and user id components, and verify that the timestamp, which indicates when the credentials expire, has not yet been reached. If this verification fails, it SHOULD reject the request with a 401 (Unauthorized) error.
</t>
<t>
If desired, the TURN server can optionally verify that the parsed user id value corresponds to a currently valid user of an external service (e.g. is currently logged in to the web app that is making use of TURN). This requires proprietary communication between the TURN server and external service on each ALLOCATE request, and is not necessary for typical applications. If this external verification fails, it SHOULD reject the request with a 401 (Unauthorized) error.
</t>
<t>
For non-ALLOCATE requests, the TURN server merely verifies that the USERNAME matches the USERNAME that was used in the ALLOCATE (since it must remain constant).
</t>
<t>
As in RFC 5766, the TURN server MUST verify the MESSAGE-INTEGRITY using the password associated with the supplied USERNAME. For the usage outlined in this document, the password will always be constructed using the supplied username and the shared secret as indicated in the "HTTP Interactions" section above. Because the password is derived from the USERNAME, successful verification of the MESSAGE-INTEGRITY ensures that the USERNAME (and the expiration time contained within) is trustworthy.
</t>
</section>
</section>
<section title="Illustration">
<t>
The diagram below shows the complete set of interactions between a client application, the TURN REST API, and the actual TURN server.
</t>
<figure>
<artwork>
<![CDATA[
Client Application Web Server TURN Server
-----------------------------------------------------------------
|----GET /?service=turn---->| |
|<---200 OK, JSON body------| |
| username:<username> | |
| password:<password> | |
| uris:["example.com:3478?transport=udp"] |
| | |
|----ALLOCATE Request------------------------------>|
|<---ALLOCATE Error Response------------------------|
| NONCE=<nonce> | |
| REALM="" | |
| ERROR_CODE=401 | |
|----ALLOCATE Request------------------------------>|
| USERNAME=<username> | |
| NONCE=<nonce> | |
| REALM="" | |
| MESSAGE_INTEGRITY=<hash> |
|<---ALLOCATE Response------------------------------|
]]>
</artwork>
</figure>
</section>
<section title="Implementation Notes">
<section title="Revocation">
<t>
In the system as described here, revoking specific credentials is not possible. The assumption is that TURN services are of low enough value that waiting for the timeout to expire is a valid approach for dealing with possibly-compromised credentials.
</t>
<t>
In extreme abuse cases, TURN server blacklists of timestamp+username values can be supplied by an administrator to stop abuse of specific credential sets.
</t>
</section>
<section title="Key Rotation">
<t>
As indicated in <xref target="RFC2104"/>, periodic rotation of the shared secret to protect against key compromise is RECOMMENDED. To facilitate the rollover, the TURN server SHOULD be able to validate incoming MESSAGE-INTEGRITY tokens based on at least 2 shared secrets at any time.
</t>
</section>
</section>
<section title="Security Considerations">
<t>Because the USERNAME values in a TURN ALLOCATE request are typically visible to eavesdroppers, inclusion of an externally identifying user id, such as a login name, may allow a passive attacker to determine the identities of the parties in a conversation. To prevent this problem, use of opaque user id values is recommended.</t>
<t>This mechanism assumes that the clocks of the web server and TURN server are roughly in sync. Given the expected large TTLs for the vended credentials, clock skew on the order of seconds to minutes should not cause an issue. However, if the TURN server's clock was mistakenly set to a date signficantly in the past, credentials could be accepted for far longer than their intended lifetime.</t>
</section>
<section title="IANA Considerations">
<t>None.</t>
</section>
<section title='Acknowledgements'>
<t>Harald Alvestrand, Alfred Godoy, and Philipp Hancke provided key input on the initial design. Dave Cridland, Cullen Jennings, Oleg Moskalenko, and Matthew Robertson pointed out several errors and omissions.</t>
</section>
</middle>
<back>
<references title="Normative References">
<?rfc include="reference.RFC.5766.xml"?>
<?rfc include="reference.RFC.5389.xml"?>
<?rfc include="reference.I-D.draft-petithuguenin-behave-turn-uris-03.xml"?>
</references>
<references title="Informative References">
<?rfc include="reference.I-D.draft-reddy-behave-turn-auth-02.xml"?>
<?rfc include="reference.RFC.2104.xml"?>
<?rfc include="reference.RFC.2616.xml"?>
<?rfc include="reference.RFC.5928.xml"?>
</references>
</back>
</rfc>