r11820@Kushana: nickm | 2007-01-03 14:54:05 -0500

Add (and specify) a BadDirectory flag to networkstatuses, so authorities can tell clients that some caches are broken.  Also, implement an as-yet-unused function to estimate how many bytes will be sent on a directory connection.


svn:r9255
This commit is contained in:
Nick Mathewson 2007-01-03 19:58:00 +00:00
parent 931e555ef9
commit 2963d4acc2
7 changed files with 62 additions and 6 deletions

View File

@ -76,6 +76,8 @@ Changes in version 0.1.2.5-alpha - 2007-01-03
- When we change nameservers or IP addresses, reset and re-launch
our tests for DNS hijacking.
- Block an obscure DoS attack from directory caches.
- Add a BadDirectory flag to network status docs so that authorities
can (eventually) tell clients about caches they believe to be broken.
o Security bugfixes:
- Stop sending the HttpProxyAuthenticator string to directory

View File

@ -86,7 +86,7 @@ N - DNS improvements
D But eventually, we give up after getting a lot of 503s.
D Delay when we get a lot of 503s, rather than punting onto the
servers that have given us 503s?
N - Add a 'BadDirectory' flag to statuses.
o Add a 'BadDirectory' flag to statuses.
- authorities should *never* 503 a cache, and should never 503
network status requests. They can 503 client descriptor requests
when they feel like it.
@ -136,8 +136,8 @@ R - "bandwidth classes", for incoming vs initiated-here conns,
and to give dir conns lower priority.
. Write limiting; separate token bucket for write
o preemptively give a 503 to some v1 dir requests
- preemptively give a 503 to some v2 dir requests
- Write function to estimate bytes needed for N descriptors
R - preemptively give a 503 to some v2 dir requests
o Write function to estimate bytes needed for N descriptors
statuses
D per-conn write buckets
D separate config options for read vs write limiting

View File

@ -347,6 +347,8 @@ $Id$
"Versions" if this directory authority recommends software versions.
"BadExits" if the directory authority flags nodes that it believes
are performing incorrectly as exit nodes.
"BadDirectories" if the directory authority flags nodes that it
believes are performing incorrectly as directory caches.
The dir-options entry is optional. The "-versions" entries are required if
the "Versions" flag is present. The other entries are required and must
@ -376,6 +378,10 @@ $Id$
"BadExit" if the router is believed to be useless as an exit node
(because its ISP censors it, because it is behind a restrictive
proxy, or for some similar reason).
"BadDirectory" if the router is believed to be useless as a
directory cache (because its directory port isn't working;
because its bandwidth is always throttled, or for some
similar reason).
"Exit" if the router is useful for building general-purpose exit
circuits.
"Fast" if the router is suitable for high-bandwidth circuits.

View File

@ -1882,6 +1882,35 @@ dirserv_test_reachability(int try_all)
ctr = (ctr + 1) % 128;
}
/** Return an approximate estimate of the number of bytes that will be needed
* to transmit the server descriptors (if is_serverdescs) or networkstatus
* objects (if !is_serverdescs) listed in <b>fps</b>. If <b>compressed</b> is
* set, we guess how large the data will be after compression.
*
* The return value is an estimate; it might be larger or smaller.
**/
size_t
dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
int compressed)
{
size_t result;
if (is_serverdescs) {
int n = smartlist_len(fps);
routerinfo_t *me = router_get_my_routerinfo();
result = (me?me->cache_info.signed_descriptor_len:2048) * n;
if (compressed)
result /= 2; /* observed compressability is between 35 and 55%. */
} else {
result = 0;
SMARTLIST_FOREACH(fps, const char *, d, {
cached_dir_t *dir = digestmap_get(cached_v2_networkstatus, d);
if (dir)
result += compressed ? dir->dir_z_len : dir->dir_len;
});
}
return result;
}
/** When we're spooling data onto our outbuf, add more whenever we dip
* below this threshold. */
#define DIRSERV_BUFFER_MIN 16384

View File

