aboutsummaryrefslogtreecommitdiff
path: root/doc/broker-spec.txt
blob: 3f9ce7ac12e56efb87747dfcc0db349bf6953502 (plain)
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
                            Snowflake broker protocol

0. Scope and Preliminaries

The Snowflake broker is used to hand out Snowflake proxies to clients using the Snowflake pluggable transport. There are some similarities to the function of the broker and how BridgeDB hands out Tor bridges.

This document specifies how the Snowflake broker interacts with other parts of the Tor ecosystem, starting with the metrics CollecTor module and to be expanded upon later.

1. Metrics Reporting (version 1.1)

Metrics data from the Snowflake broker can be retrieved by sending an HTTP GET request to https://[Snowflake broker URL]/metrics and consists of the following items:

    "snowflake-stats-end" YYYY-MM-DD HH:MM:SS (NSEC s) NL
        [At start, exactly once.]

        YYYY-MM-DD HH:MM:SS defines the end of the included measurement
        interval of length NSEC seconds (86400 seconds by default).

    "snowflake-ips" [CC=NUM,CC=NUM,...,CC=NUM] NL
        [At most once.]

        List of mappings from two-letter country codes to the number of
        unique IP addresses of Snowflake proxies that have polled. Each
        country code only appears once.

    "snowflake-ips-total" NUM NL
        [At most once.]

        A count of the total number of unique IP addresses of Snowflake
        proxies that have polled.

    "snowflake-ips-standalone" NUM NL
        [At most once.]

        A count of the total number of unique IP addresses of snowflake
        proxies of type "standalone" that have polled.

    "snowflake-ips-badge" NUM NL
        [At most once.]

        A count of the total number of unique IP addresses of snowflake
        proxies of type "badge" that have polled.

    "snowflake-ips-webext" NUM NL
        [At most once.]

        A count of the total number of unique IP addresses of snowflake
        proxies of type "webext" that have polled.

    "snowflake-idle-count" NUM NL
        [At most once.]

        A count of the number of times a proxy has polled but received
        no client offer, rounded up to the nearest multiple of 8.

    "client-denied-count" NUM NL
        [At most once.]

        A count of the number of times a client has requested a proxy
        from the broker but no proxies were available, rounded up to
        the nearest multiple of 8.

    "client-restricted-denied-count" NUM NL
        [At most once.]

        A count of the number of times a client with a restricted or
        unknown NAT type has requested a proxy from the broker but no
        proxies were available, rounded up to the nearest multiple of 8.

    "client-unrestricted-denied-count" NUM NL
        [At most once.]

        A count of the number of times a client with an unrestricted NAT
        type has requested a proxy from the broker but no proxies were
        available, rounded up to the nearest multiple of 8.

    "client-snowflake-match-count" NUM NL
        [At most once.]

        A count of the number of times a client successfully received a
        proxy from the broker, rounded up to the nearest multiple of 8.

    "client-http-count" NUM NL
        [At most once.]

        A count of the number of times a client has requested a proxy using
        the HTTP rendezvous method from the broker, rounded up to the nearest 
        multiple of 8.
    
    "client-http-ips" [CC=NUM,CC=NUM,...,CC=NUM] NL
        [At most once.]

        List of mappings from two-letter country codes to the number of
        times a client has requested a proxy using the HTTP rendezvous method, 
        rounded up to the nearest multiple of 8.  Each country code only appears 
        once.

    "client-ampcache-count" NUM NL
        [At most once.]

        A count of the number of times a client has requested a proxy using
        the ampcache rendezvous method from the broker, rounded up to the 
        nearest multiple of 8.
    
    "client-ampcache-ips" [CC=NUM,CC=NUM,...,CC=NUM] NL
        [At most once.]

        List of mappings from two-letter country codes to the number of
        times a client has requested a proxy using the ampcache rendezvous 
        method, rounded up to the nearest multiple of 8.  Each country code only 
        appears once.

    "client-sqs-count" NUM NL
        [At most once.]

        A count of the number of times a client has requested a proxy using
        the sqs rendezvous method from the broker, rounded up to the nearest 
        multiple of 8.

    "client-sqs-ips" [CC=NUM,CC=NUM,...,CC=NUM] NL
        [At most once.]

        List of mappings from two-letter country codes to the number of
        times a client has requested a proxy using the sqs rendezvous method, 
        rounded up to the nearest multiple of 8.  Each country code only appears 
        once.

    "snowflake-ips-nat-restricted" NUM NL
        [At most once.]

        A count of the total number of unique IP addresses of snowflake
        proxies that have a restricted NAT type.

    "snowflake-ips-nat-unrestricted" NUM NL
        [At most once.]

        A count of the total number of unique IP addresses of snowflake
        proxies that have an unrestricted NAT type.

    "snowflake-ips-nat-unknown" NUM NL
        [At most once.]

        A count of the total number of unique IP addresses of snowflake
        proxies that have an unknown NAT type.

   "snowflake-proxy-poll-with-relay-url-count" NUM NL
        [At most once.]

        A count of snowflake proxy polls with relay url extension present.
        This means this proxy understands relay url, and is sending its
        allowed prefix.
   "snowflake-proxy-poll-without-relay-url-count" NUM NL
        [At most once.]

        A count of snowflake proxy polls with relay url extension absent.
        This means this proxy is not yet updated.
   "snowflake-proxy-rejected-for-relay-url-count" NUM NL
        [At most once.]

        A count of snowflake proxy polls with relay url extension rejected
        based on broker's relay url extension policy.
        This means an incompatible allowed relay pattern is included in the
        proxy poll message.
