aboutsummaryrefslogtreecommitdiff
path: root/spec/tor-spec/tearing-down-circuits.md
blob: 3fde69347c149f2a062cf66de3ecfa6708c367ac (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
<a id="tor-spec.txt-5.4"></a>

# Tearing down circuits{#tearing-down-circuits}

Circuits are torn down when an unrecoverable error occurs along
the circuit, or when all streams on a circuit are closed and the
circuit's intended lifetime is over.

ORs SHOULD also tear down circuits which attempt to create:

- streams with RELAY_BEGIN, or
- rendezvous points with ESTABLISH_RENDEZVOUS,
  ending at the first hop. Letting Tor be used as a single hop proxy makes
  exit and rendezvous nodes a more attractive target for compromise.

ORs MAY use multiple methods to check if they are the first hop:

```text
   * If an OR sees a circuit created with CREATE_FAST, the OR is sure to be
     the first hop of a circuit.
   * If an OR is the responder, and the initiator:
     * did not authenticate the link, or
     * authenticated with a key that is not in the consensus,
     then the OR is probably the first hop of a circuit (or the second hop of
     a circuit via a bridge relay).

   Circuits may be torn down either completely or hop-by-hop.
```

To tear down a circuit completely, an OR or OP sends a DESTROY
cell to the adjacent nodes on that circuit, using the appropriate
direction's circID.

Upon receiving an outgoing DESTROY cell, an OR frees resources
associated with the corresponding circuit. If it's not the end of
the circuit, it sends a DESTROY cell for that circuit to the next OR
in the circuit. If the node is the end of the circuit, then it tears
down any associated edge connections (see
[Calculating the 'Digest' field](./relay-cells.md#digest-field)).

After a DESTROY cell has been processed, an OR ignores all data or
DESTROY cells for the corresponding circuit.

To tear down part of a circuit, the OP may send a RELAY_TRUNCATE message
signaling a given OR (Stream ID zero).  That OR sends a DESTROY
cell to the next node in the circuit, and replies to the OP with a
RELAY_TRUNCATED message.

\[Note: If an OR receives a TRUNCATE message and it has any relay cells
still queued on the circuit for the next node it will drop them
without sending them.  This is not considered conformant behavior,
but it probably won't get fixed until a later version of Tor.  Thus,
clients SHOULD NOT send a TRUNCATE message to a node running any current
version of Tor if a) they have sent relay cells through that node,
and b) they aren't sure whether those cells have been sent on yet.\]

```text
   When an unrecoverable error occurs along one a circuit, the nodes
   must report it as follows:
     * If possible, send a DESTROY cell to ORs _away_ from the client.
     * If possible, send *either* a DESTROY cell towards the client, or
       a RELAY_TRUNCATED cell towards the client.
```

Current versions of Tor do not reuse truncated RELAY_TRUNCATED
circuits: An OP, upon receiving a RELAY_TRUNCATED, will send
forward a DESTROY cell in order to entirely tear down the circuit.
Because of this, we recommend that relays should send DESTROY
towards the client, not RELAY_TRUNCATED.

```text
   NOTE:
     In tor versions before 0.4.5.13, 0.4.6.11 and 0.4.7.9, relays would
     handle an inbound DESTROY by sending the client a RELAY_TRUNCATED
     message.  Beginning with those versions, relays now propagate
     DESTROY cells in either direction, in order to tell every
     intermediary ORs to stop queuing data on the circuit.  The earlier
     behavior created queuing pressure on the intermediary ORs.
```

The body of a DESTROY cell or RELAY_TRUNCATED message contains a single
octet, describing the reason that the circuit was
closed. RELAY_TRUNCATED message, and DESTROY cells sent \_towards the
client, should contain the actual reason from the list of error codes
below.  Reasons in DESTROY cell SHOULD NOT be propagated downward or
upward, due to potential side channel risk: An OR receiving a DESTROY
command should use the DESTROYED reason for its next cell. An OP
should always use the NONE reason for its own DESTROY cells.

The error codes are:

```text
     0 -- NONE            (No reason given.)
     1 -- PROTOCOL        (Tor protocol violation.)
     2 -- INTERNAL        (Internal error.)
     3 -- REQUESTED       (A client sent a TRUNCATE command.)
     4 -- HIBERNATING     (Not currently operating; trying to save bandwidth.)
     5 -- RESOURCELIMIT   (Out of memory, sockets, or circuit IDs.)
     6 -- CONNECTFAILED   (Unable to reach relay.)
     7 -- OR_IDENTITY     (Connected to relay, but its OR identity was not
                           as expected.)
     8 -- CHANNEL_CLOSED  (The OR connection that was carrying this circuit
                           died.)
     9 -- FINISHED        (The circuit has expired for being dirty or old.)
    10 -- TIMEOUT         (Circuit construction took too long)
    11 -- DESTROYED       (The circuit was destroyed w/o client TRUNCATE)
    12 -- NOSUCHSERVICE   (Request for unknown hidden service)
```