aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicah Elizabeth Scott <beth@torproject.org>2023-12-20 15:07:07 -0800
committerMicah Elizabeth Scott <beth@torproject.org>2024-01-25 08:56:48 -0800
commit0dd88e6e89e620ab015fc402718bc6cb9ebaf4c1 (patch)
treef560f9da9490e7a99145d2d38180f52cd174af70
parentaee32ef87eb76b1a0b67d2c32701c1f77772830c (diff)
downloadtorspec-0dd88e6e89e620ab015fc402718bc6cb9ebaf4c1.tar.gz
torspec-0dd88e6e89e620ab015fc402718bc6cb9ebaf4c1.zip
Revert proposal 339 to Nick's accepted version, split out new text
The new file is now an unedited copy of the lines added in my diff. Future commits will clean this up.
-rw-r--r--proposals/339-udp-over-tor.md313
-rw-r--r--proposals/XXX-udp-app-support.md304
2 files changed, 321 insertions, 296 deletions
diff --git a/proposals/339-udp-over-tor.md b/proposals/339-udp-over-tor.md
index 813531e..12de0c6 100644
--- a/proposals/339-udp-over-tor.md
+++ b/proposals/339-udp-over-tor.md
@@ -11,8 +11,7 @@ Status: Accepted
Tor currently only supports delivering two kinds of traffic to the
internet: TCP data streams, and a certain limited subset of DNS
requests. This proposal describes a plan to extend the Tor protocol so
-that exit relays can also relay some additional types of UDP traffic
-to the network.
+that exit relays can also relay UDP traffic to the network?.
Why would we want to do this? There are important protocols that use
UDP, and in order to support users that rely on these protocols, we'll
@@ -32,16 +31,7 @@ implemented some version of
(relay fragment cells) so that we can transmit relay messages larger
than 498 bytes.
-With the above in mind, the goal of this proposal is specifically to enable compatibility with more applications.
-We will analyze some of those applications below, in order to choose an appropriate subset of UDP to implement which achieves our compatibility goals.
-These compatibility goals will need to be weighed against any anonymity hazards or opportunities for abuse.
-
-We expect that work to improve round-trip time and jitter characteristics, such as Conflux, will benefit both TCP and UDP applications.
-Many applications already support both transport protocols, and will perform similarly with or without this proposal.
-
-# UDP Traffic Models
-
-## User Datagram Protocol (RFC768)
+# Overview
UDP is a datagram protocol; it allows messages of up to 65536 bytes,
though in practice most protocols will use smaller messages in order to
@@ -51,278 +41,27 @@ UDP messages can be dropped or re-ordered. There is no authentication
or encryption baked into UDP, though it can be added by higher-level
protocols like DTLS or QUIC.
-The "User Interface" suggested by 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 and later RFC7857 offer best practices for implementing NAT.
-Carrier-grade NAT requirements are addressed by RFC6888.
-RFC8445 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.
-
-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.
-
-### 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
+When an application opens a UDP socket, the OS assigns it a 16-bit port
+on some IP address of a local interface. The application may send
+datagrams from that address:port combination, and will receive datagrams
+sent to that address:port.
-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.
+With most (all?) IP stacks, a UDP socket can either be _connected_ to a
+remote address:port (in which case all messages will be sent to that
+address:port, and only messages from that address will be passed to the
+application), or _unconnected_ (in which case outgoing messages can be
+sent to any address:port, and incoming messages from any address:port
+will be accepted).
-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 |
-
-## 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".
-
-# Anonymity risks
-
-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?
-
-# Alternative designs
-
-TODO: Comparison vs. an entirely out-of-protocol and potentially out-of-process TURN server. Is this complexity warranted?
-
-# Tor protocol design
-
-Using the specification- and application-based goals above, here we will briefly discuss the design constraints as they relate to Tor's protocol.
-
-## 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 an earlier version of this proposal.
-
- 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.
+In this version of the protocol, we support only _connected_ UDP
+sockets, though we provide extension points for someday adding
+_unconnected_ socket support.
# Tor protocol specification
-## Overview
-TODO
+## Overview
We reserve three new relay commands: `CONNECT_UDP`, `CONNECTED_UDP` and
`DATAGRAM`.
@@ -376,8 +115,6 @@ can be mixed on the same circuit, but not on the same stream.
## Discussion on "too full"
-TODO
-
(To be determined! We need an algorithm here before we implement, though
our choice of algorithm doesn't need to be the same on all exits or for
all clients, IIUC.)
@@ -451,8 +188,6 @@ cell.
### CONNECT_UDP
-TODO: Source port cookie, if we choose to have multiple streams per source port. (Under discussion still; see below) Flags for transmit/receive allowed.
-
```
/* Tells an exit to connect a UDP port for connecting to a new target
address. The stream ID is chosen by the client, and is part of
@@ -485,8 +220,6 @@ cell behave with regards to the hostname given.
### CONNECTED_UDP
-TODO: Do we need this at all? If a NAT is involved the info won't be correct. Even if it's correct, existing apps (connected via a VPN) wouldn't be able to make use of it. They would still talk to a STUN server. Do we care about UDP apps written directly to the Arti API? Are there non-malicious uses for this?
-
A CONNECTED_UDP cell sent in response to a CONNECT_UDP cell has the following
format.
@@ -509,8 +242,6 @@ the cell is considered malformed.
### DATAGRAM
-TODO: This would need an additional byte or two of 'peer ID' if we choose to implement streams as 1:1 with local port allocations. This is still being discussed and a conclusion hasn't been reached, see below.
-
```
struct datagram_body {
/* The datagram body is the entire body of the message.
@@ -525,14 +256,8 @@ We explicitly allow all END reasons from the existing Tor protocol.
We may wish to add more as we gain experience with this protocol.
-TODO: What does it mean for a stream to end here? This depends on how we choose to do port allocations, which needs more discussion. Should the stream lifetime and port allocation lifetime match, or should there be a separate timer system?
-
### Extensions for unconnected sockets
-TODO: This is flawed, the "connected/unconnected" idea is just a UNIX'ism and we should be thinking about streams and about how we allocate source ports. Also, limiting connections to a single peer breaks 100% of P2P connections, since they require using STUN (or similar) first.
-
-TODO: Right now beth and mike have different ideas for how this could work, and we need to discuss more.
-
Because of security concerns I don't suggest that we support unconnected
sockets in the first version of this protocol. But _if we did_, here's how
I'd suggest we do it.
@@ -582,8 +307,6 @@ their exit policies did not say so.
# MTU notes and issues
-TODO: Revise this section. Nearly everything assumes the MTU is larger, and we are driving this design based on app compatibility.
-
Internet time. I might have this wrong.
The "maximum safe IPv4 UDP payload" is "well known" to be only 508 bytes
@@ -601,13 +324,13 @@ restrict their datagram size to fit into a transport this small.
we'll probably be breaking a bunch of stuff, and creating a great deal
of overhead.)
+
# Integration issues
I do not know how applications should tell Tor that they want to use this
feature. Any ideas? We should probably integrate with their MTU discovery
systems too if we can. (TODO: write about some alternatives)
-TODO: "Application" here being the VPN or the end-user app? We've discussed having a per-app opt-in for UDP, enforced at the VPN layer.
# Resource management issues
@@ -620,8 +343,6 @@ idea?
# Security issues
-TODO: update this
-
- Are there any major DoS or amplification attack vectors that this
enables? I *think* no, because we don't allow spoofing the IP
header. But maybe some wacky protocol out there lets you specify a
diff --git a/proposals/XXX-udp-app-support.md b/proposals/XXX-udp-app-support.md
new file mode 100644
index 0000000..3a08706
--- /dev/null
+++ b/proposals/XXX-udp-app-support.md
@@ -0,0 +1,304 @@
+```
+Filename: XXX-udp-app-support.md
+Title: Support for UDP Applications over Tor
+Author: Micah Elizabeth Scott
+Created: December 2023
+Status: Draft
+```
+
+that exit relays can also relay some additional types of UDP traffic
+to the network.
+With the above in mind, the goal of this proposal is specifically to enable compatibility with more applications.
+We will analyze some of those applications below, in order to choose an appropriate subset of UDP to implement which achieves our compatibility goals.
+These compatibility goals will need to be weighed against any anonymity hazards or opportunities for abuse.
+
+We expect that work to improve round-trip time and jitter characteristics, such as Conflux, will benefit both TCP and UDP applications.
+Many applications already support both transport protocols, and will perform similarly with or without this proposal.
+
+# UDP Traffic Models
+
+## User Datagram Protocol (RFC768)
+The "User Interface" suggested by 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 and later RFC7857 offer best practices for implementing NAT.
+Carrier-grade NAT requirements are addressed by RFC6888.
+RFC8445 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.
+
+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.
+
+### 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 |
+## 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".
+
+# Anonymity risks
+
+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?
+
+# Alternative designs
+
+TODO: Comparison vs. an entirely out-of-protocol and potentially out-of-process TURN server. Is this complexity warranted?
+
+# Tor protocol design
+
+Using the specification- and application-based goals above, here we will briefly discuss the design constraints as they relate to Tor's protocol.
+
+## 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 an earlier version of this proposal.
+
+ 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.
+
+
+# Tor protocol specification
+TODO
+
+TODO
+
+TODO: Source port cookie, if we choose to have multiple streams per source port. (Under discussion still; see below) Flags for transmit/receive allowed.
+
+TODO: Do we need this at all? If a NAT is involved the info won't be correct. Even if it's correct, existing apps (connected via a VPN) wouldn't be able to make use of it. They would still talk to a STUN server. Do we care about UDP apps written directly to the Arti API? Are there non-malicious uses for this?
+
+TODO: This would need an additional byte or two of 'peer ID' if we choose to implement streams as 1:1 with local port allocations. This is still being discussed and a conclusion hasn't been reached, see below.
+
+TODO: What does it mean for a stream to end here? This depends on how we choose to do port allocations, which needs more discussion. Should the stream lifetime and port allocation lifetime match, or should there be a separate timer system?
+
+TODO: This is flawed, the "connected/unconnected" idea is just a UNIX'ism and we should be thinking about streams and about how we allocate source ports. Also, limiting connections to a single peer breaks 100% of P2P connections, since they require using STUN (or similar) first.
+
+TODO: Right now beth and mike have different ideas for how this could work, and we need to discuss more.
+
+TODO: Revise this section. Nearly everything assumes the MTU is larger, and we are driving this design based on app compatibility.
+
+TODO: "Application" here being the VPN or the end-user app? We've discussed having a per-app opt-in for UDP, enforced at the VPN layer.
+TODO: update this
+