2. Broker messaging specification and endpoints

The broker facilitates the connection of snowflake clients and snowflake proxies
through the exchange of WebRTC SDP information with its endpoints.

2.1. Client interactions with the broker

The broker offers multiple ways for clients to exchange registration
messages.

2.1.1. HTTPS POST

Clients interact with the broker by making a POST request to `/client` with the
offer SDP in the request body:
```
POST /client HTTP

[offer SDP]
```
If the broker is behind a domain-fronted connection, this request is accompanied
with the necessary HOST information.

If the client is matched up with a proxy, they receive a 200 OK response with
the proxy's answer SDP in the request body:
```
HTTP 200 OK

[answer SDP]
```

If no proxies were available, they receive a 503 status code:
```
HTTP 503 Service Unavailable
```

2.1.2. AMP

The broker's /amp/client endpoint receives client poll messages encoded
into the URL path, and sends client poll responses encoded as HTML that
conforms to the requirements of AMP (Accelerated Mobile Pages). This
endpoint is intended to be accessed through an AMP cache, using the
-ampcache option of snowflake-client.

The client encodes its poll message into a GET request as follows:
```
GET /amp/client/0[0 or more bytes]/[base64 of client poll message]
```
The components of the path are as follows:
* "/amp/client/", the root of the endpoint.
* "0", a format version number, which controls the interpretation of the
  rest of the path. Only the first byte matters as a version indicator
  (not the whole first path component).
* Any number of slash or non-slash bytes. These may be used as padding
  or to prevent cache collisions in the AMP cache.
* A final slash.
* base64 encoding of the client poll message, using the URL-safe
  alphabet (which does not include slash).

The broker returns a client poll response message in the HTTP response.
The message is encoded using AMP armor, an AMP-compatible HTML encoding.
The data stream is notionally a "0" byte (a format version indicator)
followed by the base64 encoding of the message (using the standard
alphabet, with "=" padding). This stream is broken into
whitespace-separated chunks, which are then bundled into HTML <pre>
elements. The <pre> elements are then surrounded by AMP boilerplate. To
decode, search the HTML for <pre> elements, concatenate their contents
and join on whitespace, discard the "0" prefix, and base64 decode.

2.2 Proxy interactions with the broker

Proxies poll the broker with a proxy poll request to `/proxy`:

```
POST /proxy HTTP

{
  Sid: [generated session id of proxy],
  Version: 1.3,
  Type: ["badge"|"webext"|"standalone"|"mobile"],
  NAT: ["unknown"|"restricted"|"unrestricted"],
  Clients: [number of current clients, rounded down to multiples of 8],
  AcceptedRelayPattern: [a pattern representing accepted set of relay domains]
}
```

If the request is well-formed, they receive a 200 OK response.

If a client is matched:
```
HTTP 200 OK

{
  Status: "client match",
  {
    type: offer,
    sdp: [WebRTC SDP]
  },
  RelayURL: [the WebSocket URL proxy should connect to relay Snowflake traffic]
}
```

If a client is not matched:
```
HTTP 200 OK

{
    Status: "no match"
}
```

If the request is malformed:
```
HTTP 400 BadRequest
```

If they are matched with a client, they provide their SDP answer with a POST
request to `/answer`:
```
POST /answer HTTP

{
  Sid: [generated session id of proxy],
  Version: 1.3,
  Answer:
  {
    type: answer,
    sdp: [WebRTC SDP]
  }
}
```

If the request is well-formed, they receive a 200 OK response.

If the client retrieved the answer:
```
HTTP 200 OK

{
  Status: "success"
}
```

If the client left:
```
HTTP 200 OK

{
  Status: "client gone"
}

3) If the request is malformed:
HTTP 400 BadRequest
```