aboutsummaryrefslogtreecommitdiff
path: root/proposals/254-padding-negotiation.txt
blob: e4da0045549303a66bb2bd5b29e0a671e5ec588f (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
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
Filename: 254-padding-negotiation.txt
Title: Padding Negotiation
Authors: Mike Perry
Created: 01 September 2015
Status: Draft


0. Overview

This proposal aims to describe mechanisms for requesting various types
of padding from relays.

These padding primitives are general enough to use to defend against
both website traffic fingerprinting as well as hidden service circuit
setup fingerprinting.


1. Motivation

Tor already supports both link-level padding via (CELL_PADDING cell
types), as well as circuit-level padding (via RELAY_COMMAND_DROP relay
cells).

Unfortunately, there is no way for clients to request padding from
relays, or request that relays not send them padding to conserve
bandwidth. This proposal aims to create a mechanism for clients to do
both of these.

It also establishes consensus parameters to limit the amount of padding
that relays will send, to prevent custom wingnut clients from requesting
too much.


2. Link-level padding

Padding is most useful if it can defend against a malicious or
compromised guard node. However, link-level padding is still useful to
defend against an adversary that can merely observe a Guard node
externally, such as for low-resolution netflow-based attacks (see
Proposal 251[1]).

In that scenario, the primary negotiation mechanism we need is a way for
mobile clients to tell their Guards to stop padding, or to pad less
often. The following Trunnel payloads should cover the needed
parameters:

    const CELL_PADDING_COMMAND_STOP = 1;
    const CELL_PADDING_COMMAND_START = 2;

    /* This command tells the relay to stop sending any periodic
       CELL_PADDING cells. */
    struct cell_padding_stop {
      u8 command IN [CELL_PADDING_COMMAND_STOP];
    };

    /* This command tells the relay to alter its min and max netflow
       timeout range values, and send padding at that rate (resuming
       if stopped). */
    struct cell_padding_start {
      u8 command IN [CELL_PADDING_COMMAND_START];

      /* Min must not be lower than the current consensus parameter
         nf_ito_low. */
      u16 ito_low_ms;

      /* Max must not be lower than ito_low_ms */
      u16 ito_high_ms;
    };

More complicated forms of link-level padding can still be specified
using the primitives in Section 3, by using "leaky pipe" topology to
send the RELAY commands to the Guard node instead of to later nodes in
the circuit.


3. End-to-end circuit padding

For circuit-level padding, we need two types of additional features: the
ability to schedule additional incoming cells at one or more fixed
points in the future, and the ability to schedule a statistical
distribution of arbitrary padding to overlay on top of non-padding
traffic (aka "Adaptive Padding").

In both cases, these messages will be sent from clients to middle nodes
using the "leaky pipe" property of the 'recognized' field of RELAY
cells, allowing padding to originate from middle nodes on a circuit in a
way that is not detectable from the Guard node.

This same mechanism can also be used to request padding from the Guard
node itself, to achieve link-level padding without the additional
overhead requirements on middle nodes.

3.1. Fixed-schedule padding message (RELAY_COMMAND_PADDING_SCHEDULE)

The fixed schedule padding will be encoded in a
RELAY_COMMAND_PADDING_SCHEDULE cell. It specifies a set of up to 80
fixed time points in the future to send cells.

XXX: 80 timers is a lot to allow every client to create. We may want to
have something that checks this structure to ensure it actually
schedules no more than N in practice, until we figure out how to
optimize either libevent or timer scheduling/packet delivery. See also
Section 4.3.

The RELAY_COMMAND_PADDING_SCHEDULE body is specified in Trunnel as
follows:

    struct relay_padding_schedule {
       u8 schedule_length IN [1..80];

       /* Number of microseconds before sending cells (cumulative) */
       u32 when_send[schedule_length];

       /* Number of cells to send at time point sum(when_send[0..i]) */
       u16 num_cells[schedule_length];

       /* Adaptivity: If 1, and server-originating cells arrive before the
          next when_send time, then decrement the next non-zero when_send
          index, so we don't send a padding cell then, too */
       u8 adaptive IN [0,1];
    };

To allow both high-resolution time values, and the ability to specify
timeout values far in the future, the time values are cumulative. In
other words, sending a cell with when_send = [MAX_INT, MAX_INT, MAX_INT,
0...] and num_cells = [0, 0, 100, 0...] would cause the relay to reply
with 100 cells in 3*MAX_INT microseconds from the receipt of this cell.

This scheduled padding is non-periodic. For any forms of periodic
padding, implementations should use the RELAY_COMMAND_PADDING_ADAPTIVE
cell from Section 3.2 instead.

3.2. Adaptive Padding message (RELAY_COMMAND_PADDING_ADAPTIVE)

The following message is a generalization of the Adaptive Padding
defense specified in "Timing Attacks and Defenses"[2].

The message encodes either one or two state machines, each of which can
contain one or two histograms ("Burst" and "Gap") governing their
behavior.

The "Burst" histogram specifies the delay probabilities for sending a
padding packet after the arrival of a non-padding data packet.

The "Gap" histogram specifies the delay probabilities for sending
another padding packet after a padding packet was just sent from this
node. This self-triggering property of the "Gap" histogram allows the
construction of multi-packet padding trains using a simple statistical
distribution.

Both "Gap" and "Burst" histograms each have a special "Infinity" bin,
which means "We have decided not to send a packet".

Each histogram is combined with state transition information, which
allows a client to specify the types of incoming packets that cause the
state machine to decide to schedule padding cells (and/or when to cease
scheduling them).

The client also maintains its own local histogram state machine(s), for
reacting to traffic on its end.

Note that our generalization of the Adaptive Padding state machine also
gives clients full control over the state transition events, even
allowing them to specify a single-state Burst-only state machine if
desired. See Sections 3.2.1 and 3.2.2 for details.

The histograms and the associated state machine packet layout is
specified in Trunnel as follows:

    /* These constants form a bitfield to specify the types of events
     * that can cause transitions between state machine states.
     *
     * Note that SENT and RECV are relative to this endpoint. For
     * relays, SENT means packets destined towards the client and
     * RECV means packets destined towards the relay. On the client,
     * SENT means packets destined towards the relay, where as RECV
     * means packets destined towards the client.
     */
    const RELAY_PADDING_TRANSITION_EVENT_NONPADDING_RECV = 1;
    const RELAY_PADDING_TRANSITION_EVENT_NONPADDING_SENT = 2;
    const RELAY_PADDING_TRANSITION_EVENT_PADDING_SENT = 4;
    const RELAY_PADDING_TRANSITION_EVENT_PADDING_RECV = 8;
    const RELAY_PADDING_TRANSITION_EVENT_INFINITY = 16;
    const RELAY_PADDING_TRANSITION_EVENT_BINS_EMPTY = 32;

    /* Token Removal rules. Enum, not bitfield. */
    const RELAY_PADDING_REMOVE_NO_TOKENS = 0;
    const RELAY_PADDING_REMOVE_LOWER_TOKENS = 1;
    const RELAY_PADDING_REMOVE_HIGHER_TOKENS = 2;
    const RELAY_PADDING_REMOVE_CLOSEST_TOKENS = 3;

    /* This payload encodes a histogram delay distribution representing
     * the probability of sending a single RELAY_DROP cell after a
     * given delay in response to a non-padding cell.
     *
     * Payload max size: 113 bytes
     */
    struct burst_state {
      u8 histogram_len IN [2..51];
      u16 histogram[histogram_len];
      u32 start_usec;
      u16 max_sec;

      /* This is a bitfield that specifies which direction and types
       * of traffic that cause us to abort our scheduled packet and
       * return to waiting for another event from transition_burst_events.
       */
      u8 transition_start_events;

      /* This is a bitfield that specifies which direction and types
       * of traffic that cause us to remain in the burst state: Cancel the
       * pending padding packet (if any), and schedule another padding
       * packet from our histogram.
       */
      u8 transition_reschedule_events;

      /* This is a bitfield that specifies which direction and types
       * of traffic that cause us to transition to the Gap state. */
      u8 transition_gap_events;

      /* If true, remove tokens from the histogram upon padding and
       * non-padding activity. */
      u8 remove_tokens IN [0..3];
    };

    /* This histogram encodes a delay distribution representing the
     * probability of sending a single additional padding packet after
     * sending a padding packet that originated at this hop.
     *
     * Payload max size: 113 bytes
     */
    struct gap_state {
      u8 histogram_len IN [2..51];
      u16 histogram[histogram_len];
      u32 start_usec;
      u16 max_sec;

      /* This is a bitfield which specifies which direction and types
       * of traffic should cause us to transition back to the start
       * state (ie: abort scheduling packets completely). */
      u8 transition_start_events;

      /* This is a bitfield which specifies which direction and types
       * of traffic should cause us to transition back to the burst
       * state (and schedule a packet from the burst histogram). */
      u8 transition_burst_events;

      /* This is a bitfield that specifies which direction and types
       * of traffic that cause us to remain in the gap state: Cancel the
       * pending padding packet (if any), and schedule another padding
       * packet from our histogram.
       */
      u8 transition_reschedule_events;

      /* If true, remove tokens from the histogram upon padding and
         non-padding activity. */
      u8 remove_tokens IN [0..3];
    };

    /* Payload max size: 227 bytes */
    struct adaptive_padding_machine {
      /* This is a bitfield which specifies which direction and types
       * of traffic should cause us to transition to the burst
       * state (and schedule a packet from the burst histogram). */
       u8 transition_burst_events;

       struct burst_state burst;
       struct gap_state gap;
    };

    /* This is the full payload of a RELAY_COMMAND_PADDING_ADAPTIVE
     * cell.
     *
     * Payload max size: 455 bytes
     */
    struct relay_command_padding_adaptive {
       /* Technically, we could allow more than 2 state machines here,
          but only two are sure to fit. More than 2 seems excessive
          anyway. */
       u8 num_machines IN [1,2];

       struct adaptive_padding_machine machines[num_machines];
    };

3.2.1. Histogram state machine operation

Each of pair of histograms ("Burst" and "Gap") together form a state
machine whose transitions are governed by incoming traffic and/or
locally generated padding traffic.

Each state machine has a Start state S, a Burst state B, and a Gap state
G.

The state machine starts idle (state S) until it receives a packet of a
type that matches the bitmask in machines[i].transition_burst_events. If
machines[i].transition_burst_events is 0, transition to the burst state
happens immediately.

This causes it to enter burst mode (state B), in which a delay t is
sampled from the Burst histogram, and a timer is scheduled to count down
until either another matching packet arrives, or t expires. If the
"Infinity" time is sampled from this histogram, the machine returns to
the lowest state with the INFINITY event bit set.

If a packet that matches machines[i].burst.transition_start_events
arrives before t expires, the machine transitions back to the Start
state.

If a packet that matches machines[i].burst.transition_reschedule_events
arrives before t expires, a new delay is sampled and the process is
repeated again, i.e.  it remains in burst mode.

Otherwise, if t expires, a padding message is sent to the other end.

If a packet that matches machines[i].burst.transition_gap_events
arrives (or is sent), the machine transitions to the Gap state G.

In state G, the machine samples from the Gap histogram and sends padding
messages when the time it samples expires. If an infinite delay is
sampled while being in state G we jump back to state B or S,
depending upon the usage of the infinity event bitmask.

If a packet arrives that matches gap.transition_start_events, the
machine transitions back to the Start state.

If a packet arrives that matches gap.transition_burst_events, the
machine transitions back to the Burst state.

If a packet arrives that matches
machines[i].gap.transition_reschedule_events, the machine remains in G
but schedules a new padding time from its Gap histogram.

In the event that a malicious or buggy client specifies conflicting
state transition rules with the same bits in multiple transition
bitmasks, the transition rules of a state that specify transition to
earlier states take priority. So burst.transition_start_events
takes priority over burst.transition_reschedule_events, and both of
these take priority over burst.transition_gap_events.

Similarly, gap.transition_start_events takes priority over
gap.transition_burst_events, and gap.transition_burst_events takes
priority over gap.transition_reschedule_events.

In our generalization of Adaptive Padding, either histogram may actually
be self-scheduling (by setting the bit
RELAY_PADDING_TRANSITION_EVENT_PADDING_SENT in their
transition_reschedule_events). This allows the client to create a
single-state machine if desired.

Clients are expected to maintain their own local version of the state
machines, for reacting to their own locally generated traffic, in
addition to sending one or more state machines to the middle relay. The
histograms that the client uses locally will differ from the ones it
sends to the upstream relay.

On the client, the "SENT" direction means packets destined towards the
relay, where as "RECV" means packets destined towards the client.
However, on the relay, the "SENT" direction means packets destined
towards the client, where as "RECV" means packets destined towards the
relay.

3.2.2. The original Adaptive Padding algorithm

As we have noted, the state machines above represent a generalization of
the original Adaptive Padding algorithm. To implement the original
behavior, the following flags should be set in both the client and
the relay state machines:

 num_machines = 1;

 machines[0].transition_burst_events =
    RELAY_PADDING_TRANSITION_EVENT_NONPADDING_SENT;

 machines[0].burst.transition_reschedule_events =
    RELAY_PADDING_TRANSITION_EVENT_NONPADDING_SENT;

 machines[0].burst.transition_gap_events =
    RELAY_PADDING_TRANSITION_EVENT_PADDING_SENT;

 machines[0].burst.transition_start_events =
    RELAY_PADDING_TRANSITION_EVENT_INFINITY;

 machines[0].gap.transition_reschedule_events =
    RELAY_PADDING_TRANSITION_EVENT_PADDING_SENT;

 machines[0].gap.transition_burst_events =
    RELAY_PADDING_TRANSITION_EVENT_NONPADDING_SENT |
    RELAY_PADDING_TRANSITION_EVENT_INFINITY;

The rest of the transition fields would be 0.

Adding additional transition flags will either increase or decrease the
amount of padding sent, depending on their placement.

The second machine slot is provided in the event that it proves useful
to have separate state machines reacting to both sent and received
traffic.

3.2.3. Histogram decoding/representation

Each of the histograms' fields represent a probability distribution that
is expanded into bins representing time periods a[i]..b[i] as follows:

start_usec,max_sec,histogram_len initialized from appropriate histogram
body.

n = histogram_len-1
INFINITY_BIN = n

a[0] = start_usec;
b[0] = start_usec + max_sec*USEC_PER_SEC/2^(n-1);
for(i=1; i < n; i++) {
  a[i] = start_usec + max_sec*USEC_PER_SEC/2^(n-i)
  b[i] = start_usec + max_sec*USEC_PER_SEC/2^(n-i-1)
}

To sample the delay time to send a padding packet, perform the
following:

  i = 0;
  curr_weight = histogram[0];

  tot_weight = sum(histogram);
  bin_choice = crypto_rand_int(tot_weight);

  while (curr_weight < bin_choice) {
    curr_weight += histogram[i];
    i++;
  }

  if (i == INFINITY_BIN)
    return; // Don't send a padding packet

  // Sample uniformly between a[i] and b[i]
  send_padding_packet_at = a[i] + crypto_rand_int(b[i] - a[i]);

In this way, the bin widths are exponentially increasing in width, where
the width is set at max_sec/2^(n-i) seconds. This exponentially
increasing bin width allows the histograms to most accurately represent
small interpacket delay (where accuracy is needed), and devote less
accuracy to larger timescales (where accuracy is not as important).

3.2.4. Token removal and refill

If the remove_tokens field is set to a non-zero value for a given
state's histogram, then whenever a padding packet is sent, the
corresponding histogram bin's token count is decremented by one.

If a packet matching the current state's transition_reschedule_events
bitmask arrives from the server before the chosen padding timer expires,
then a token is removed from a non-empty bin corresponding to
the delay since the last packet was sent, and the padding packet timer
is re-sampled from the histogram.

The three enums for the remove_tokens field govern if we take the token
out of the nearest lower non-empty bin, the nearest higher non-empty
bin, or simply the closest non-empty bin.

If the entire histogram becomes empty, it is then refilled to the
original values. This refill happens prior to any state transitions due
to RELAY_PADDING_TRANSITION_EVENT_BINS_EMPTY (but obviously does not
prevent the transition from happening).


3.2.5. Constructing the histograms

Care must be taken when constructing the histograms themselves, since
their non-uniform widths means that the actual underlying probability
distribution needs to be both normalized for total number of tokens, as
well as the non-uniform histogram bin widths.

Care should also be taken with interaction with the token removal rules
from Section 3.2.4. Obviously using a large number of tokens will cause
token removal to have much less of an impact upon the adaptive nature of
the padding in the face of existing traffic.

Actual optimal histogram and state transition construction for different
traffic types is expected to be a topic for further research.

Intuitively, the burst state is used to detect when the line is idle
(and should therefore have few or no tokens in low histogram bins). The
lack of tokens in the low histogram bins causes the system to remain in
the burst state until the actual application traffic either slows,
stalls, or has a gap.

The gap state is used to fill in otherwise idle periods with artificial
payloads from the server (and should have many tokens in low bins, and
possibly some also at higher bins).

It should be noted that due to our generalization of these states and
their transition possibilities, more complicated interactions are also
possible.


4. Security considerations and mitigations

The risks from this proposal are primarily DoS/resource exhaustion, and
side channels.

4.1. Rate limiting and accounting

Fully client-requested padding introduces a vector for resource
amplification attacks and general network overload due to
overly-aggressive client implementations requesting too much padding.

Current research indicates that this form of statistical padding should
be effective at overhead rates of 50-60%. This suggests that clients
that use more padding than this are likely to be overly aggressive in
their behavior.

We recommend that three consensus parameters be used in the event that
the network is being overloaded from padding to such a degree that
padding requests should be ignored:

  * CircuitPaddingMaxRatio
    - The maximum ratio of padding traffic to non-padding traffic
      (expressed as a percent) to allow on a circuit before ceasing
      to pad. Ex: 75 means 75 padding packets for every 100 non-padding
      packets.
    - Default: 120
  * CircuitPaddingLimitCount
    - The number of padding cells that must be transmitted before the
      ratio limit is applied.
    - Default: 5000
  * CircuitPaddingLimitTime
    - The time period in seconds over which to count padding cells for
      application of the ratio limit (ie: reset the limit count this
      often).
    - Default: 60

XXX: Should we cap padding at these rates, or fully disable it once
they're crossed? Probably cap?

In order to monitor the quantity of padding to decide if we should alter
these limits in the consensus, every node will publish the following
values in a padding-counts line in its extra-info descriptor:

 * write-drop-multihop
   - The number of RELAY_DROP cells sent by this relay to a next hop
     that is listed in the consensus.
 * write-drop-onehop
   - The number of RELAY_DROP cells sent by this relay to a next hop
     that is not listed in the consensus.
 * write-pad
   - The number of CELL_PADDING cells sent by this relay.
 * write-total
   - The total number of cells sent by this relay.
 * read-drop-multihop
   - The number of RELAY_DROP cells read by this relay from a hop
     that is listed in the consensus.
 * read-drop-onehop
   - The number of RELAY_DROP cells read by this relay from a hop
     that is not listed in the consensus.
 * read-pad
   - The number of CELL_PADDING cells read by this relay.
 * read-total
   - The total number of cells read by this relay.

Each of these counters will be rounded to the nearest 10,000 cells. This
rounding parameter will also be listed in the extra-info descriptor line, in
case we change it in a later release.

In the future, we may decide to introduce Laplace Noise in a similar
manner to the hidden service statistics, to further obscure padding
quantities.

4.2. Malicious state machines

The state machine capabilities of RELAY_COMMAND_PADDING_ADAPTIVE are
very flexible, and as a result may specify conflicting or
non-deterministic state transitions.

We believe that the rules in Section 3.2.1 for prioritizing transitions
towards lower states remove any possibility of non-deterministic
transitions.

However, because of self-triggering property that allows the state
machines to schedule more padding packets after sending their own
locally generated padding packets, care must be taken with the
interaction with the rate limiting rules in Section 4.1. If the limits
in section 4.1 are exceeded, the state machines should stop, rather than
continually poll themselves trying to transmit packets and being blocked
by the rate limiter at another layer.

4.3. Libevent timer exhaustion

As mentioned in section 3.1, scheduled padding may create an excessive
number of libevent timers. Care should be taken in the implementation to
devise a way to prevent clients from sending padding requests
specifically designed to impact the ability of relays to function by
causing too many timers to be scheduled at once.

XXX: Can we suggest any specifics here? I can imagine a few ways of
lazily scheduling timers only when they are close to their expiry time,
and other ways of minimizing the number of pending timer callbacks at a
given time, but I am not sure which would be best for libevent.

4.4. Side channels

In order to prevent relays from introducing side channels by requesting
padding from clients, all of these commands should only be valid in the
outgoing (from the client/OP) direction.

Clients should perform accounting on the amount of padding that they
receive, and if it exceeds the amount that they have requested, they
alert the user of a potentially misbehaving node, and/or close the
circuit.

Similarly, if RELAY_DROP cells arrive from the last hop of a circuit,
rather than from the expected interior node, clients should alert the
user of the possibility of that circuit endpoint introducing a
side-channel attack, and/or close the circuit.

4.5. Memory exhaustion

Because interior nodes do not have information on the current circuits
SENDME windows, it is possible for malicious clients to consume the
buffers of relays by specifying padding, and then not reading from the
associated circuits.

XXX: Tor already had a few flow-control related DoS's in the past[3]. Is
that defense sufficient here without any mods? It seems like it may be!

-------------------

1. https://gitweb.torproject.org/torspec.git/tree/proposals/251-netflow-padding.txt
2. http://freehaven.net/anonbib/cache/ShWa-Timing06.pdf
3. https://blog.torproject.org/blog/new-tor-denial-service-attacks-and-defenses