aboutsummaryrefslogtreecommitdiff
path: root/proposals/XXX-udp-app-support.md
blob: 386037f685549524820c0523502a209edf8d91b5 (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
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
```
Filename: XXX-udp-app-support.md
Title: Support for UDP Applications over Tor
Author: Micah Elizabeth Scott
Created: December 2023
Status: Draft
```

# Introduction

This proposal takes a fresh look at the problem of implementing support in Tor for applications which require UDP/IP communication.

This work is being done with the sponsorship and goals of the [Tor VPN Client for Android project](https://gitlab.torproject.org/groups/tpo/-/milestones/32).

We start out by defining how this proposal compares to previous work, and the specific problem space we are addressing.
This leads into an analysis that references appropriate standards and proposes some specific solutions with properties we can compare.

## History

There have been multiple attempts already within Tor to define some type of UDP support.

[Proposal 100](https://spec.torproject.org/proposals/100-tor-spec-udp.html) by Marc Liberatore in 2006 suggested a way to "add support for tunneling unreliable datagrams through tor with as few modifications to the protocol as possible." 
This proposal suggested extending the existing TLS+TCP protocol with a new DTLS+UDP link mode.
The focus of this work was on a potential way to support unreliable traffic, not necessarily on UDP itself or on UDP applications.

In proposal 100, a Tor *stream* is used for one pairing of local and remote address and port, copying the technique used by Tor for TCP. This works for some types of UDP applications, as we detail below, but for many peer-to-peer use cases it's unhelpful to allocate local ports that can only be used with a single remote peer.

Furthermore, no additional large-message fragmentation protocol is defined, so the MTU in proposal 100 is limited to what fits in a single Tor cell. This value we will see is unusably small for most applications.

It's possible these UDP protocol details would have been elaborated during design, but the proposal hit a snag elsewhere:
there was no agreement on a way to avoid facilitating new attacks against anonymity.

In 2018, Nick Mathewson and Mike Perry wrote a 
[summary of the side-channel issues with unreliable transports for Tor](https://research.torproject.org/techreports/side-channel-analysis-2018-11-27.pdf).

TODO: Look closer at this, some of the attacks described might overlap with non-datagram-transport ways of encapsulating UDP. (i.e. a malicious exit may always cause drops/injections regardless of what the rest of the anonymity network does.)

[Proposal 339](https://spec.torproject.org/proposals/339-udp-over-tor.html) by Nick Mathewson in 2020 introduced a simpler UDP encapsulation design which had similar stream mapping properties as in proposal 100, but with the unreliable transport omitted. Datagrams are tunneled over a new type of Tor stream using a new type of Tor message.
As a prerequisite, it depends on [proposal 319](https://spec.torproject.org/proposals/319-wide-everything.html) to support messages that may be larger than a cell, extending the MTU to support arbitrarily large UDP datagrams.

In proposal 339 the property of binding a stream both to a local port and to a remote peer is described in UNIX-style terminology as a *connected socket*. We dive deeper into this idea below and supply an alternate formulation based on [RFC4787](https://www.rfc-editor.org/rfc/rfc4787), *NAT behavior requirements for UDP*.
The single-peer *connected socket* behavior would be referred to as an *endpoint-dependent mapping* in RFC4787.
This type works fine for client/server apps but precludes the use of NAT traversal for peer-to-peer transfer.

## Scope

This proposal aims to allow Tor applications and Tor-based VPNs to provide compatibility with applications that require UDP/IP communications.

We don't have a specific list of applications that must be supported, but we are currently aiming for broad support of popular applications while still respecting and referencing all applicable Internet standards documents.

Changes to the structure of the Tor network are out of scope, as are most performance optimizations. We expect to rely on common optimizations to the performance of Tor circuits, rather than looking to make specific changes that optimize for unreliable datagram transmission.

We will discuss the design implications of UDP on onion services below.
It's worth planning for this as a way to evaluate the design space, but in practice we are not aiming for UDP to onion services yet.
This will require changes to most applications that want to use it, as it implies that any media negotiations will need to understand onion addressing in addition to IPv4 and IPv6.

We do not rigidly define the subset of UDP traffic that will be allowed.
There are several options discussed below using the RFC4787 framework.

We require support for DNS clients. Tor currently only supports a limited subset of DNS queries, and it's desirable to support more. This will be analyzed in detail as an application below. DNS is one of very few applications that still rely on fragmented UDP datagrams, though this may not be relevant for us since only servers typically need to control the production of fragments.

We require support for voice/video telecommunications apps. Even without an underlying transport that supports unreliable datagrams, we expect a tunnel to provide a usable level of compatibility. This design space is very similar to the TURN ([RFC8656](https://www.rfc-editor.org/rfc/rfc8656)) specification, already used very widely for compatibility with networks that filter UDP. See the analysis of specific applications below.

We require support for peer-to-peer UDP transfer without additional relaying, in apps that use ICE ([RFC8445](https://www.rfc-editor.org/rfc/rfc8445)) or similar connection establishment techniques.
Video calls between two Tor users should transit directly between two exit nodes.
This requires that allocated UDP ports can each communicate with multiple peers:
*endpoint-independent mapping* as described by RFC4787.

We do not plan to support applications which accept arbitrary incoming datagrams, for example a DNS server hosted via Tor.
RFC4787 calls this *endpoint-independent filtering*.
It's unnecessary for running peer-to-peer apps, and it facilitates an extremely easy traffic injection attack.

# UDP Traffic Models

To better specify the role of a UDP extension for Tor, we will look at a few frameworks for describing UDP applications.

## User Datagram Protocol (RFC768)

The "User Interface" suggested by [RFC768](https://www.rfc-editor.org/rfc/rfc768) for the protocol is a rough sketch, suggesting that applications have some way to allocate a local port for receiving datagrams and to transmit datagrams with arbitrary headers.

Despite UDP's simplicity as an application of IP, we do need to be aware of IP features that are typically hidden by TCP's abstraction.

UDP applications typically try to obtain an awareness of the path MTU, using some type of path MTU discovery (PMTUD) algorithm.
On IPv4, this requires sending packets with the "Don't Fragment" flag set, and measuring when those packets are lost or when ICMP "Fragmentation Needed" replies are seen.

Note that many applications have their own requirements for path MTU. For example, QUIC and common implementations of WebRTC require an MTU no smaller than 1200 bytes, but they can discover larger MTUs when available.

## Socket Layer

In practice the straightforward "User Interface" from RFC768, capable of arbitrary local address, is only available to privileged users.

BSD-style sockets support UDP via `SOCK_DGRAM`.
UDP is a stateless protocol, but sockets do have state.
Each socket is bound, either explicitly with `bind()` or automatically, to a source IP and port.

At the API level, a socket is said to be *connected* to a remote address:port if that address is the default destination.
A *connected* socket will also filter out incoming packets with source addresses different from this default destination.
A socket is considered *unconnected* if `connect()` has not been called.
These sockets have no default destination, and they accept datagrams from any source.

There does not need to be any particular mapping between the lifetime of these application sockets and any higher-level "connection" the application establishes.
It's better to think of one socket as one allocated source port.
A typical application may allocate only a single port (one socket) for talking to many peers.
Every datagram sent or received on the socket may have a different peer address.

## Network Address Translation (NAT)

Much of the real-world complexity in UDP applications comes from their strategies to detect and overcome the effects of NAT.

Many RFCs have been written on NAT behavior and NAT traversal strategies.
[RFC4787](https://www.rfc-editor.org/rfc/rfc4787.html) and later [RFC7857](https://www.rfc-editor.org/rfc/rfc7857.html) offer best practices for implementing NAT. These are sometimes referred to as the [BEHAVE-WG](https://datatracker.ietf.org/wg/behave/about/) recommendations, based on the "Behavior Engineering for Hindrance Avoidance" working group behind them.
Carrier-grade NAT requirements are addressed by [RFC6888](https://www.rfc-editor.org/rfc/rfc6888.html).

[RFC8445](https://www.rfc-editor.org/rfc/rfc8445.html) describes the Interactive Connectivity Establishment (ICE) protocol, which has become a common and recommended application-level technique for building peer-to-peer applications that work through NAT.

There are multiple fundamental technical issues that NAT presents:

1. NAT must be stateful in order to route replies back to the correct source.
   This directly conflicts with the stateless nature of UDP itself.
   The NAT's mapping lifetime, determined by a timer, will not necessarily match the lifetime of the application-level connection.
   This necessitates keep-alive packets in some protocols.
   Protocols that allow their binding to expire may be open to a NAT rebinding attack, when a different party acquires access to the NAT's port allocation.
2. Applications no longer know an address they can be reached at without outside help.
   Chosen port numbers may or may not be used by the NAT.
   The effective IP address and port are not knowable without observing from an outside peer.
3. Filtering and mapping approaches both vary, and it's not generally possible to establish a connection without testing several alternatives and choosing the one that works.
   This is the reason ICE exists, but it's also a possible anonymity hazard.

We can use the constraints of NAT both to understand application behavior and as an opportunity to model Tor's behavior as a type of NAT.
In fact, Tor's many exit nodes already share similarity with some types of carrier-grade NAT.
Applications will need to assume very little about the IP address their outbound UDP originates on, and we can use that to our advantage in implementing UDP for Tor.

This body of IETF work is invaluable for understanding the scope of the problem and for defining common terminology.
We must take inspiration from these documents while also keeping in mind that the analogy between Tor and a NAT is imperfect.
For example, in analyzing Tor as a type of carrier-grade NAT, we may consider the "pooling behavior" defined in RFC4787: the choice of which external addresses map to an internal address.
Tor by necessity must carefully limit how predictable these mappings can ever be, to preserve its anonymity properties.
A literal application of RFC6888 would find trouble in REQ-2 and REQ-9, as well as the various per-subscriber limiting requirements.

### Mapping and Filtering Behaviors

RFC4787 defines a framework for understanding the behavior of NAT by analyzing both its "mapping" and "filtering" behavior separately.
Mappings are the NAT's unit of state tracking.
Filters are layered on top of mappings, potentially rejecting incoming datagrams that don't match an already-expected address.
Both RFC4787 and the demands of peer to peer applications make a good case for always using an **Endpoint-Independent Mapping**.

Choice of filtering strategy is left open by the BEHAVE-WG recommendations.
RFC4787 defines three types with different properties, and does not make one single recommendation for all circumstances.
We can gain some additional insight by looking at requirements that come from outside RFC4787.

- **Endpoint-Independent Filtering** allows incoming datagrams from any peer once a mapping has been established.
  
  RFC4787 recommends this approach, with the concession that it may not be ideal for all security requirements.
  
  In the context of Tor, we can likely rule out this technique entirely.
  It makes traffic injection attacks possible from any source address, provided you can guess the UDP port number used at an exit.
  It also makes possible clearnet hosting of UDP servers using an exit node's IP, which may have undesirable abuse properties.
  
  It precludes "Port overlapping" behavior as defined in RFC7857 section 3, which may be necessary in order to achieve sufficient utilization of local port numbers on exit nodes.
  
  It is still common for present-day applications to *prefer* endpoint-independent filtering, as it allows incoming connections from peers which cannot use STUN or a similar address fixing protocol.
  Choosing endpoint-independent filtering would have *some* compatibility benefit, but among modern protocols which use ICE and STUN there would be no improvement.
  The cost, on the other hand, would be an uncomfortably low-cost traffic injection attack and additional risks toward exit nodes.

- **Address-Dependent Filtering**

  This is a permitted alternative according to RFC4787, in which incoming datagrams are allowed from only IP addresses we have previously sent to, but any port on that IP may be the sender.

  The intended benefits of this approach would be:
  
  - To support a class of applications that rely on, for a single local port, multiple remote ports achieving filter acceptance status when only one of those ports has been sent a datagram.
    We are currently lacking examples of applications in this category.
    Any application using ICE will be outside this category, as each port would have its own connectivity check datagrams exchanged in each direction.

  - To support peers using firewalls that are not compliant with RFC4787. This claim from the spec:
  
    ```
      However, if NAT-A uses Endpoint-Independent Filtering
      or Address-Dependent Filtering, ICE will ultimately find
      connectivity without requiring a UDP relay.
    ```

    TODO: Is this actually true? I haven't worked out how port-independent filtering is what makes this succeed.

  One security hazard of address-dependent and non-port-dependent filtering, identified in RFC4787, is that a peer on a NAT effectively negates the security benefits of this host filtering.
  In fact, this should raise additional red flags as applied to either Tor or carrier grade NAT.
  If we are intending to support peer to peer applications, it should be commonplace to establish UDP flows between two tor exit nodes.
  When this takes place, non-port-dependent filtering would then allow anyone on Tor to connect via those same nodes and perform traffic injection.
  The resulting security properties really become uncomfortably similar to endpoint-independent filtering.

- **Address and Port-Dependent Filtering**

  This is the strictest variety of filtering, and it is an allowed alternative under RFC4787.
  It provides opportunities for increased security and opportunities for reduced compatibility, both of which in practice may depend on other factors.

  For every application we've analyzed so far, port-dependent filtering is not a problem.
  Usage of ICE will open all required filters during the connectivity check phase.

  This is the only type of filtering that provides any barrier at all between cross-circuit traffic injection when the communicating parties are known.

RFC4787 recommends that filtering style be configurable.
We would like to implement that advice, but we are also looking for opportunities to make design decisions that give us the best network and end-user behaviors.

## Common Protocols

Applications that want to use UDP are increasingly making use of higher-level protocols to avoid creating bespoke solutions for problems like NAT traversal, connection establishment, and reliable delivery.

We will analyze how these protocols affect Tor's UDP traffic requirements.

### QUIC

RFC9000 defines QUIC, a multiplexed secure point-to-point protocol which supports reliable and unreliable delivery. The most common use is as an optional HTTP replacement, especially among Google services.

QUIC does not normally try to traverse NAT; as an HTTP replacement, the server is expected to have a routable address.

TODO: Look closer at the NAT rebinding attack described in the RFC, check how applicable that is for us.

When QUIC is used as an optional upgrade path, we must compare any proposed UDP support against the baseline of a non-upgraded original connection.
In these cases we are not looking for any specific compatibility enhancement, simply an avoidance of regression.

In cases where QUIC is used as a primary protocol without TCP fallback, we expect UDP support to be vital. These applications are currently niche but we expect they may rise in popularity.

### WebRTC

WebRTC is a large collection of protocols tuned to work together for media transport and NAT traversal.
It is increasingly common, both for browser-based telephony and for peer to peer data transfer.
Non-browser-based apps often implement WebRTC or have components in common with WebRTC.

See RFC7734, RFC8825, RFC8445, RFC5389, others.

TODO: Organize and expand references here.

Of particular importance to us, WebRTC uses the Interactive Connection Establishment (ICE, RFC8445, RFC8838) protocol to establish a bidirectional channel between endpoints that may or may not be behind a NAT with unknown configuration.

TODO: More about the specifics of how ICE effects us. More about privacy concerns.

## Common Applications

With applications exhibiting such a wide variety of behaviors, how do we know what to expect from a good implementation?
How do we know which compatibility decisions will be most important to users?
For this it's helpful to look at specific application behaviors.
This is a best-effort analysis conducted at a point in time.
It's not meant to be a definitive reference, think of it as a site survey taken before we plan a building.

In alphabetical order:

| Application            | Type           | Protocol features                 | Current behavior   | Expected outcome                                   |
| ---------------------- | -------------- | --------------------------------- | ------------------ | -------------------------------------------------- |
| BitTorrent             | File sharing   | Many peers per local port         | Fails without UDP  | Works, new source of nuisance traffic              |
| BigBlueButton          | Telecom        | WebRTC, TURN, TURN-over-TLS       | Works              | Slight latency improvement                         |
| Discord                | Telecom        | Proprietary, client/server        | Fails without UDP  | Starts working                                     |
| DNS                    | Infrastructure | Might want IP fragmentation       | Limited            | Full DNS support, for better and worse             |
| FaceTime               | Telecom        | WebRTC, TURN, TURN-over-TCP       | Works              | Slight latency improvement                         |
| Google Meet            | Telecom        | STUN/TURN, TURN-over-TCP          | Works              | Slight latency improvement                         |
| Jitsi (meet.jit.si)    | Telecom        | WebRTC, TURN-over-TLS, Cloudflare | Fails on Tor       | No change, problem does not appear UDP-related     |
| Jitsi (docker-compose) | Telecom        | WebRTC, centralized STUN only     | Fails without UDP  | Starts working                                     |
| Linphone               | Telecom (SIP)  | SIP-over-TLS, STUN, TURN          | Fails without UDP  | Starts working                                     |
| Signal                 | Telecom        | WebRTC, TURN, TURN-over-TCP       | Works              | Slight latency improvement                         |
| Skype                  | Telecom        | P2P, STUN, TURN-over-TLS          | Works              | Slight latency improvement                         |
| WhatsApp               | Telecom        | STUN, TURN-over-TCP. Multi server | Works              | Slight latency improvement                         |
| WiFi Calling           | Telecom        | IPsec tunnel                      | Out of scope       | Still out of scope                                 |
| Zoom                   | Telecom        | client/server or P2P, UDP/TCP     | Works              | Slight latency improvement                         |

# Design approaches

Now that we've defined some categories of UDP traffic we are interested in handling, this section starts to examine different implementation techniques.

We can broadly split these into *datagram routing* and *tunneling*.

## Datagram routing

These approaches seek to use an anonymity network that can directly route datagrams from place to place.
These approaches are the most obviously suitable for implementing UDP, but they also form the widest departure from classic Tor.

### 3rd party implementations

TODO: What examples do we have of 3rd party mixnets that already have these desirable datagram properties? i2p would be a good reference point here, but only for the mixnet portion itself not for any kind of exit bridge.

### Hybrid approaches

TODO: If we do have a good story for some potential datagram mixnet above, examine the possibility of splitting traffic between Tor and that network.

TODO: Also discuss splitting traffic between exit and rend for onions? This is technically more likely to be useful for tunneling below, so maybe we don't go into it here.

### Making room for a future Tor implementation

TODO: Consider whether datagram message types could realistically carry over to a future Tor protocol that supports unrealiable delivery. Would we be building a foundation for real or is it not useful yet?

## Tunneling

### Using TURN (RFC8656) encapsulated in a Tor stream

TODO: Comparison vs. an entirely out-of-protocol and potentially out-of-process TURN server. Is this complexity warranted?

### Using Tor streams to an exit

TODO: Bulk of the design goes here, this is what we likely start with

### Using Tor streams to a rendezvous point

TODO: possible generalization of above to support onion UDP. big caveat that apps need extensions to support onion addressing.

#### Stream usage

An early design juncture in this project is the particular choice of scope for one *stream* in the existing Tor protocol.

- One stream **per socket** was the approach suggested in Proposal 339.

  Each stream would match the lifetime of a source port allocation.
  There would be a single peer address/port allowed per allocation.
  This matches the usage of BSD-style sockets on which `connect()` has completed.
  It's incompatible with many of the applications analyzed.
  Multiple peers are typically needed for a variety of reasons, like connectivity checks or multi-region servers.

  This approach would be simplest to implement and specify.
  It also unfortunately has very limited compatibility, and no clear path toward incremental upgrades if we wish to improve compatibility later.
  
- One stream **per flow** has also been suggested. This would assign a stream ID to the combination of an allocated source port and a remote peer address/port. The flows may contain additional flags, like transmit and receive filtering, IPv4/v6, and *Don't Fragment*.

  This has advantages in keeping the datagram cells simple, with no additional IDs beyond the existing circuit ID.
  It may also have advantages in DoS-prevention and in privacy analysis.
  
  By decoupling protocol features from the lifetime of sockets on the exit side, we facilitate implementing the desirable "Port overlapping" NAT behavior as mentioned above.

  Stream lifetimes, in this case, would not have any specific meaning other than the lifetime of the ID itself.
  The bundle of flows associated with one source port would still all be limited to the lifetime of a Tor circuit, by scoping the source port identifier to be contained within the lifetime of its circuit.

  It would be necessary to allocate a new stream ID any time a new set of parameters (source port, remote address, remote port) is seen.
  This would most commonly happen as a result of a first datagram sent to a new peer, coinciding with the establishment of a NAT-style mapping and the possible allocation of a socket on the exit.
  A less common case needs to be considered too: what if the parameter tuple first occurs on the exit side?
  We don't yet have a way to allocate stream IDs from either end of a circuit.
  This would need to be considered, and the simplest solution might just be to partition the stream ID space into a half that can be allocated by each side.
  This leaves a quite unfair split in the common case where streams are almost always allocated by the OP side.

  When is this exit-originated circuit ID allocation potentially needed?
  It is clearly needed when using **address-dependent filtering**.
  An incoming datagram from a previously-unseen peer port is expected to be deliverable, and the exit would need to allocate an ID for it.

  Even with the stricter **address and port-dependent filtering** we may still be exposed to exit-originated circuit IDs if there are mismatches in the lifetime of the filter and the stream.

  This approach thus requires some attention to either correctly allocating stream IDs on both sides of the circuit, or choosing a filtering strategy and filter/mapping lifetime that does not ever leave stream IDs undefined when expecting incoming datagrams.

- One stream **per mapping** is an alternative which attemps to reduce the number of edge cases by merging the lifetimes of one stream and one **endpoint-independent mapping**.

  A mapping would always be allocated from the OP side.
  It could explicitly specify a filtering style, if we wish to allow applications to request non-port-dependent filtering for compatibility.
  Each datagram within the stream would still need to be tagged with a peer address/port in some way.

  This puts us in a very similar design space to TURN, RFC8656.
  In TURN, "allocations" are made explicitly on request, and assigned a random relayed port.
  TURN also uses its "allocations" as an opportunity to support a *Don't Fragment* flag.
  
  Within the scope of one allocation, datagrams each still may have an arbitrary peer address. This takes up additional space in every datagram.

- Hybrid approach, one stream **per mapping** and **per flow** at the same time

  We could try to combine the strengths of both approaches, using the lifetime of one stream to define a mapping and to carry otherwise-unbundled traffic while also allowing additional streams to bundle datagrams that would otherwise have repetetive headers.

  This avoids the space overhead of a purely **per mapping** approach and avoids the ID allocation and lifetime complexity introduced with **per flow**.
  
  This takes more inspiration from TURN, where commonly used peers will be defined as a "channel" with an especially short header.
  In TURN, a "channel" is only ever allocated from the originating side of the connection.
  Incoming datagrams with no channel can always be represented in the long form, so TURN never has to allocate channels unexpectedly.

# Protocol Designs

Currently we have two design candidates, and both are described here.

TODO: Exit selection is likely common to both of these approaches. Talk about how we specify UDP exit policy, how we provide a smart tradeoff between ability to filter harmful traffic while avoiding an explosion in exit policy complexity.

## Tor UDP Mapping Protocol

This is a *tunneled* approach, using Tor's existing protocol objects where possible. Exits advertise support for specific UDP policies. Clients choose an exit where they would like to allocate a UDP local port. They create one *stream* with a lifetime matching the lifetime of that mapping. Optional additional *streams* may be used as fast paths for common peers. This is the *hybrid approach* to stream usage, from above.

- `NEW_UDP_MAPPING`

  - always client-to-exit
  - stream ID for mapping
  - no address given
  - "don't fragment" flag
  - port-specific filtering flag
  - no reply? early data always ok.
  - ended on circuit teardown or by `END`

- `UDP_MAPPING_DATAGRAM`

  - conveys one datagram on a stream defined by ALLOCATE_UDP_MAPPING.
  - Includes peer address (ipv4/ipv6) as well as datagram content

- `NEW_UDP_FLOW`

  - Lifetime is <= lifetime of UDP mapping.
  - stream ID for parent mapping, and new flow within that mapping
  - ended on mapping end or by explicit `END`
  - Includes peer address (ipv4/ipv6)

- `UDP_FLOW_DATAGRAM`

  - Datagram contents without address, for flow streams.
  - If a flow stream exists, the exit must use `UDP_FLOW_DATAGRAM` instead of `UDP_MAPPING_DATAGRAM`.
  - Mappings that do not request port-specific filtering may always get unexpected UDP_MAPPING_DATAGRAMs. Mappings that do use port-specific filtering could make a flow for their only expected peers, then expect to never see `UDP_MAPPING_DATAGRAM`.

## TURN over Tor

In this approach, a single Tor stream is used for all UDP traffic.

- `CONNECT_TURN`

  - Establish a stream as a connection to the exit relay's built-in (or configured) TURN server.
  - RFC8656 requires authentication before data can be relayed, which is a good default best practice for the internet perhaps but is the opposite of what Tor is trying to do. We would either modify the specification to relax this auth requirement, or we would provide a way for clients to discover credentials: either by fixing them ahead of time or by including them in the relay descriptor.

# Risks

## Performance and compatibility regressions

TODO: By implementing UDP at all, we open ourselves up to bugs and performance regressions vs any existing TCP compatibility support present in applications.

## Additional malicious traffic

TODO: Various kinds of traffic we want to avoid

- Amplification attacks against arbitrary target (protocol contains reply addr, like SIP)
- Amplification attacks against exit relay (similar to attacks against NAT)
- Malicious fragmented traffic
- Excessive sends to a host that has never replied (DoS)
- Excessive number of peers (makes port scanning too much easier)

See also RFC 7675, on the concept of "Send consent".

## Additional high-bandwidth application traffic

TODO: Analyze bittorrent and friends

## Additional exposure to malicious exit nodes

TODO: There may be new cases where an exit node could modify or inspect UDP-tunneled traffic that would otherwise have been unavailable, e.g. by bypassing tor or by using a secure TURN-over-TLS tunnel.

## Additional risks to anonymity

TODO: ICE connectivity checks, as mentioned elsewhere.

TODO: Are there plaintext identifiers in these telecom apps?

TODO: Is there any chance we make the anonymity risk worse by providing UDP exits than it would be with an application-provided TCP relay server?

### Traffic injection attacks

Some forms of UDP support would have obvious and severe traffic injection vulnerabilities. For example, the very permissive *endpoint-independent filtering* strategy would allow any host on the internet to send datagrams in bulk to all available local ports on a Tor exit in order to map that traffic's effect on any guards they control.

Any vehicle for malicious parties to mark traffic can be abused to deanonymize users. Even if there is a more restrictive filtering policy, UDP's lack of sequence numbers make header spoofing attacks considerably easier than in TCP. Third parties capable of routing datagrams to an exit with a spoofed source address could bypass filtering when the communicating parties are known or can be guessed. For example, a malicious superuser at an ISP without egress filtering could send packets with the source IPs set to various common DNS servers and application STUN/TURN servers. If a specific application is being targeted, only the exit node and local port numbers need to be guessed by brute force.

In case of malicious exit relays, whole datagrams can be inserted and dropped, and datagrams may be padded with additional data, both without any specific knowledge of the application protocol. With specific protocol insights, a malicious relay may make arbitrary edits to plaintext data.

Of particular interest is the plaintext STUN, TURN, and ICE traffic used by most WebRTC apps. These applications rely on higher-level protocols (SRTP, DTLS) to provide end-to-end encryption and authentication. A compromise at the connection establishment layer would not violate application-level end-to-end security requirements, making it outside the threat model of WebRTC but very much still a concern for Tor.

These attacks are not fully unique to the proposed UDP support, but UDP may increase exposure. In cases where the application already has a fallback using TURN-over-TLS, the proposal is a clear regression over previous behaviors. Even when we are comparing plaintext to plaintext, there may be a serious downside to centralizing all connection establishment traffic through a small number of exit IPs. Depending on your threat model, it could very well be more private to allow the UDP traffic to bypass Tor entirely.

### Peer to peer deanonymization attacks

One of our goals was to achieve the compatibility and perhaps performance benefits of allowing "peer to peer" (in our case really exit-to-exit) UDP connections. We expect this to enable the subset of applications that lack a fallback path which loops traffic through an app-provided server.

This goal may be at odds with our privacy requirements. At minimum, a pool of malicious exit nodes could passively collect metadata about these connections as a noisy proxy for call metadata.

TODO: Seems likely applications do often leak enough information through the plaintext portions of their UDP traffic in order to facilitate fingerprinting, I should look closer at this and confirm or deny.

Even if the application traffic itself is fingerprint-resistant, this is easily combined with the above traffic injection attacks in order to mark specific communicating peers.

## Port allocation risks

TODO: Without a way to limit port allocations, exits can quickly run out.

TODO: Incorporate a mitigation in the form of Port Overlapping