diff options
author | Roger Dingledine <arma@torproject.org> | 2006-07-17 06:35:06 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2006-07-17 06:35:06 +0000 |
commit | 9db7b2c0687a3ee28e96e0c0db6c2a3e7ef4c626 (patch) | |
tree | 08ce2b504d2a41655d2945304b3474733cad6b20 /src | |
parent | 8868830ac5730e455bbc727893b2234b5f1f33fe (diff) | |
download | tor-9db7b2c0687a3ee28e96e0c0db6c2a3e7ef4c626.tar tor-9db7b2c0687a3ee28e96e0c0db6c2a3e7ef4c626.tar.gz |
Allow servers with no hostname or IP address to learn their IP address
by asking the directory authorities. This code only kicks in when you
would normally have exited with a "no address" error.
This design is flawed, though, since the X-Your-Address-Is header is not
authenticated, and doing it this way introduces too many new attacks. The
right answer is to give IP address hints inside the HELLO cell; much of
this code can be reused when we switch.
svn:r6774
Diffstat (limited to 'src')
-rw-r--r-- | src/or/config.c | 2 | ||||
-rw-r--r-- | src/or/directory.c | 27 | ||||
-rw-r--r-- | src/or/or.h | 2 | ||||
-rw-r--r-- | src/or/router.c | 98 |
4 files changed, 99 insertions, 30 deletions
diff --git a/src/or/config.c b/src/or/config.c index 7148f40d4..fcca7acf9 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2129,7 +2129,7 @@ options_validate(or_options_t *old_options, or_options_t *options, options->PublishServerDescriptor = 0; } - if (server_mode(options)) { + if (authdir_mode(options)) { /* confirm that our address isn't broken, so we can complain now */ uint32_t tmp; if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0) diff --git a/src/or/directory.c b/src/or/directory.c index dd920893e..52ebf19f2 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -58,6 +58,8 @@ static void note_request(const char *key, size_t bytes); * before deciding that one of us has the wrong time? */ #define ALLOW_DIRECTORY_TIME_SKEW (30*60) +#define X_ADDRESS_HEADER "X-Your-Address-Is: " + /********* END VARIABLES ************/ /** Return true iff the directory purpose 'purpose' must use an @@ -386,6 +388,7 @@ directory_initiate_command(const char *address, uint32_t addr, /* give it an initial state */ conn->state = DIR_CONN_STATE_CONNECTING; + conn->dirconn_direct = (private_connection == 0); if (!private_connection) { /* then we want to connect directly */ @@ -658,9 +661,8 @@ http_get_header(const char *headers, const char *which) } /** If <b>headers</b> indicates that a proxy was involved, then rewrite - * <b>conn</b>-\>address to describe our best guess of the addresses - * involved in this HTTP request. The format is either "1.2.3.4" or - * "1.2.3.4 (forwarded for 5.6.7.8)". */ + * <b>conn</b>-\>address to describe our best guess of the address that + * originated this HTTP request. */ static void http_set_address_origin(const char *headers, connection_t *conn) { @@ -670,13 +672,9 @@ http_set_address_origin(const char *headers, connection_t *conn) if (!fwd) fwd = http_get_header(headers, "X-Forwarded-For: "); if (fwd) { - size_t len = strlen(fwd)+strlen(conn->address)+32; - char *result = tor_malloc(len); - tor_snprintf(result, len, "%s (forwarded for %s)", conn->address, - escaped(fwd)); - tor_free(fwd); tor_free(conn->address); - conn->address = result; + conn->address = tor_strdup(escaped(fwd)); + tor_free(fwd); } } @@ -851,6 +849,15 @@ connection_dir_client_reached_eof(connection_t *conn) "Received response from directory server '%s:%d': %d %s", conn->address, conn->port, status_code, escaped(reason)); + /* now check if it's got any hints for us about our IP address. */ + if (server_mode(get_options())) { + char *guess = http_get_header(headers, X_ADDRESS_HEADER); + if (guess) { + router_new_address_suggestion(guess); + tor_free(guess); + } + } + if (date_header > 0) { now = time(NULL); delta = now-date_header; @@ -1264,7 +1271,7 @@ write_http_response_header(connection_t *conn, ssize_t length, cp = tmp; tor_snprintf(cp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n" - "X-Your-Address-Is: %s\r\n", + X_ADDRESS_HEADER "%s\r\n", date, type, conn->address); cp += strlen(tmp); if (encoding) { diff --git a/src/or/or.h b/src/or/or.h index 9f3c96d18..5700221fa 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -691,6 +691,7 @@ struct connection_t { /* Used only by Dir connections */ char *requested_resource; /**< Which 'resource' did we ask the directory * for? */ + unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */ /* Used only for server sides of some dir connections. */ enum { DIR_SPOOL_NONE=0, DIR_SPOOL_SERVER_BY_DIGEST, DIR_SPOOL_SERVER_BY_FP, @@ -2274,6 +2275,7 @@ void mark_my_descriptor_dirty_if_older_than(time_t when); void mark_my_descriptor_dirty(void); void check_descriptor_bandwidth_changed(time_t now); void check_descriptor_ipaddress_changed(time_t now); +void router_new_address_suggestion(const char *suggestion); int router_compare_to_my_exit_policy(connection_t *conn); routerinfo_t *router_get_my_routerinfo(void); const char *router_get_my_descriptor(void); diff --git a/src/or/router.c b/src/or/router.c index 9f7913cf6..0e577a803 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -736,9 +736,11 @@ router_get_my_descriptor(void) /*DOCDOC*/ static smartlist_t *warned_nonexistent_family = NULL; +static int router_guess_address_from_dir_headers(uint32_t *guess); + /** If <b>force</b> is true, or our descriptor is out-of-date, rebuild * a fresh routerinfo and signed server descriptor for this OR. - * Return 0 on success, -1 on error. + * Return 0 on success, -1 on temporary error. */ int router_rebuild_descriptor(int force) @@ -752,9 +754,14 @@ router_rebuild_descriptor(int force) if (desc_clean_since && !force) return 0; - if (resolve_my_address(LOG_WARN, options, &addr, NULL) < 0) { - log_warn(LD_CONFIG,"options->Address didn't resolve into an IP."); - return -1; + if (resolve_my_address(LOG_INFO, options, &addr, NULL) < 0) { + log_info(LD_CONFIG, "Could not determine our address locally. " + "Checking if directory headers provide any hints."); + if (router_guess_address_from_dir_headers(&addr) < 0) { + log_info(LD_CONFIG, "No hints from directory headers either. " + "Will try again later."); + return -1; + } } ri = tor_malloc_zero(sizeof(routerinfo_t)); @@ -894,6 +901,26 @@ check_descriptor_bandwidth_changed(time_t now) } } +static void +log_addr_has_changed(uint32_t prev, uint32_t cur) +{ + char addrbuf_prev[INET_NTOA_BUF_LEN]; + char addrbuf_cur[INET_NTOA_BUF_LEN]; + struct in_addr in_prev; + struct in_addr in_cur; + + in_prev.s_addr = htonl(prev); + tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev)); + + in_cur.s_addr = htonl(cur); + tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur)); + + log_info(LD_GENERAL, + "Our IP Address has changed from %s to %s; " + "rebuilding descriptor.", + addrbuf_prev, addrbuf_cur); +} + /** Check whether our own address as defined by the Address configuration * has changed. This is for routers that get their address from a service * like dyndns. If our address has changed, mark our descriptor dirty. */ @@ -908,29 +935,62 @@ check_descriptor_ipaddress_changed(time_t now) return; prev = desc_routerinfo->addr; - if (resolve_my_address(LOG_WARN, options, &cur, NULL) < 0) { - log_warn(LD_CONFIG,"options->Address didn't resolve into an IP."); + if (resolve_my_address(LOG_INFO, options, &cur, NULL) < 0) { + log_info(LD_CONFIG,"options->Address didn't resolve into an IP."); return; } if (prev != cur) { - char addrbuf_prev[INET_NTOA_BUF_LEN]; - char addrbuf_cur[INET_NTOA_BUF_LEN]; - struct in_addr in_prev; - struct in_addr in_cur; + log_addr_has_changed(prev, cur); + mark_my_descriptor_dirty(); + /* the above call is probably redundant, since resolve_my_address() + * probably already noticed and marked it dirty. */ + } +} + +static uint32_t last_guessed_ip = 0; - in_prev.s_addr = htonl(prev); - tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev)); +/** A directory authority told us our IP address is <b>suggestion</b>. + * If this address is different from the one we think we are now, and + * if our computer doesn't actually know its IP address, then switch. */ +void +router_new_address_suggestion(const char *suggestion) +{ + uint32_t addr, cur; + struct in_addr in; - in_cur.s_addr = htonl(cur); - tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur)); + /* first, learn what the IP address actually is */ + if (!tor_inet_aton(suggestion, &in)) { + log_debug(LD_DIR, "Malformed X-Your-Address-Is header. Ignoring."); + return; + } + addr = ntohl(in.s_addr); - log_info(LD_GENERAL, - "Our IP Address has changed from %s to %s; " - "rebuilding descriptor.", - addrbuf_prev, addrbuf_cur); - mark_my_descriptor_dirty(); + if (resolve_my_address(LOG_INFO, get_options(), &cur, NULL) >= 0) { + /* We're all set -- we already know our address. Great. */ + last_guessed_ip = cur; /* store it in case we need it later */ + return; + } + + if (last_guessed_ip != addr) { + log_addr_has_changed(last_guessed_ip, addr); + server_has_changed_ip(); + last_guessed_ip = addr; /* router_rebuild_descriptor() will fetch it */ + } +} + +/** We failed to resolve our address locally, but we'd like to build + * a descriptor and publish / test reachability. If we have a guess + * about our address based on directory headers, answer it and return + * 0; else return -1. */ +static int +router_guess_address_from_dir_headers(uint32_t *guess) +{ + if (last_guessed_ip) { + *guess = last_guessed_ip; + return 0; } + return -1; } /** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short |