From fc542167cb568fc3805275e2405990423cf87e3b Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 8 Oct 2021 11:14:53 -0400 Subject: [PATCH 1/3] Implement a MiddleOnly flag for vote generation. This proposal implements part of Prop335; it's based on a patch from Neel Chauhan. When configured to do so, authorities will assign a MiddleOnly flag to certain relays. Any relay which an authority gives this flag will not get Exit, V2Dir, Guard, or HSDir, and might get BadExit if the authority votes for that one. --- src/app/config/config.c | 3 +++ src/app/config/or_options_st.h | 4 ++++ src/core/or/policies.c | 22 ++++++++++++++++++++++ src/core/or/policies.h | 1 + src/feature/dirauth/dirauth_options.inc | 4 ++++ src/feature/dirauth/dirvote.c | 11 ++++++++--- src/feature/dirauth/process_descs.c | 15 +++++++++++++++ src/feature/dirauth/process_descs.h | 3 ++- src/feature/dirauth/voteflags.c | 11 ++++++++++- src/feature/dirauth/voteflags.h | 3 ++- src/feature/dirparse/ns_parse.c | 2 ++ src/feature/nodelist/fmt_routerstatus.c | 3 ++- src/feature/nodelist/node_st.h | 2 ++ src/feature/nodelist/routerstatus_st.h | 2 ++ src/test/test_voting_flags.c | 3 ++- 15 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/app/config/config.c b/src/app/config/config.c index 15b4585954..8df5275cc6 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -193,6 +193,7 @@ static const config_abbrev_t option_abbrevs_[] = { PLURAL(AuthDirBadDirCC), PLURAL(AuthDirBadExitCC), PLURAL(AuthDirInvalidCC), + PLURAL(AuthDirMiddleOnlyCC), PLURAL(AuthDirRejectCC), PLURAL(EntryNode), PLURAL(ExcludeNode), @@ -331,6 +332,8 @@ static const config_var_t option_vars_[] = { V(AuthDirBadExitCCs, CSV, ""), V(AuthDirInvalid, LINELIST, NULL), V(AuthDirInvalidCCs, CSV, ""), + V(AuthDirMiddleOnly, LINELIST, NULL), + V(AuthDirMiddleOnlyCCs, CSV, ""), V(AuthDirReject, LINELIST, NULL), V(AuthDirRejectCCs, CSV, ""), OBSOLETE("AuthDirRejectUnlisted"), diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h index 812fa92cae..3a1acad044 100644 --- a/src/app/config/or_options_st.h +++ b/src/app/config/or_options_st.h @@ -499,6 +499,9 @@ struct or_options_t { struct smartlist_t *NodeFamilySets; struct config_line_t *AuthDirBadExit; /**< Address policy for descriptors to * mark as bad exits. */ + /** Address policy for descriptors to mark as only suitable for the + * middle position in circuits. */ + struct config_line_t *AuthDirMiddleOnly; struct config_line_t *AuthDirReject; /**< Address policy for descriptors to * reject. */ struct config_line_t *AuthDirInvalid; /**< Address policy for descriptors to @@ -512,6 +515,7 @@ struct or_options_t { */ struct smartlist_t *AuthDirBadExitCCs; struct smartlist_t *AuthDirInvalidCCs; + struct smartlist_t *AuthDirMiddleOnlyCCs; struct smartlist_t *AuthDirRejectCCs; /**@}*/ diff --git a/src/core/or/policies.c b/src/core/or/policies.c index f91c23ad31..a53849b4d0 100644 --- a/src/core/or/policies.c +++ b/src/core/or/policies.c @@ -59,6 +59,9 @@ static smartlist_t *authdir_invalid_policy = NULL; /** Policy that addresses for incoming router descriptors must not * match in order to not be marked as BadExit. */ static smartlist_t *authdir_badexit_policy = NULL; +/** Policy that addresses for incoming router descriptors must not + * match in order to not be marked as MiddleOnly. */ +static smartlist_t *authdir_middleonly_policy = NULL; /** Parsed addr_policy_t describing which addresses we believe we can start * circuits at. */ @@ -1119,6 +1122,17 @@ authdir_policy_badexit_address(const tor_addr_t *addr, uint16_t port) return addr_is_in_cc_list(addr, get_options()->AuthDirBadExitCCs); } +/** Return 1 if addr:port should be marked as MiddleOnly, + * based on authdir_middleonly_policy. Else return 0. + */ +int +authdir_policy_middleonly_address(const tor_addr_t *addr, uint16_t port) +{ + if (!addr_policy_permits_tor_addr(addr, port, authdir_middleonly_policy)) + return 1; + return addr_is_in_cc_list(addr, get_options()->AuthDirMiddleOnlyCCs); +} + #define REJECT(arg) \ STMT_BEGIN *msg = tor_strdup(arg); goto err; STMT_END @@ -1173,6 +1187,9 @@ validate_addr_policies(const or_options_t *options, char **msg) if (parse_addr_policy(options->AuthDirBadExit, &addr_policy, ADDR_POLICY_REJECT)) REJECT("Error in AuthDirBadExit entry."); + if (parse_addr_policy(options->AuthDirMiddleOnly, &addr_policy, + ADDR_POLICY_REJECT)) + REJECT("Error in AuthDirMiddleOnly entry."); if (parse_addr_policy(options->ReachableAddresses, &addr_policy, ADDR_POLICY_ACCEPT)) @@ -1266,6 +1283,9 @@ policies_parse_from_options(const or_options_t *options) if (load_policy_from_option(options->AuthDirBadExit, "AuthDirBadExit", &authdir_badexit_policy, ADDR_POLICY_REJECT) < 0) ret = -1; + if (load_policy_from_option(options->AuthDirMiddleOnly, "AuthDirMiddleOnly", + &authdir_middleonly_policy, ADDR_POLICY_REJECT) < 0) + ret = -1; if (parse_metrics_port_policy(options) < 0) { ret = -1; } @@ -3112,6 +3132,8 @@ policies_free_all(void) authdir_invalid_policy = NULL; addr_policy_list_free(authdir_badexit_policy); authdir_badexit_policy = NULL; + addr_policy_list_free(authdir_middleonly_policy); + authdir_middleonly_policy = NULL; if (!HT_EMPTY(&policy_root)) { policy_map_ent_t **ent; diff --git a/src/core/or/policies.h b/src/core/or/policies.h index a32f50ab1d..e11e1d0ff5 100644 --- a/src/core/or/policies.h +++ b/src/core/or/policies.h @@ -106,6 +106,7 @@ int metrics_policy_permits_address(const tor_addr_t *addr); int authdir_policy_permits_address(const tor_addr_t *addr, uint16_t port); int authdir_policy_valid_address(const tor_addr_t *addr, uint16_t port); int authdir_policy_badexit_address(const tor_addr_t *addr, uint16_t port); +int authdir_policy_middleonly_address(const tor_addr_t *addr, uint16_t port); int validate_addr_policies(const or_options_t *options, char **msg); void policy_expand_private(smartlist_t **policy); diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc index 05726b8c2f..968f8e6c3d 100644 --- a/src/feature/dirauth/dirauth_options.inc +++ b/src/feature/dirauth/dirauth_options.inc @@ -27,6 +27,10 @@ CONF_VAR(AuthDirHasIPv6Connectivity, BOOL, 0, "0") * good. */ CONF_VAR(AuthDirListBadExits, BOOL, 0, "0") +/** True iff we should list middle-only relays, and vote for all other + * relays as possibly suitable for other positions. */ +CONF_VAR(AuthDirListMiddleOnly, BOOL, 0, "0") + /** Do not permit more than this number of servers per IP address. */ CONF_VAR(AuthDirMaxServersPerAddr, POSINT, 0, "2") diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c index ffaa78b997..4f8cf2b8e6 100644 --- a/src/feature/dirauth/dirvote.c +++ b/src/feature/dirauth/dirvote.c @@ -4581,6 +4581,7 @@ const char DIRVOTE_UNIVERSAL_FLAGS[] = * depending on our configuration. */ const char DIRVOTE_OPTIONAL_FLAGS[] = "BadExit " + "MiddleOnly " "Running"; /** Return a new networkstatus_t* containing our current opinion. (For v3 @@ -4598,7 +4599,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, smartlist_t *routers, *routerstatuses; char identity_digest[DIGEST_LEN]; char signing_key_digest[DIGEST_LEN]; - const int listbadexits = d_options->AuthDirListBadExits; + const int list_bad_exits = d_options->AuthDirListBadExits; + const int list_middle_only = d_options->AuthDirListMiddleOnly; routerlist_t *rl = router_get_routerlist(); time_t now = time(NULL); time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; @@ -4703,7 +4705,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); rs = &vrs->status; dirauth_set_routerstatus_from_routerinfo(rs, node, ri, now, - listbadexits); + list_bad_exits, + list_middle_only); if (ri->cache_info.signing_key_cert) { memcpy(vrs->ed25519_id, @@ -4827,8 +4830,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); if (vote_on_reachability) smartlist_add_strdup(v3_out->known_flags, "Running"); - if (listbadexits) + if (list_bad_exits) smartlist_add_strdup(v3_out->known_flags, "BadExit"); + if (list_middle_only) + smartlist_add_strdup(v3_out->known_flags, "MiddleOnly"); smartlist_sort_strings(v3_out->known_flags); if (d_options->ConsensusParams) { diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c index eca987b8b5..db4eca5329 100644 --- a/src/feature/dirauth/process_descs.c +++ b/src/feature/dirauth/process_descs.c @@ -226,6 +226,8 @@ dirserv_load_fingerprint_file(void) add_status = RTR_BADEXIT; } else if (!strcasecmp(nickname, "!invalid")) { add_status = RTR_INVALID; + } else if (!strcasecmp(nickname, "!middleonly")) { + add_status = RTR_MIDDLEONLY; } /* Check if fingerprint is RSA or ed25519 by verifying it. */ @@ -496,6 +498,13 @@ dirserv_get_status_impl(const char *id_digest, result |= RTR_BADEXIT; } + if (authdir_policy_middleonly_address(ipv4_addr, ipv4_orport)) { + log_fn(severity, LD_DIRSERV, + "Marking '%s' as middle-only because of address '%s'", + nickname, fmt_addr(ipv4_addr)); + result |= RTR_MIDDLEONLY; + } + if (!authdir_policy_permits_address(ipv4_addr, ipv4_orport)) { log_fn(severity, LD_DIRSERV, "Rejecting '%s' because of address '%s'", nickname, fmt_addr(ipv4_addr)); @@ -630,6 +639,7 @@ dirserv_set_node_flags_from_authoritative_status(node_t *node, { node->is_valid = (authstatus & RTR_INVALID) ? 0 : 1; node->is_bad_exit = (authstatus & RTR_BADEXIT) ? 1 : 0; + node->is_middle_only = (authstatus & RTR_MIDDLEONLY) ? 1 : 0; } /** True iff a is more severe than b. */ @@ -963,6 +973,11 @@ directory_remove_invalid(void) (r & RTR_BADEXIT) ? "bad" : "good"); node->is_bad_exit = (r&RTR_BADEXIT) ? 1: 0; } + if (bool_neq((r & RTR_MIDDLEONLY), node->is_middle_only)) { + log_info(LD_DIRSERV, "Router '%s' is now %smiddle-only", description, + (r & RTR_MIDDLEONLY) ? "" : "not"); + node->is_middle_only = (r&RTR_MIDDLEONLY) ? 1: 0; + } } SMARTLIST_FOREACH_END(node); routerlist_assert_ok(rl); diff --git a/src/feature/dirauth/process_descs.h b/src/feature/dirauth/process_descs.h index 6c056d11dd..a509eb1fbe 100644 --- a/src/feature/dirauth/process_descs.h +++ b/src/feature/dirauth/process_descs.h @@ -45,7 +45,8 @@ typedef struct authdir_config_t { #define RTR_REJECT 4 /**< We will not publish this router. */ /* 8 Historically used to avoid using this as a dir. */ #define RTR_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */ -/* 32 Historically used to indicade Unnamed */ +/** We'll vote to only use this router as a midpoint. */ +#define RTR_MIDDLEONLY 32 #endif /* defined(PROCESS_DESCS_PRIVATE) || defined(TOR_UNIT_TESTS) */ diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c index d755a270be..05c19ff501 100644 --- a/src/feature/dirauth/voteflags.c +++ b/src/feature/dirauth/voteflags.c @@ -565,7 +565,8 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs, node_t *node, const routerinfo_t *ri, time_t now, - int listbadexits) + int listbadexits, + int listmiddleonly) { const or_options_t *options = get_options(); uint32_t routerbw_kb = dirserv_get_credible_bandwidth_kb(ri); @@ -597,6 +598,14 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs, /* Override rs->is_bad_exit */ rs->is_bad_exit = listbadexits && node->is_bad_exit; + /* Override rs->is_middle_only and related flags. */ + rs->is_middle_only = listmiddleonly && node->is_middle_only; + if (rs->is_middle_only) { + if (listbadexits) + rs->is_bad_exit = 1; + rs->is_exit = rs->is_possible_guard = rs->is_hs_dir = rs->is_v2_dir = 0; + } + /* Set rs->is_staledesc. */ rs->is_staledesc = (ri->cache_info.published_on + DESC_IS_STALE_INTERVAL) < now; diff --git a/src/feature/dirauth/voteflags.h b/src/feature/dirauth/voteflags.h index 818a0bafd2..8371f1c315 100644 --- a/src/feature/dirauth/voteflags.h +++ b/src/feature/dirauth/voteflags.h @@ -22,7 +22,8 @@ void dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs, node_t *node, const routerinfo_t *ri, time_t now, - int listbadexits); + int listbadexits, + int listmiddleonly); void dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil); #endif /* defined(HAVE_MODULE_DIRAUTH) */ diff --git a/src/feature/dirparse/ns_parse.c b/src/feature/dirparse/ns_parse.c index 947b3810a4..cd3e2731be 100644 --- a/src/feature/dirparse/ns_parse.c +++ b/src/feature/dirparse/ns_parse.c @@ -434,6 +434,8 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->is_possible_guard = 1; else if (!strcmp(tok->args[i], "BadExit")) rs->is_bad_exit = 1; + else if (!strcmp(tok->args[i], "MiddleOnly")) + rs->is_middle_only = 1; else if (!strcmp(tok->args[i], "Authority")) rs->is_authority = 1; else if (!strcmp(tok->args[i], "Unnamed") && diff --git a/src/feature/nodelist/fmt_routerstatus.c b/src/feature/nodelist/fmt_routerstatus.c index 6db40c0b68..95379a7721 100644 --- a/src/feature/nodelist/fmt_routerstatus.c +++ b/src/feature/nodelist/fmt_routerstatus.c @@ -87,7 +87,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, goto done; smartlist_add_asprintf(chunks, - "s%s%s%s%s%s%s%s%s%s%s%s%s\n", + "s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", /* These must stay in alphabetical order. */ rs->is_authority?" Authority":"", rs->is_bad_exit?" BadExit":"", @@ -95,6 +95,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, rs->is_fast?" Fast":"", rs->is_possible_guard?" Guard":"", rs->is_hs_dir?" HSDir":"", + rs->is_middle_only?" MiddleOnly":"", rs->is_flagged_running?" Running":"", rs->is_stable?" Stable":"", rs->is_staledesc?" StaleDesc":"", diff --git a/src/feature/nodelist/node_st.h b/src/feature/nodelist/node_st.h index b15e7154c4..df67a47ada 100644 --- a/src/feature/nodelist/node_st.h +++ b/src/feature/nodelist/node_st.h @@ -70,6 +70,8 @@ struct node_t { unsigned int is_exit:1; /**< Do we think this is an OK exit? */ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked, * or otherwise nasty? */ + /** Is this unsuitable for use as anything besides a middle relay? */ + unsigned int is_middle_only:1; unsigned int is_hs_dir:1; /**< True iff this router is a hidden service * directory according to the authorities. */ diff --git a/src/feature/nodelist/routerstatus_st.h b/src/feature/nodelist/routerstatus_st.h index 46ff0bdeac..55b76de581 100644 --- a/src/feature/nodelist/routerstatus_st.h +++ b/src/feature/nodelist/routerstatus_st.h @@ -51,6 +51,8 @@ struct routerstatus_t { * choice as an entry guard. */ unsigned int is_bad_exit:1; /**< True iff this node is a bad choice for * an exit node. */ + unsigned int is_middle_only:1; /**< True iff this node is marked as bad + * for anything besides middle positions. */ unsigned int is_hs_dir:1; /**< True iff this router is a v2-or-later hidden * service directory. */ unsigned int is_v2_dir:1; /** True iff this router publishes an open DirPort diff --git a/src/test/test_voting_flags.c b/src/test/test_voting_flags.c index 4c5f3a3270..457b0fa796 100644 --- a/src/test/test_voting_flags.c +++ b/src/test/test_voting_flags.c @@ -62,7 +62,8 @@ check_result(flag_vote_test_cfg_t *c) bool result = false; routerstatus_t rs; memset(&rs, 0, sizeof(rs)); - dirauth_set_routerstatus_from_routerinfo(&rs, &c->node, &c->ri, c->now, 0); + dirauth_set_routerstatus_from_routerinfo(&rs, &c->node, &c->ri, c->now, + 0, 0); tt_i64_op(rs.published_on, OP_EQ, c->expected.published_on); tt_str_op(rs.nickname, OP_EQ, c->expected.nickname); From ab26475cabff49767c1b301371d81478695b5943 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 8 Oct 2021 11:36:04 -0400 Subject: [PATCH 2/3] Add a new consensus method to handle MiddleOnly specially. When this method is in place, then any relay which is assigned MiddleOnly has Exit, V2Dir, Guard, and HSDir cleared (and has BadExit set if appropriate). --- src/feature/dirauth/dirvote.c | 41 +++++++++++++++++++++++++++++++++-- src/feature/dirauth/dirvote.h | 6 ++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c index 4f8cf2b8e6..9c13f762e2 100644 --- a/src/feature/dirauth/dirvote.c +++ b/src/feature/dirauth/dirvote.c @@ -1479,6 +1479,21 @@ compute_nth_protocol_set(int n, int n_voters, const smartlist_t *votes) return result; } +/** Helper: Takes a smartlist of `const char *` flags, and a flag to remove. + * + * Removes that flag if it is present in the list. Doesn't free it. + */ +static void +remove_flag(smartlist_t *sl, const char *flag) +{ + /* We can't use smartlist_string_remove() here, since that doesn't preserve + * order, and since it frees elements from the string. */ + + int idx = smartlist_string_pos(sl, flag); + if (idx >= 0) + smartlist_del_keeporder(sl, idx); +} + /** Given a list of vote networkstatus_t in votes, our public * authority identity_key, our private authority signing_key, * and the number of total_authorities that we believe exist in our @@ -1633,6 +1648,9 @@ networkstatus_compute_consensus(smartlist_t *votes, tor_free(votesec_list); tor_free(distsec_list); } + // True if anybody is voting on the BadExit flag. + const bool badexit_flag_is_listed = + smartlist_contains_string(flags, "BadExit"); chunks = smartlist_new(); @@ -1924,7 +1942,7 @@ networkstatus_compute_consensus(smartlist_t *votes, const char *chosen_name = NULL; int exitsummary_disagreement = 0; int is_named = 0, is_unnamed = 0, is_running = 0, is_valid = 0; - int is_guard = 0, is_exit = 0, is_bad_exit = 0; + int is_guard = 0, is_exit = 0, is_bad_exit = 0, is_middle_only = 0; int naming_conflict = 0; int n_listing = 0; char microdesc_digest[DIGEST256_LEN]; @@ -2055,7 +2073,6 @@ networkstatus_compute_consensus(smartlist_t *votes, } /* Set the flags. */ - smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */ SMARTLIST_FOREACH_BEGIN(flags, const char *, fl) { if (!strcmp(fl, "Named")) { if (is_named) @@ -2077,6 +2094,8 @@ networkstatus_compute_consensus(smartlist_t *votes, is_running = 1; else if (!strcmp(fl, "BadExit")) is_bad_exit = 1; + else if (!strcmp(fl, "MiddleOnly")) + is_middle_only = 1; else if (!strcmp(fl, "Valid")) is_valid = 1; } @@ -2093,6 +2112,22 @@ networkstatus_compute_consensus(smartlist_t *votes, if (!is_valid) continue; + /* Starting with consensus method 32, we handle the middle-only + * flag specially: when it is present, we clear some flags, and + * set others. */ + if (is_middle_only && consensus_method >= MIN_METHOD_FOR_MIDDLEONLY) { + remove_flag(chosen_flags, "Exit"); + remove_flag(chosen_flags, "V2Dir"); + remove_flag(chosen_flags, "Guard"); + remove_flag(chosen_flags, "HSDir"); + is_exit = is_guard = 0; + if (! is_bad_exit && badexit_flag_is_listed) { + is_bad_exit = 1; + smartlist_add(chosen_flags, (char *)"BadExit"); + smartlist_sort_strings(chosen_flags); // restore order. + } + } + /* Pick the version. */ if (smartlist_len(versions)) { sort_version_list(versions, 0); @@ -2253,6 +2288,8 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_add_asprintf(chunks, "m %s\n", m); } /* Next line is all flags. The "\n" is missing. */ + smartlist_add_asprintf(chunks, "s%s", + smartlist_len(chosen_flags)?" ":""); smartlist_add(chunks, smartlist_join_strings(chosen_flags, " ", 0, NULL)); /* Now the version line. */ diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h index d6a2d9cc75..9cb7fe1694 100644 --- a/src/feature/dirauth/dirvote.h +++ b/src/feature/dirauth/dirvote.h @@ -53,7 +53,7 @@ #define MIN_SUPPORTED_CONSENSUS_METHOD 28 /** The highest consensus method that we currently support. */ -#define MAX_SUPPORTED_CONSENSUS_METHOD 31 +#define MAX_SUPPORTED_CONSENSUS_METHOD 32 /** * Lowest consensus method where microdescriptor lines are put in canonical @@ -70,6 +70,10 @@ */ #define MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE 31 +/** Lowest consensus method for which we handle the MiddleOnly flag specially. + */ +#define MIN_METHOD_FOR_MIDDLEONLY 32 + /** Default bandwidth to clip unmeasured bandwidths to using method >= * MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not * get confused with the above macros.) */ From 54ab43d05e67984bda5661cb9530ad8a0b1e2a7a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 8 Oct 2021 11:42:55 -0400 Subject: [PATCH 3/3] Prop335: Changes file and manual entries. Closes #40448. --- changes/prop335 | 11 +++++++++++ doc/man/tor.1.txt | 29 ++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 changes/prop335 diff --git a/changes/prop335 b/changes/prop335 new file mode 100644 index 0000000000..4fa61ca2e9 --- /dev/null +++ b/changes/prop335 @@ -0,0 +1,11 @@ + o Major features (directory authority): + - Authorities can now be configured to label relays as "MiddleOnly". + When voting for this flag, authorities automatically vote against + Exit, Guard, HSDir, and V2Dir; and in favor of BadExit. + Implements part of proposal 335. Based on a patch from Neel + Chauhan. + - Add a new consensus method to handle MiddleOnly specially. When + enough authorities are using this method, then any relay + tagged with the MiddleOnly flag will have its Exit, Guard, HSDir, + and V2Dir flags automatically cleared, and will have its BadExit flag + automatically set. Implements part of proposal 335. diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt index 551ead7533..149d35b018 100644 --- a/doc/man/tor.1.txt +++ b/doc/man/tor.1.txt @@ -3025,6 +3025,11 @@ on the public Tor network. is the same as for exit policies, except that you don't need to say "accept" or "reject", and ports are not needed.) +[[AuthDirMiddleOnly]] **AuthMiddleOnly** __AddressPattern...__:: + Authoritative directories only. A set of address patterns for servers that + will be listed as middle-only in any network status document this authority + publishes, if **AuthDirListMiddleOnly** is set. + + [[AuthDirFastGuarantee]] **AuthDirFastGuarantee** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**:: Authoritative directories only. If non-zero, always vote the Fast flag for any relay advertising this amount of capacity or @@ -3072,6 +3077,13 @@ on the public Tor network. 1 unless you plan to list non-functioning exits as bad; otherwise, you are effectively voting in favor of every declared exit as an exit.) +[[AuthDirListMiddleOnly]] **AuthDirListMiddleOnly** **0**|**1**:: + Authoritative directories only. If set to 1, this directory has some + opinion about which nodes should only be used in the middle position. + (Do not set this to 1 unless you plan to list questionable relays + as "middle only"; otherwise, you are effectively voting _against_ + middle-only status for every relay.) + [[AuthDirMaxServersPerAddr]] **AuthDirMaxServersPerAddr** __NUM__:: Authoritative directories only. The maximum number of servers that we will list as acceptable on a single IP address. Set this to "0" for "no limit". @@ -3090,18 +3102,20 @@ on the public Tor network. authority publishes, or accepted as an OR address in any descriptor submitted for publication by this authority. +[[AuthDirRejectRequestsUnderLoad]] **AuthDirRejectRequestsUnderLoad** **0**|**1**:: + If set, the directory authority will start rejecting directory requests + from non relay connections by sending a 503 error code if it is under + bandwidth pressure (reaching the configured limit if any). Relays will + always tried to be answered even if this is on. (Default: 1) + //Out of order because it logically belongs with the other CCs options. [[AuthDirBadExitCCs]] **AuthDirBadExitCCs** __CC__,... + //Out of order because it logically belongs with the other CCs options. [[AuthDirInvalidCCs]] **AuthDirInvalidCCs** __CC__,... + - -[[AuthDirRejectRequestsUnderLoad]] **AuthDirRejectRequestsUnderLoad** **0**|**1**:: - If set, the directory authority will start rejecting directory requests - from non relay connections by sending a 503 error code if it is under - bandwidth pressure (reaching the configured limit if any). Relays will - always tried to be answered even if this is on. (Default: 1) +//Out of order because it logically belongs with the other CCs options. +[[AuthDirMiddleOnlytCCs]] **AuthDirMiddleOnlyCCs** __CC__,... + [[AuthDirRejectCCs]] **AuthDirRejectCCs** __CC__,...:: Authoritative directories only. These options contain a comma-separated @@ -3847,7 +3861,8 @@ __DataDirectory__/**`approved-routers`**:: descriptors are accepted, but marked in the vote as not valid. If it is **!badexit**, then the authority will vote for it to receive a BadExit flag, indicating that it shouldn't be used for traffic leaving - the Tor network. + the Tor network. If it is **!middleonly**, then the authority will + vote for it to only be used in the middle of circuits. (Neither rejected nor invalid relays are included in the consensus.) __DataDirectory__/**`v3-status-votes`**::