diff options
-rw-r--r-- | changes/ticket40652 | 10 | ||||
-rw-r--r-- | doc/man/tor.1.txt | 26 | ||||
-rw-r--r-- | src/feature/dirauth/dirauth_config.c | 5 | ||||
-rw-r--r-- | src/feature/dirauth/dirauth_options.inc | 25 | ||||
-rw-r--r-- | src/feature/dirauth/voteflags.c | 56 |
5 files changed, 95 insertions, 27 deletions
diff --git a/changes/ticket40652 b/changes/ticket40652 new file mode 100644 index 0000000000..ff9f4d0591 --- /dev/null +++ b/changes/ticket40652 @@ -0,0 +1,10 @@ + o Minor features (dirauth): + - Add an AuthDirVoteGuard torrc option that can allow authorities to + assign the Guard flag to the given fingerprints/country code/IPs. This + is a needed feature mostly for defense purposes in case a DoS hits the + network and relay start losing the Guard flags too fast. + - Make UPTIME_TO_GUARANTEE_STABLE, MTBF_TO_GUARANTEE_STABLE, + TIME_KNOWN_TO_GUARANTEE_FAMILIAR WFU_TO_GUARANTEE_GUARD tunable from + torrc. + - Add a torrc option to control the Guard flag bandwidth threshold + percentile. Closes ticket 40652. diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt index 59a9ddc714..712988fa5a 100644 --- a/doc/man/tor.1.txt +++ b/doc/man/tor.1.txt @@ -3229,6 +3229,32 @@ on the public Tor network. If set to 0, we vote Running for every relay, and don't perform these tests. (Default: 1) +[[AuthDirVoteGuard]] **AuthDirVoteGuard** __node__,__node__,__...__:: + A list of identity fingerprints or country codes or address patterns of + nodes to vote Guard for regardless of their uptime and bandwidth. See + <<ExcludeNodes,ExcludeNodes>> for more information on how to specify nodes. + +[[AuthDirVoteGuardBwThresholdFraction]] **AuthDirVoteGuardBwThresholdFraction** __FRACTION__:: + The Guard flag bandwidth performance threshold fraction that is the + fraction representing who gets the Guard flag out of all measured + bandwidth. (Default: 0.75) + +[[AuthDirVoteGuardGuaranteeTimeKnown]] **AuthDirVoteGuardGuaranteeTimeKnown** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**:: + A relay with at least this much weighted time known can be considered + familiar enough to be a guard. (Default: 8 days) + +[[AuthDirVoteGuardGuaranteeWFU]] **AuthDirVoteGuardGuaranteeWFU** __FRACTION__:: + A level of weighted fractional uptime (WFU) is that is sufficient to be a + Guard. (Default: 0.98) + +[[AuthDirVoteStableGuaranteeMinUptime]] **AuthDirVoteStableGuaranteeMinUptime** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**:: + If a relay's uptime is at least this value, then it is always considered + stable, regardless of the rest of the network. (Default: 30 days) + +[[AuthDirVoteStableGuaranteeMTBF]] **AuthDirVoteStableGuaranteeMTBF** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**:: + If a relay's mean time between failures (MTBF) is least this value, then + it will always be considered stable. (Default: 5 days) + [[BridgePassword]] **BridgePassword** __Password__:: If set, contains an HTTP authenticator that tells a bridge authority to serve all requested bridge information. Used by the (only partially diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c index 53c9f9f781..f98513ef75 100644 --- a/src/feature/dirauth/dirauth_config.c +++ b/src/feature/dirauth/dirauth_config.c @@ -434,6 +434,11 @@ dirauth_options_validate(const void *arg, char **msg) "Recommended*Versions."); } + if (options->AuthDirVoteGuardBwThresholdFraction > 1.0 || + options->AuthDirVoteGuardBwThresholdFraction < 0.0) { + REJECT("Guard bandwdith threshold fraction is invalid."); + } + char *t; /* Call these functions to produce warnings only. */ t = format_recommended_version_list(options->RecommendedClientVersions, 1); diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc index 4fd07a8859..7ee0201e1a 100644 --- a/src/feature/dirauth/dirauth_options.inc +++ b/src/feature/dirauth/dirauth_options.inc @@ -76,6 +76,31 @@ CONF_VAR(RecommendedClientVersions, LINELIST, 0, NULL) /** Which versions of tor should we tell users to run on relays? */ CONF_VAR(RecommendedServerVersions, LINELIST, 0, NULL) +/** Relays which should be voted Guard regardless of uptime and bandwidth. */ +CONF_VAR(AuthDirVoteGuard, ROUTERSET, 0, NULL) + +/** If a relay's uptime is at least this value, then it is always considered + * stable, regardless of the rest of the network. This way we resist attacks + * where an attacker doubles the size of the network using allegedly + * high-uptime nodes, displacing all the current guards. */ +CONF_VAR(AuthDirVoteStableGuaranteeMinUptime, INTERVAL, 0, "30 days") + +/** If a relay's MTBF is at least this value, then it is always stable. See + * above. */ +CONF_VAR(AuthDirVoteStableGuaranteeMTBF, INTERVAL, 0, "5 days") + +/** A relay with at least this much weighted time known can be considered + * familiar enough to be a guard. */ +CONF_VAR(AuthDirVoteGuardGuaranteeTimeKnown, INTERVAL, 0, "8 days") + +/** A relay with sufficient WFU is around enough to be a guard. */ +CONF_VAR(AuthDirVoteGuardGuaranteeWFU, DOUBLE, 0, "0.98") + +/** The Guard flag bandwidth performance threshold fraction that is the + * fraction representing who gets the Guard flag out of all measured + * bandwidth. */ +CONF_VAR(AuthDirVoteGuardBwThresholdFraction, DOUBLE, 0, "0.75") + /** If an authority has been around for less than this amount of time, it * does not believe its reachability information is accurate. Only * altered on testing networks. */ diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c index 9aefc6c5b4..71ee03e265 100644 --- a/src/feature/dirauth/voteflags.c +++ b/src/feature/dirauth/voteflags.c @@ -36,24 +36,6 @@ #include "lib/container/order.h" -/** If a router's uptime is at least this value, then it is always - * considered stable, regardless of the rest of the network. This - * way we resist attacks where an attacker doubles the size of the - * network using allegedly high-uptime nodes, displacing all the - * current guards. */ -#define UPTIME_TO_GUARANTEE_STABLE (3600*24*30) -/** If a router's MTBF is at least this value, then it is always stable. - * See above. (Corresponds to about 7 days for current decay rates.) */ -#define MTBF_TO_GUARANTEE_STABLE (60*60*24*5) -/** Similarly, every node with at least this much weighted time known can be - * considered familiar enough to be a guard. Corresponds to about 20 days for - * current decay rates. - */ -#define TIME_KNOWN_TO_GUARANTEE_FAMILIAR (8*24*60*60) -/** Similarly, every node with sufficient WFU is around enough to be a guard. - */ -#define WFU_TO_GUARANTEE_GUARD (0.98) - /* Thresholds for server performance: set by * dirserv_compute_performance_thresholds, and used by * generate_v2_networkstatus */ @@ -111,13 +93,13 @@ dirserv_thinks_router_is_unreliable(time_t now, */ long uptime = real_uptime(router, now); if ((unsigned)uptime < stable_uptime && - (unsigned)uptime < UPTIME_TO_GUARANTEE_STABLE) + uptime < dirauth_get_options()->AuthDirVoteStableGuaranteeMinUptime) return 1; } else { double mtbf = rep_hist_get_stability(router->cache_info.identity_digest, now); if (mtbf < stable_mtbf && - mtbf < MTBF_TO_GUARANTEE_STABLE) + mtbf < dirauth_get_options()->AuthDirVoteStableGuaranteeMTBF) return 1; } } @@ -325,13 +307,15 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil) /* (Now bandwidths is sorted.) */ if (fast_bandwidth_kb < RELAY_REQUIRED_MIN_BANDWIDTH/(2 * 1000)) fast_bandwidth_kb = bandwidths_kb[n_active/4]; + int nth = (int)(n_active * + dirauth_options->AuthDirVoteGuardBwThresholdFraction); guard_bandwidth_including_exits_kb = - third_quartile_uint32(bandwidths_kb, n_active); + find_nth_uint32(bandwidths_kb, n_active, nth); guard_tk = find_nth_long(tks, n_active, n_active/8); } - if (guard_tk > TIME_KNOWN_TO_GUARANTEE_FAMILIAR) - guard_tk = TIME_KNOWN_TO_GUARANTEE_FAMILIAR; + if (guard_tk > dirauth_options->AuthDirVoteGuardGuaranteeTimeKnown) + guard_tk = dirauth_options->AuthDirVoteGuardGuaranteeTimeKnown; { /* We can vote on a parameter for the minimum and maximum. */ @@ -379,15 +363,16 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil) } SMARTLIST_FOREACH_END(node); if (n_familiar) guard_wfu = median_double(wfus, n_familiar); - if (guard_wfu > WFU_TO_GUARANTEE_GUARD) - guard_wfu = WFU_TO_GUARANTEE_GUARD; + if (guard_wfu > dirauth_options->AuthDirVoteGuardGuaranteeWFU) + guard_wfu = dirauth_options->AuthDirVoteGuardGuaranteeWFU; enough_mtbf_info = rep_hist_have_measured_enough_stability(); if (n_active_nonexit) { + int nth = (int)(n_active_nonexit * + dirauth_options->AuthDirVoteGuardBwThresholdFraction); guard_bandwidth_excluding_exits_kb = - find_nth_uint32(bandwidths_excluding_exits_kb, - n_active_nonexit, n_active_nonexit*3/4); + find_nth_uint32(bandwidths_excluding_exits_kb, n_active_nonexit, nth); } log_info(LD_DIRSERV, @@ -573,6 +558,21 @@ should_publish_node_ipv6(const node_t *node, const routerinfo_t *ri, router_is_me(ri)); } +/** Set routerstatus flags based on the authority options. Same as the testing + * function but for the main network. */ +static void +dirserv_set_routerstatus_flags(routerstatus_t *rs) +{ + const dirauth_options_t *options = dirauth_get_options(); + + tor_assert(rs); + + /* Assign Guard flag to relays that can get it unconditionnaly. */ + if (routerset_contains_routerstatus(options->AuthDirVoteGuard, rs, 0)) { + rs->is_possible_guard = 1; + } +} + /** * Extract status information from <b>ri</b> and from other authority * functions and store it in <b>rs</b>, as per @@ -638,6 +638,8 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs, if (options->TestingTorNetwork) { dirserv_set_routerstatus_testing(rs); + } else { + dirserv_set_routerstatus_flags(rs); } } |