[or-cvs] Allow servers with no hostname or IP address to learn their...

arma at seul.org arma at seul.org
Mon Jul 17 06:35:08 UTC 2006


Update of /home2/or/cvsroot/tor/src/or
In directory moria:/home/arma/work/onion/cvs/tor/src/or

Modified Files:
	config.c directory.c or.h router.c 
Log Message:
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.


Index: config.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/config.c,v
retrieving revision 1.572
retrieving revision 1.573
diff -u -p -d -r1.572 -r1.573
--- config.c	15 Jul 2006 20:26:04 -0000	1.572
+++ config.c	17 Jul 2006 06:35:06 -0000	1.573
@@ -2129,7 +2129,7 @@ options_validate(or_options_t *old_optio
     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)

Index: directory.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/directory.c,v
retrieving revision 1.391
retrieving revision 1.392
diff -u -p -d -r1.391 -r1.392
--- directory.c	15 Jul 2006 19:21:30 -0000	1.391
+++ directory.c	17 Jul 2006 06:35:06 -0000	1.392
@@ -58,6 +58,8 @@ static void note_request(const char *key
  * 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 *a
 
   /* 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, con
 }
 
 /** 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 *head
   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(connec
             "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 
   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) {

Index: or.h
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.850
retrieving revision 1.851
diff -u -p -d -r1.850 -r1.851
--- or.h	16 Jul 2006 05:57:11 -0000	1.850
+++ or.h	17 Jul 2006 06:35:06 -0000	1.851
@@ -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_t
 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);

Index: router.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/router.c,v
retrieving revision 1.269
retrieving revision 1.270
diff -u -p -d -r1.269 -r1.270
--- router.c	15 Jul 2006 20:26:05 -0000	1.269
+++ router.c	17 Jul 2006 06:35:06 -0000	1.270
@@ -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_
   }
 }
 
+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_
     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. */
+  }
+}
 
-    in_prev.s_addr = htonl(prev);
-    tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev));
+static uint32_t last_guessed_ip = 0;
 
-    in_cur.s_addr = htonl(cur);
-    tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur));
+/** 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;
 
-    log_info(LD_GENERAL,
-             "Our IP Address has changed from %s to %s; "
-             "rebuilding descriptor.",
-             addrbuf_prev, addrbuf_cur);
-    mark_my_descriptor_dirty();
+  /* 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);
+
+  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



More information about the tor-commits mailing list