From 79e2e4d3cbabff41675aa1f7defb67f4acba398c Mon Sep 17 00:00:00 2001 From: Mike Perry Date: Fri, 23 Jun 2017 16:53:39 -0400 Subject: [PATCH 1/3] Ticket #17857: Padding off-switch for single hop connections This doesn't apply to currently active connections.. yet... --- src/or/channel.c | 7 +- src/or/channelpadding.c | 16 ++++ src/test/test_channelpadding.c | 164 +++++++++++++++++++++++++++++---- 3 files changed, 166 insertions(+), 21 deletions(-) diff --git a/src/or/channel.c b/src/or/channel.c index df6d7d342..8348ffd64 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -65,6 +65,7 @@ #include "routerlist.h" #include "scheduler.h" #include "compat_time.h" +#include "networkstatus.h" /* Global lists of channels */ @@ -2711,7 +2712,11 @@ channel_do_open_actions(channel_t *chan) /* Disable or reduce padding according to user prefs. */ if (chan->padding_enabled || get_options()->ConnectionPadding == 1) { - if (!get_options()->ConnectionPadding) { + if (!get_options()->ConnectionPadding || + (get_options()->Tor2webMode && + !networkstatus_get_param(NULL, "nf_pad_tor2web", 1, 0, 1)) + || (get_options()->HiddenServiceSingleHopMode && + !networkstatus_get_param(NULL, "nf_pad_single_onion", 1, 0, 1))) { channelpadding_disable_padding_on_channel(chan); } diff --git a/src/or/channelpadding.c b/src/or/channelpadding.c index f5248e896..9a2fdc4bb 100644 --- a/src/or/channelpadding.c +++ b/src/or/channelpadding.c @@ -46,6 +46,10 @@ static int consensus_nf_conntimeout_clients; static int consensus_nf_pad_before_usage; /** Should we pad relay-to-relay connections? */ static int consensus_nf_pad_relays; +/** Should we pad tor2web connections? */ +static int consensus_nf_pad_tor2web; +/** Should we pad rosos connections? */ +static int consensus_nf_pad_single_onion; #define TOR_MSEC_PER_SEC 1000 #define TOR_USEC_PER_MSEC 1000 @@ -130,6 +134,12 @@ channelpadding_new_consensus_params(networkstatus_t *ns) consensus_nf_pad_relays = networkstatus_get_param(ns, "nf_pad_relays", 0, 0, 1); + + consensus_nf_pad_tor2web = + networkstatus_get_param(ns, "nf_pad_tor2web", 1, 0, 1); + + consensus_nf_pad_single_onion = + networkstatus_get_param(ns, "nf_pad_single_onion", 1, 0, 1); } /** @@ -707,6 +717,12 @@ channelpadding_decide_to_pad_channel(channel_t *chan) return CHANNELPADDING_WONTPAD; } + if (options->Tor2webMode && !consensus_nf_pad_tor2web) + return CHANNELPADDING_WONTPAD; + + if (options->HiddenServiceSingleHopMode && !consensus_nf_pad_single_onion) + return CHANNELPADDING_WONTPAD; + if (!chan->has_queued_writes(chan)) { int is_client_channel = 0; diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c index 0a70184f8..99f8880a4 100644 --- a/src/test/test_channelpadding.c +++ b/src/test/test_channelpadding.c @@ -26,6 +26,7 @@ void test_channelpadding_timers(void *arg); void test_channelpadding_consensus(void *arg); void test_channelpadding_negotiation(void *arg); void test_channelpadding_decide_to_pad_channel(void *arg); +void test_channelpadding_killonehop(void *arg); void dummy_nop_timer(void); @@ -111,8 +112,6 @@ setup_fake_connection_for_channel(channel_tls_t *chan) conn->base_.conn_array_index = smartlist_len(connection_array); smartlist_add(connection_array, conn); - connection_or_set_canonical(conn, 1); - conn->chan = chan; chan->conn = conn; @@ -127,6 +126,8 @@ setup_fake_connection_for_channel(channel_tls_t *chan) conn->tls = (tor_tls_t *)((void *)(&fake_tortls)); conn->link_proto = MIN_LINK_PROTO_FOR_CHANNEL_PADDING; + + connection_or_set_canonical(conn, 1); } static channel_tls_t * @@ -166,16 +167,30 @@ free_fake_channeltls(channel_tls_t *chan) } static void -setup_mock_network(void) +setup_mock_consensus(void) { - routerstatus_t *relay; - connection_array = smartlist_new(); - current_md_consensus = current_ns_consensus = tor_malloc_zero(sizeof(networkstatus_t)); current_md_consensus->net_params = smartlist_new(); current_md_consensus->routerstatus_list = smartlist_new(); channelpadding_new_consensus_params(current_md_consensus); +} + +static void +free_mock_consensus(void) +{ + SMARTLIST_FOREACH(current_md_consensus->routerstatus_list, void *, r, + tor_free(r)); + smartlist_free(current_md_consensus->routerstatus_list); + smartlist_free(current_ns_consensus->net_params); + tor_free(current_ns_consensus); +} + +static void +setup_mock_network(void) +{ + routerstatus_t *relay; + connection_array = smartlist_new(); relay1_relay2 = (channel_t*)new_fake_channeltls(2); relay1_relay2->write_cell = mock_channel_write_cell_relay1; @@ -202,6 +217,11 @@ setup_mock_network(void) client_relay3 = (channel_t*)new_fake_channeltls(3); client_relay3->write_cell = mock_channel_write_cell_client; channel_timestamp_active(client_relay3); + + channel_do_open_actions(relay1_relay2); + channel_do_open_actions(relay2_relay1); + channel_do_open_actions(relay3_client); + channel_do_open_actions(client_relay3); } static void @@ -212,12 +232,7 @@ free_mock_network(void) free_fake_channeltls((channel_tls_t*)relay3_client); free_fake_channeltls((channel_tls_t*)client_relay3); - SMARTLIST_FOREACH(current_md_consensus->routerstatus_list, void *, r, - tor_free(r)); - smartlist_free(current_md_consensus->routerstatus_list); - smartlist_free(current_ns_consensus->net_params); smartlist_free(connection_array); - tor_free(current_ns_consensus); } static void @@ -344,6 +359,118 @@ test_channelpadding_timers(void *arg) return; } +void +test_channelpadding_killonehop(void *arg) +{ + channelpadding_decision_t decision; + (void)arg; + tor_libevent_postfork(); + + routerstatus_t *relay = tor_malloc_zero(sizeof(routerstatus_t)); + monotime_init(); + timers_initialize(); + + setup_mock_consensus(); + + /* Do we disable padding if tor2webmode or rsos are enabled, and + * the consensus says don't pad? */ + + /* Ensure we can kill tor2web and rsos padding if we want. */ + // First, test that padding works if either is enabled + smartlist_clear(current_md_consensus->net_params); + channelpadding_new_consensus_params(current_md_consensus); + + setup_mock_network(); + tried_to_write_cell = 0; + get_options_mutable()->Tor2webMode = 1; + client_relay3->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); + tt_assert(client_relay3->pending_padding_callback); + tt_int_op(tried_to_write_cell, OP_EQ, 0); + + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED); + + // Wait for the timer + event_base_loop(tor_libevent_get_base(), 0); + tt_int_op(tried_to_write_cell, OP_EQ, 1); + tt_assert(!client_relay3->pending_padding_callback); + + // Then test disabling each via consensus param + smartlist_add(current_md_consensus->net_params, + (void*)"nf_pad_tor2web=0"); + channelpadding_new_consensus_params(current_md_consensus); + + // Test client side (it should stop immediately) + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD); + tt_assert(!client_relay3->pending_padding_callback); + + // Reset connnections.. XXX: remove this requirement via client + // negotiation + free_mock_network(); + setup_mock_network(); + + // Test relay side (it should have gotten the negotiation to disable) + get_options_mutable()->Tor2webMode = 0; + tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ, + CHANNELPADDING_WONTPAD); + tt_assert(!relay3_client->padding_enabled); + + /* Repeat for SOS */ + // First, test that padding works if either is enabled + smartlist_clear(current_md_consensus->net_params); + channelpadding_new_consensus_params(current_md_consensus); + + // Reset connections + free_mock_network(); + setup_mock_network(); + tried_to_write_cell = 0; + get_options_mutable()->HiddenServiceSingleHopMode = 1; + client_relay3->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); + tt_assert(client_relay3->pending_padding_callback); + tt_int_op(tried_to_write_cell, OP_EQ, 0); + + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_ALREADY_SCHEDULED); + + // Wait for the timer + event_base_loop(tor_libevent_get_base(), 0); + tt_int_op(tried_to_write_cell, OP_EQ, 1); + tt_assert(!client_relay3->pending_padding_callback); + + // Then test disabling each via consensus param + smartlist_add(current_md_consensus->net_params, + (void*)"nf_pad_single_onion=0"); + channelpadding_new_consensus_params(current_md_consensus); + + // Test client side (it should stop immediately) + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD); + tt_assert(!client_relay3->pending_padding_callback); + + // Reset connnections.. XXX: remove this requirement... + free_mock_network(); + setup_mock_network(); + + // Test relay side (it should have gotten the negotiation to disable) + get_options_mutable()->HiddenServiceSingleHopMode = 0; + tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ, + CHANNELPADDING_WONTPAD); + tt_assert(!relay3_client->padding_enabled); + + done: + free_mock_consensus(); + free_mock_network(); + tor_free(relay); + + timers_shutdown(); + channel_free_all(); +} + void test_channelpadding_consensus(void *arg) { @@ -379,11 +506,7 @@ test_channelpadding_consensus(void *arg) chan = (channel_t*)new_fake_channeltls(0); channel_timestamp_active(chan); - current_md_consensus = current_ns_consensus - = tor_malloc_zero(sizeof(networkstatus_t)); - current_md_consensus->net_params = smartlist_new(); - current_md_consensus->routerstatus_list = smartlist_new(); - channelpadding_new_consensus_params(current_md_consensus); + setup_mock_consensus(); get_options_mutable()->ORPort_set = 1; @@ -441,6 +564,7 @@ test_channelpadding_consensus(void *arg) channelpadding_new_consensus_params(current_md_consensus); tried_to_write_cell = 0; + chan->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; decision = channelpadding_decide_to_pad_channel(chan); tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); tt_assert(chan->pending_padding_callback); @@ -547,12 +671,9 @@ test_channelpadding_consensus(void *arg) tt_i64_op(val, OP_LE, 24*60*60*2); done: + free_mock_consensus(); free_fake_channeltls((channel_tls_t*)chan); smartlist_free(connection_array); - smartlist_free(current_md_consensus->routerstatus_list); - smartlist_free(current_ns_consensus->net_params); - tor_free(relay); - tor_free(current_ns_consensus); timers_shutdown(); channel_free_all(); @@ -579,6 +700,7 @@ test_channelpadding_negotiation(void *arg) */ monotime_init(); timers_initialize(); + setup_mock_consensus(); setup_mock_network(); /* Test case #1: Do the right things ignore negotiation? */ @@ -680,6 +802,7 @@ test_channelpadding_negotiation(void *arg) done: free_mock_network(); + free_mock_consensus(); timers_shutdown(); channel_free_all(); @@ -894,6 +1017,7 @@ struct testcase_t channelpadding_tests[] = { TEST_CHANNELPADDING(channelpadding_decide_to_pad_channel, TT_FORK), TEST_CHANNELPADDING(channelpadding_negotiation, TT_FORK), TEST_CHANNELPADDING(channelpadding_consensus, TT_FORK), + TEST_CHANNELPADDING(channelpadding_killonehop, TT_FORK), TEST_CHANNELPADDING(channelpadding_timers, TT_FORK), END_OF_TESTCASES }; From 6d221c8f371a0c1809552b699f1afab8cde3bd31 Mon Sep 17 00:00:00 2001 From: Mike Perry Date: Fri, 23 Jun 2017 18:34:41 -0400 Subject: [PATCH 2/3] Ticket #17857: Apply padding off-switch to existing connections. --- src/or/channel.c | 30 ++++++++++----- src/or/channelpadding.c | 28 +++++++++++--- src/or/channelpadding.h | 5 +++ src/test/test_channelpadding.c | 67 ++++++++++++++++++++++++++-------- 4 files changed, 100 insertions(+), 30 deletions(-) diff --git a/src/or/channel.c b/src/or/channel.c index 8348ffd64..17b2191b7 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -66,6 +66,7 @@ #include "scheduler.h" #include "compat_time.h" #include "networkstatus.h" +#include "rendservice.h" /* Global lists of channels */ @@ -2712,17 +2713,26 @@ channel_do_open_actions(channel_t *chan) /* Disable or reduce padding according to user prefs. */ if (chan->padding_enabled || get_options()->ConnectionPadding == 1) { - if (!get_options()->ConnectionPadding || - (get_options()->Tor2webMode && - !networkstatus_get_param(NULL, "nf_pad_tor2web", 1, 0, 1)) - || (get_options()->HiddenServiceSingleHopMode && - !networkstatus_get_param(NULL, "nf_pad_single_onion", 1, 0, 1))) { + if (!get_options()->ConnectionPadding) { + /* Disable if torrc disabled */ channelpadding_disable_padding_on_channel(chan); - } - - /* Padding can be forced and/or reduced by clients, regardless of if - * the channel supports it */ - if (get_options()->ReducedConnectionPadding) { + } else if (get_options()->Tor2webMode && + !networkstatus_get_param(NULL, + CHANNELPADDING_TOR2WEB_PARAM, + CHANNELPADDING_TOR2WEB_DEFAULT, 0, 1)) { + /* Disable if we're using tor2web and the consensus disabled padding + * for tor2web */ + channelpadding_disable_padding_on_channel(chan); + } else if (rend_service_allow_non_anonymous_connection(get_options()) && + !networkstatus_get_param(NULL, + CHANNELPADDING_SOS_PARAM, + CHANNELPADDING_SOS_DEFAULT, 0, 1)) { + /* Disable if we're using RSOS and the consensus disabled padding + * for RSOS*/ + channelpadding_disable_padding_on_channel(chan); + } else if (get_options()->ReducedConnectionPadding) { + /* Padding can be forced and/or reduced by clients, regardless of if + * the channel supports it */ channelpadding_reduce_padding_on_channel(chan); } } diff --git a/src/or/channelpadding.c b/src/or/channelpadding.c index 9a2fdc4bb..ee6d29f7c 100644 --- a/src/or/channelpadding.c +++ b/src/or/channelpadding.c @@ -21,6 +21,7 @@ #include "router.h" #include "compat_time.h" #include +#include "rendservice.h" STATIC int channelpadding_get_netflow_inactive_timeout_ms(const channel_t *); STATIC int channelpadding_send_disable_command(channel_t *); @@ -136,10 +137,14 @@ channelpadding_new_consensus_params(networkstatus_t *ns) networkstatus_get_param(ns, "nf_pad_relays", 0, 0, 1); consensus_nf_pad_tor2web = - networkstatus_get_param(ns, "nf_pad_tor2web", 1, 0, 1); + networkstatus_get_param(ns, + CHANNELPADDING_TOR2WEB_PARAM, + CHANNELPADDING_TOR2WEB_DEFAULT, 0, 1); consensus_nf_pad_single_onion = - networkstatus_get_param(ns, "nf_pad_single_onion", 1, 0, 1); + networkstatus_get_param(ns, + CHANNELPADDING_SOS_PARAM, + CHANNELPADDING_SOS_DEFAULT, 0, 1); } /** @@ -717,11 +722,24 @@ channelpadding_decide_to_pad_channel(channel_t *chan) return CHANNELPADDING_WONTPAD; } - if (options->Tor2webMode && !consensus_nf_pad_tor2web) - return CHANNELPADDING_WONTPAD; + if (options->Tor2webMode && !consensus_nf_pad_tor2web) { + /* If the consensus just changed values, this channel may still + * think padding is enabled. Negotiate it off. */ + if (chan->padding_enabled) + channelpadding_disable_padding_on_channel(chan); - if (options->HiddenServiceSingleHopMode && !consensus_nf_pad_single_onion) return CHANNELPADDING_WONTPAD; + } + + if (rend_service_allow_non_anonymous_connection(options) && + !consensus_nf_pad_single_onion) { + /* If the consensus just changed values, this channel may still + * think padding is enabled. Negotiate it off. */ + if (chan->padding_enabled) + channelpadding_disable_padding_on_channel(chan); + + return CHANNELPADDING_WONTPAD; + } if (!chan->has_queued_writes(chan)) { int is_client_channel = 0; diff --git a/src/or/channelpadding.h b/src/or/channelpadding.h index 2708ee973..a227e27d5 100644 --- a/src/or/channelpadding.h +++ b/src/or/channelpadding.h @@ -13,6 +13,11 @@ #include "channelpadding_negotiation.h" +#define CHANNELPADDING_TOR2WEB_PARAM "nf_pad_tor2web" +#define CHANNELPADDING_TOR2WEB_DEFAULT 1 +#define CHANNELPADDING_SOS_PARAM "nf_pad_single_onion" +#define CHANNELPADDING_SOS_DEFAULT 1 + typedef enum { CHANNELPADDING_WONTPAD, CHANNELPADDING_PADLATER, diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c index 99f8880a4..998368cf4 100644 --- a/src/test/test_channelpadding.c +++ b/src/test/test_channelpadding.c @@ -371,6 +371,7 @@ test_channelpadding_killonehop(void *arg) timers_initialize(); setup_mock_consensus(); + setup_mock_network(); /* Do we disable padding if tor2webmode or rsos are enabled, and * the consensus says don't pad? */ @@ -380,7 +381,6 @@ test_channelpadding_killonehop(void *arg) smartlist_clear(current_md_consensus->net_params); channelpadding_new_consensus_params(current_md_consensus); - setup_mock_network(); tried_to_write_cell = 0; get_options_mutable()->Tor2webMode = 1; client_relay3->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; @@ -402,17 +402,35 @@ test_channelpadding_killonehop(void *arg) (void*)"nf_pad_tor2web=0"); channelpadding_new_consensus_params(current_md_consensus); - // Test client side (it should stop immediately) - decision = channelpadding_decide_to_pad_channel(client_relay3); - tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD); + // Before the client tries to pad, the relay will still pad: + tried_to_write_cell = 0; + relay3_client->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; + get_options_mutable()->ORPort_set = 1; + get_options_mutable()->Tor2webMode = 0; + decision = channelpadding_decide_to_pad_channel(relay3_client); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); + tt_assert(relay3_client->pending_padding_callback); + + // Wait for the timer + event_base_loop(tor_libevent_get_base(), 0); + tt_int_op(tried_to_write_cell, OP_EQ, 1); tt_assert(!client_relay3->pending_padding_callback); - // Reset connnections.. XXX: remove this requirement via client - // negotiation - free_mock_network(); - setup_mock_network(); + // Test client side (it should stop immediately, but send a negotiate) + tried_to_write_cell = 0; + tt_assert(relay3_client->padding_enabled); + tt_assert(client_relay3->padding_enabled); + get_options_mutable()->Tor2webMode = 1; + /* For the relay to recieve the negotiate: */ + get_options_mutable()->ORPort_set = 1; + decision = channelpadding_decide_to_pad_channel(client_relay3); + tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD); + tt_int_op(tried_to_write_cell, OP_EQ, 1); + tt_assert(!client_relay3->pending_padding_callback); + tt_assert(!relay3_client->padding_enabled); // Test relay side (it should have gotten the negotiation to disable) + get_options_mutable()->ORPort_set = 1; get_options_mutable()->Tor2webMode = 0; tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ, CHANNELPADDING_WONTPAD); @@ -423,11 +441,13 @@ test_channelpadding_killonehop(void *arg) smartlist_clear(current_md_consensus->net_params); channelpadding_new_consensus_params(current_md_consensus); - // Reset connections - free_mock_network(); - setup_mock_network(); + relay3_client->padding_enabled = 1; + client_relay3->padding_enabled = 1; + tried_to_write_cell = 0; + get_options_mutable()->ORPort_set = 0; get_options_mutable()->HiddenServiceSingleHopMode = 1; + get_options_mutable()->HiddenServiceNonAnonymousMode = 1; client_relay3->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; decision = channelpadding_decide_to_pad_channel(client_relay3); tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); @@ -447,17 +467,34 @@ test_channelpadding_killonehop(void *arg) (void*)"nf_pad_single_onion=0"); channelpadding_new_consensus_params(current_md_consensus); + // Before the client tries to pad, the relay will still pad: + tried_to_write_cell = 0; + relay3_client->next_padding_time_ms = monotime_coarse_absolute_msec() + 100; + get_options_mutable()->ORPort_set = 1; + get_options_mutable()->HiddenServiceSingleHopMode = 0; + get_options_mutable()->HiddenServiceNonAnonymousMode = 0; + decision = channelpadding_decide_to_pad_channel(relay3_client); + tt_int_op(decision, OP_EQ, CHANNELPADDING_PADDING_SCHEDULED); + tt_assert(relay3_client->pending_padding_callback); + + // Wait for the timer + event_base_loop(tor_libevent_get_base(), 0); + tt_int_op(tried_to_write_cell, OP_EQ, 1); + tt_assert(!client_relay3->pending_padding_callback); + // Test client side (it should stop immediately) + get_options_mutable()->HiddenServiceSingleHopMode = 1; + get_options_mutable()->HiddenServiceNonAnonymousMode = 1; + /* For the relay to recieve the negotiate: */ + get_options_mutable()->ORPort_set = 1; decision = channelpadding_decide_to_pad_channel(client_relay3); tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD); tt_assert(!client_relay3->pending_padding_callback); - // Reset connnections.. XXX: remove this requirement... - free_mock_network(); - setup_mock_network(); - // Test relay side (it should have gotten the negotiation to disable) + get_options_mutable()->ORPort_set = 1; get_options_mutable()->HiddenServiceSingleHopMode = 0; + get_options_mutable()->HiddenServiceNonAnonymousMode = 0; tt_int_op(channelpadding_decide_to_pad_channel(relay3_client), OP_EQ, CHANNELPADDING_WONTPAD); tt_assert(!relay3_client->padding_enabled); From 6689c95d061d440ca16369583dac066cc35a6807 Mon Sep 17 00:00:00 2001 From: Mike Perry Date: Fri, 23 Jun 2017 18:44:00 -0400 Subject: [PATCH 3/3] Changes file for #17857. --- changes/bug17857 | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changes/bug17857 diff --git a/changes/bug17857 b/changes/bug17857 new file mode 100644 index 000000000..6c8863823 --- /dev/null +++ b/changes/bug17857 @@ -0,0 +1,6 @@ + o Minor features (defensive programming): + - Create a pair of consensus parameters nf_pad_tor2web and + nf_pad_single_onion that allow us to disable netflow padding in the + consensus for non-anonymous connections, in case the overhead is high. + Closes #17857. +