[or-cvs] [tor/master] If configured, write entry-node statistics to disk periodically.

Nick Mathewson nickm at seul.org
Tue Jul 7 18:26:59 UTC 2009


Author: Karsten Loesing <karsten.loesing at gmx.net>
Date: Sun, 5 Jul 2009 20:48:16 +0200
Subject: If configured, write entry-node statistics to disk periodically.
Commit: c0b6cb132baaf9cf259bfb09e14c1128d7abc9d6

---
 ChangeLog       |    4 ++++
 configure.in    |    7 +++++++
 src/or/config.c |   20 ++++++++++++++++++++
 src/or/geoip.c  |   42 ++++++++++++++++++++++++++++++++++++++++++
 src/or/or.h     |    9 ++++++++-
 src/or/router.c |    3 +++
 6 files changed, 84 insertions(+), 1 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0d5af88..a5f35fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -21,6 +21,10 @@ Changes in version 0.2.2.1-alpha - 2009-??-??
       transferred bytes per port to disk every 24 hours.  To enable this,
       run configure with the --enable-exit-stats option, and set
       "ExitPortStatistics 1" in your torrc.
+    - Entry nodes can write statistics on the rough number and origins of
+      connecting clients to disk every 24 hours. To enable this, run
+      configure with the --enable-entry-stats option, and set
+      "EntryStatistics 1" in your torrc.
 
   o Minor bugfixes
     - Hidden service clients didn't use a cached service descriptor that
diff --git a/configure.in b/configure.in
index 8442115..0f83207 100644
--- a/configure.in
+++ b/configure.in
@@ -99,6 +99,13 @@ if test "$enable_geoip_stats" = "yes"; then
   AC_DEFINE(ENABLE_GEOIP_STATS, 1, [Defined if we try to collect per-country statistics])
 fi
 
+AC_ARG_ENABLE(entry-stats,
+     AS_HELP_STRING(--enable-entry-stats, enable code for entry guards to collect per-country statistics))
+
+if test "$enable_entry_stats" = "yes"; then
+  AC_DEFINE(ENABLE_ENTRY_STATS, 1, [Defined if we try to collect per-country statistics])
+fi
+
 AC_ARG_ENABLE(gcc-warnings,
      AS_HELP_STRING(--enable-gcc-warnings, enable verbose warnings))
 
diff --git a/src/or/config.c b/src/or/config.c
index f1fea13..c9ef21b 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -198,6 +198,7 @@ static config_var_t _option_vars[] = {
   V(DownloadExtraInfo,           BOOL,     "0"),
   V(EnforceDistinctSubnets,      BOOL,     "1"),
   V(EntryNodes,                  ROUTERSET,   NULL),
+  V(EntryStatistics,             BOOL,     "0"),
   V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "10 minutes"),
   V(ExcludeNodes,                ROUTERSET, NULL),
   V(ExcludeExitNodes,            ROUTERSET, NULL),
@@ -1395,6 +1396,25 @@ options_act(or_options_t *old_options)
     log_warn(LD_CONFIG, "ExitPortStatistics enabled, but Tor was built "
              "without port statistics support.");
 #endif
