From f7a3cdc8f27c2306cf06d742af63846c82ebdc56 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Wed, 9 Mar 2011 11:34:04 +0100 Subject: Use observed instead of declared uptime for HSDir It is important to verify the uptime claim of a relay instead of just trusting it, otherwise it becomes too easy to blackhole a specific hidden service. rephist already has data available that we can use here. Bugfix on 0.2.0.10-alpha. --- changes/hsdir_assignment | 7 +++++++ src/or/dirserv.c | 19 ++++++++++++++++++- src/or/rephist.c | 14 ++++++++++++++ src/or/rephist.h | 1 + 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 changes/hsdir_assignment diff --git a/changes/hsdir_assignment b/changes/hsdir_assignment new file mode 100644 index 000000000..ba019901e --- /dev/null +++ b/changes/hsdir_assignment @@ -0,0 +1,7 @@ + o Security fixes: + - Directory authorities now use data collected from rephist when + choosing whether to assign the HSDir flag to relays, instead of + trusting the uptime value the relay reports in its descriptor. + This helps prevent an attack where relatively few malaicious + nodes can blackhole any given hidden service. Bugfix on + 0.2.0.10-alpha; fixes bug 2709. diff --git a/src/or/dirserv.c b/src/or/dirserv.c index aeeab4538..40136a18e 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -43,6 +43,8 @@ extern time_t time_of_process_start; /* from main.c */ +extern long stats_n_seconds_working; /* from main.c */ + /** Do we need to regenerate the v1 directory when someone asks for it? */ static time_t the_directory_is_dirty = 1; /** Do we need to regenerate the v1 runningrouters document when somebody @@ -1775,7 +1777,22 @@ dirserv_thinks_router_is_unreliable(time_t now, static int dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now) { - long uptime = real_uptime(router, now); + + long uptime; + + /* If we haven't been running for at least + * get_options()->MinUptimeHidServDirectoryV2 seconds, we can't + * have accurate data telling us a relay has been up for at least + * that long. We also want to allow a bit of slack: Reachability + * tests aren't instant. If we haven't been running long enough, + * trust the relay. */ + + if (stats_n_seconds_working > + get_options()->MinUptimeHidServDirectoryV2 * 1.1) + uptime = MIN(rep_hist_get_uptime(router->cache_info.identity_digest, now), + real_uptime(router, now)); + else + uptime = real_uptime(router, now); /* XXX We shouldn't need to check dir_port, but we do because of * bug 1693. In the future, once relays set wants_to_be_hs_dir diff --git a/src/or/rephist.c b/src/or/rephist.c index 53214d61e..69001de83 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -528,6 +528,20 @@ get_weighted_fractional_uptime(or_history_t *hist, time_t when) return ((double) up) / total; } +/** Return how long the router whose identity digest is id has + * been reachable. Return 0 if the router is unknown or currently deemed + * unreachable. */ +long +rep_hist_get_uptime(const char *id, time_t when) +{ + or_history_t *hist = get_or_history(id); + if (!hist) + return 0; + if (!hist->start_of_run) + return 0; + return when - hist->start_of_run; +} + /** Return an estimated MTBF for the router whose identity digest is * id. Return 0 if the router is unknown. */ double diff --git a/src/or/rephist.h b/src/or/rephist.h index 5f6b9f9b4..b06a39ed5 100644 --- a/src/or/rephist.h +++ b/src/or/rephist.h @@ -40,6 +40,7 @@ int rep_hist_record_mtbf_data(time_t now, int missing_means_down); int rep_hist_load_mtbf_data(time_t now); time_t rep_hist_downrate_old_runs(time_t now); +long rep_hist_get_uptime(const char *id, time_t when); double rep_hist_get_stability(const char *id, time_t when); double rep_hist_get_weighted_fractional_uptime(const char *id, time_t when); long rep_hist_get_weighted_time_known(const char *id, time_t when); -- cgit v1.2.3 From 3a0c6021556abc96f4c610d5e097e3890216595f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 11 Mar 2011 13:03:25 -0500 Subject: Clarify threat description and avoid negative uptimes. --- changes/hsdir_assignment | 7 ++++--- src/or/rephist.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/changes/hsdir_assignment b/changes/hsdir_assignment index ba019901e..5c04b9b9b 100644 --- a/changes/hsdir_assignment +++ b/changes/hsdir_assignment @@ -2,6 +2,7 @@ - Directory authorities now use data collected from rephist when choosing whether to assign the HSDir flag to relays, instead of trusting the uptime value the relay reports in its descriptor. - This helps prevent an attack where relatively few malaicious - nodes can blackhole any given hidden service. Bugfix on - 0.2.0.10-alpha; fixes bug 2709. + This helps prevent an attack where a small set of nodes with + frequently-changing identity keys can blackhole a hidden service. + (Only authorities need upgrade; others will be fine once they do.) + Bugfix on 0.2.0.10-alpha; fixes bug 2709. diff --git a/src/or/rephist.c b/src/or/rephist.c index 69001de83..e4afe62b6 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -537,7 +537,7 @@ rep_hist_get_uptime(const char *id, time_t when) or_history_t *hist = get_or_history(id); if (!hist) return 0; - if (!hist->start_of_run) + if (!hist->start_of_run || when < hist->start_of_run) return 0; return when - hist->start_of_run; } -- cgit v1.2.3