@ -1012,6 +1012,8 @@ typedef 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_bad_directory:1; /**< Do we think this directory is junky,
* underpowered, or otherwise useless? */
/** True iff we know version info for this router. (i.e., a "v" entry was
* included.) We'll replace all these with a big tor_version_t or a char[]
@ -1081,9 +1083,11 @@ typedef struct networkstatus_t {
unsigned int recommends_versions:1; /**< True iff this directory server
* recommends client and server software
* versions. */
unsigned int lists_bad_exits:1; /** True iff this directory server marks
unsigned int lists_bad_exits:1; /**< True iff this directory server marks
* malfunctioning exits as bad. */
/** True iff this directory server marks malfunctioning directories as
* bad. */
unsigned int lists_bad_directories:1;
smartlist_t *entries; /**< List of routerstatus_t*. This list is kept
* sorted by identity_digest. */
} networkstatus_t;
@ -2319,6 +2323,8 @@ void dirserv_test_reachability(int try_all);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int complain);
int dirserv_would_reject_router(routerstatus_t *rs);
size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
int compressed);
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);

View File

@ -546,6 +546,8 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
int is_overloaded = _local_status->last_dir_503_at + DIR_503_TIMEOUT > now;
if (!status->is_running || !status->dir_port || !status->is_valid)
continue;
if (status->is_bad_directory)
continue;
if (requireother && router_digest_is_me(status->identity_digest))
continue;
is_trusted = router_digest_is_trusted_dir(status->identity_digest);
@ -3212,7 +3214,7 @@ routerstatus_list_update_from_networkstatus(time_t now)
{
or_options_t *options = get_options();
int n_trusted, n_statuses, n_recent = 0, n_naming = 0;
int n_listing_bad_exits = 0;
int n_listing_bad_exits = 0, n_listing_bad_directories = 0;
int i, j, warned;
int *index, *size;
networkstatus_t **networkstatus;
@ -3262,6 +3264,8 @@ routerstatus_list_update_from_networkstatus(time_t now)
++n_recent;
if (networkstatus[i]->lists_bad_exits)
++n_listing_bad_exits;
if (networkstatus[i]->lists_bad_directories)
++n_listing_bad_directories;
}
/** Iterate over all entries in all networkstatuses, and build
@ -3333,6 +3337,7 @@ routerstatus_list_update_from_networkstatus(time_t now)
while (1) {
int n_running=0, n_named=0, n_valid=0, n_listing=0;
int n_v2_dir=0, n_fast=0, n_stable=0, n_exit=0, n_guard=0, n_bad_exit=0;
int n_bad_directory=0;
int n_version_known=0, n_supports_begindir=0;
int n_desc_digests=0, highest_count=0;
const char *the_name = NULL;
@ -3421,6 +3426,8 @@ routerstatus_list_update_from_networkstatus(time_t now)
++n_v2_dir;
if (rs->is_bad_exit)
++n_bad_exit;
if (rs->is_bad_directory)
++n_bad_directory;
if (rs->version_known)
++n_version_known;
if (rs->version_supports_begindir)
@ -3475,6 +3482,8 @@ routerstatus_list_update_from_networkstatus(time_t now)
rs_out->status.is_stable = n_stable > n_statuses/2;
rs_out->status.is_v2_dir = n_v2_dir > n_statuses/2;
rs_out->status.is_bad_exit = n_bad_exit > n_listing_bad_exits/2;
rs_out->status.is_bad_directory =
n_bad_directory > n_listing_bad_directories/2;
rs_out->status.version_known = n_version_known > 0;
rs_out->status.version_supports_begindir =
n_supports_begindir > n_version_known/2;

View File

@ -1077,6 +1077,8 @@ routerstatus_parse_entry_from_string(const char **s, smartlist_t *tokens)
rs->is_possible_guard = 1;
else if (!strcmp(tok->args[i], "BadExit"))
rs->is_bad_exit = 1;
else if (!strcmp(tok->args[i], "BadDirectory"))
rs->is_bad_directory = 1;
}
}
if ((tok = find_first_by_keyword(tokens, K_V))) {
@ -1224,6 +1226,8 @@ networkstatus_parse_from_string(const char *s)
ns->recommends_versions = 1;
if (!strcmp(tok->args[i], "BadExits"))
ns->lists_bad_exits = 1;
if (!strcmp(tok->args[i], "BadDirectories"))
ns->lists_bad_directories = 1;
}
}