+#ifdef ENABLE_ENTRY_STATS
+  if (options->EntryStatistics) {
+    if (should_record_bridge_info(options)) {
+      /* Don't allow measuring statistics on entry guards when configured
+       * as bridge. */
+      log_warn(LD_CONFIG, "Bridges cannot be configured to measure "
+               "additional GeoIP statistics as entry guards.");
+      return -1;
+    } else
+      log_notice(LD_CONFIG, "Configured to measure entry node "
+                 "statistics. Look for the entry-stats file that will "
+                 "first be written to the data directory in 24 hours "
+                 "from now.");
+  }
+#else
+  if (options->EntryStatistics)
+    log_warn(LD_CONFIG, "EntryStatistics enabled, but Tor was built "
+             "without entry node statistics support.");
+#endif
   /* Check if we need to parse and add the EntryNodes config option. */
   if (options->EntryNodes &&
       (!old_options ||
diff --git a/src/or/geoip.c b/src/or/geoip.c
index 41c8f21..13a6a28 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -13,6 +13,7 @@
 
 static void clear_geoip_db(void);
 static void dump_geoip_stats(void);
+static void dump_entry_stats(void);
 
 /** An entry from the GeoIP file: maps an IP range to a country. */
 typedef struct geoip_entry_t {
@@ -308,8 +309,13 @@ geoip_note_client_seen(geoip_client_action_t action,
   or_options_t *options = get_options();
   clientmap_entry_t lookup, *ent;
   if (action == GEOIP_CLIENT_CONNECT) {
+#ifdef ENABLE_ENTRY_STATS
+    if (!options->EntryStatistics)
+      return;
+#else
     if (!(options->BridgeRelay && options->BridgeRecordUsageByCountry))
       return;
+#endif
     /* Did we recently switch from bridge to relay or back? */
     if (client_history_starts > now)
       return;
@@ -337,6 +343,8 @@ geoip_note_client_seen(geoip_client_action_t action,
     geoip_remove_old_clients(current_request_period_starts);
     /* Before rotating, write the current stats to disk. */
     dump_geoip_stats();
+    if (get_options()->EntryStatistics)
+      dump_entry_stats();
     /* Now rotate request period */
     SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, {
         memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1],
@@ -657,6 +665,40 @@ dump_geoip_stats(void)
 #endif
 }
 
+/** Store all our geoip statistics as entry guards into
+ * $DATADIR/entry-stats. */
+static void
+dump_entry_stats(void)
+{
+#ifdef ENABLE_ENTRY_STATS
+  time_t now = time(NULL);
+  char *filename = get_datadir_fname("entry-stats");
+  char *data = NULL;
+  char since[ISO_TIME_LEN+1], written[ISO_TIME_LEN+1];
+  open_file_t *open_file = NULL;
+  FILE *out;
+
+  data = geoip_get_client_history(now, GEOIP_CLIENT_CONNECT);
+  format_iso_time(since, geoip_get_history_start());
+  format_iso_time(written, now);
+  out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND,
+                                    0600, &open_file);
+  if (!out)
+    goto done;
+  if (fprintf(out, "written %s\nstarted-at %s\nips %s\n",
+              written, since, data ? data : "") < 0)
+    goto done;
+
+  finish_writing_to_file(open_file);
+  open_file = NULL;
+ done:
+  if (open_file)
+    abort_writing_to_file(open_file);
+  tor_free(filename);
+  tor_free(data);
+#endif
+}
+
 /** Helper used to implement GETINFO ip-to-country/... controller command. */
 int
 getinfo_helper_geoip(control_connection_t *control_conn,
diff --git a/src/or/or.h b/src/or/or.h
index 935ea52..65eac0e 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2478,6 +2478,9 @@ typedef struct {
   /** If true, the user wants us to collect statistics on port usage. */
   int ExitPortStatistics;
 
+  /** If true, the user wants us to collect statistics as entry node. */
+  int EntryStatistics;
+
   /** If true, do not believe anybody who tells us that a domain resolves
    * to an internal address, or that an internal address has a PTR mapping.
    * Helps avoid some cross-site attacks. */
@@ -3595,6 +3598,10 @@ int dnsserv_launch_request(const char *name, int is_reverse);
  * we are willing to talk about it? */
 #define DIR_RECORD_USAGE_MIN_OBSERVATION_TIME (24*60*60)
 
+/** Time interval: Flush geoip data to disk this often when measuring on an
+ * entry guard. */
+#define ENTRY_RECORD_USAGE_RETAIN_IPS (24*60*60)
+
 #ifdef GEOIP_PRIVATE
 int geoip_parse_entry(const char *line);
 #endif
@@ -3610,7 +3617,7 @@ country_t geoip_get_country(const char *countrycode);
  * the others, we're not.
  */
 typedef enum {
-  /** We've noticed a connection as a bridge relay. */
+  /** We've noticed a connection as a bridge relay or entry guard. */
   GEOIP_CLIENT_CONNECT = 0,
   /** We've served a networkstatus consensus as a directory server. */
   GEOIP_CLIENT_NETWORKSTATUS = 1,
diff --git a/src/or/router.c b/src/or/router.c
index cb73e37..bdea4fa 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1919,6 +1919,9 @@ extrainfo_get_client_geoip_summary(time_t now)
 #ifdef ENABLE_GEOIP_STATS
   geoip_purge_interval = DIR_RECORD_USAGE_RETAIN_IPS;
 #endif
+#ifdef ENABLE_ENTRY_STATS
+  geoip_purge_interval = ENTRY_RECORD_USAGE_RETAIN_IPS;
+#endif
   if (now > last_purged_at+geoip_purge_interval) {
     /* (Note that this also discards items in the client history with
      * action GEOIP_CLIENT_NETWORKSTATUS{_V2}, which doesn't matter
-- 
1.5.6.5



More information about the tor-commits mailing list