[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: Reusing Exit Nodes?
Thus spake Roger Dingledine (arma@xxxxxxx):
> Right. Well, the address mapping data structures should live inside
> Tor, since that's where they're used.
>
> Speaking of, you might find our string-keyed binary tree handy in keeping
> track of addressmaps and hunting through them, so you don't have to do
> it linearly. Check out strmap_* in src/common/container.c
>
> > Yeah, once the map address code exists it seems like it would be a
> > replacement for the exit_history data structure, at which point about
> > half my patch should just go away.. But it looks like a sizeable
> > chunk of work though (since it's basically blocked on the entire TC
> > and remote). Is there an ETA?
>
> It doesn't have to block on the controller. You could implement it
> locally with normal config options, so people can individually define some
> addressmaps when tor starts, and also so people can define some addresses
> or ports (as your patch already does) that will get auto-addressmapped
> once they pick an exit. Then the controller stuff could come later.
>
> What do you think? :)
How's this? I kind of just haphazardly placed the addressmap_remap
function close to where I needed it. It turned out to be a much
smaller patch than my previous one.
Do you think this is good enough to use as a starting point for the
full addressmap feature?
--
Mike Perry
Mad Computer Scientist
fscked.org evil labs
diff -ur tor/doc/tor.1.in tor-MP/doc/tor.1.in
--- tor/doc/tor.1.in 2005-01-18 19:46:22.000000000 -0800
+++ tor-MP/doc/tor.1.in 2005-01-27 00:26:18.000000000 -0800
@@ -151,6 +151,23 @@
If 1, Tor will never use any nodes besides those listed in "entrynodes" for
the first hop of a circuit.
.TP
+\fBTrackHostExits \fR\fIhost1\fR,\fI.domain1\fR|\fI.\fR\fP
+For each value in the comma separated list, Tor will track recent connections
+to hosts that match this value and attempt to
+reuse the same exit node for each. If the value is prepended with a '.', it is
+treated as matching an entire domain. If one of the values is just a '.', it
+means match everything. This option is useful if you frequently connect to
+sites that will expire all your authentication cookies (ie log you out) if
+your IP address changes. Note that this option does have the disadvantage of
+making it more clear that a given history is
+associated with a single user. However, most people who would wish to observe
+this will observe it through cookies or other protocol-specific means anyhow.
+.TP
+\fBTrackHostExitsExpire \fR\fINUM\fP
+Since exit servers go up and down, it is desirable to expire the association
+between host and exit server after so many minutes of inactivity. The default
+is 30.
+.TP
\fBFascistFirewall \fR\fB0\fR|\fB1\fR\fP
If 1, Tor will only create outgoing connections to ORs running on ports that
your firewall allows (defaults to 80 and 443; see \fBFirewallPorts\fR). This will
diff -ur tor/src/or/circuituse.c tor-MP/src/or/circuituse.c
--- tor/src/or/circuituse.c 2005-01-21 22:33:07.000000000 -0800
+++ tor-MP/src/or/circuituse.c 2005-01-30 01:44:24.000000000 -0800
@@ -955,8 +955,63 @@
link_apconn_to_circ(conn, circ);
tor_assert(conn->socks_request);
- if (conn->socks_request->command == SOCKS_COMMAND_CONNECT)
+ if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) {
+
+ or_options_t *options = get_options();
+ /* If an exit wasn't specifically chosen, save the history for future
+ * use */
+
+ /* search the addressmap for this conn's dest.. */
+ /* If he's not in the address map.. */
+ if(options->TrackHostExits &&
+ (!addressmap || !strmap_get(addressmap, conn->socks_request->address))) {
+ int found_needle = 0;
+ SMARTLIST_FOREACH(options->TrackHostExits, const char *, cp, {
+ if(cp[0] == '.') { /* match end */
+ char *str;
+ if((str = strstr(conn->socks_request->address, &cp[1]))) {
+ if(str == conn->socks_request->address
+ || strcmp(str, &cp[1]) == 0) {
+ found_needle = 1;
+ }
+ }
+ } else if(strcmp(cp, conn->socks_request->address) == 0) {
+ found_needle = 1;
+ }
+ });
+
+ if(found_needle) {
+ /* Add this exit/hostname pair to the addressmap. */
+ time_t now = time(NULL);
+ addressmap_entry_t *ent = (addressmap_entry_t *)malloc(sizeof(addressmap_entry_t));
+ size_t addrlen = strlen(conn->socks_request->address);
+ size_t exitlen = strlen(circ->build_state->chosen_exit_name);
+
+ ent->address = (char *)malloc(
+ addrlen + 1 /* '.' */ +
+ exitlen + 1 /* '.' */ +
+ strlen("exit") + 1 /* '\0' */);
+ ent->max_age = options->TrackHostExitsExpire*60;
+ ent->last_used = now;
+
+ strcpy(ent->address, conn->socks_request->address);
+ ent->address[addrlen] = '.';
+
+ strcpy(&ent->address[addrlen+1], circ->build_state->chosen_exit_name);
+ ent->address[addrlen+exitlen+1] = '.';
+
+ strcpy(&ent->address[addrlen+exitlen+2], "exit");
+
+ if(!addressmap) addressmap = strmap_new();
+
+ strmap_set(addressmap, conn->socks_request->address, ent);
+ log_fn(LOG_NOTICE, "Addressmap: creating %s to %s",
+ conn->socks_request->address, ent->address);
+ }
+ }
+
connection_ap_handshake_send_begin(conn, circ);
+ }
else
connection_ap_handshake_send_resolve(conn, circ);
diff -ur tor/src/or/config.c tor-MP/src/or/config.c
--- tor/src/or/config.c 2005-01-30 01:40:46.000000000 -0800
+++ tor-MP/src/or/config.c 2005-01-29 20:55:16.000000000 -0800
@@ -120,6 +120,8 @@
VAR("StrictEntryNodes", BOOL, StrictEntryNodes, "0"),
VAR("ExitPolicy", LINELIST, ExitPolicy, NULL),
VAR("ExcludeNodes", STRING, ExcludeNodes, NULL),
+ VAR("TrackHostExits", CSV, TrackHostExits, NULL),
+ VAR("TrackHostExitsExpire",UINT, TrackHostExitsExpire, "30"),
VAR("FascistFirewall", BOOL, FascistFirewall, "0"),
VAR("FirewallPorts", CSV, FirewallPorts, "80,443"),
VAR("MyFamily", STRING, MyFamily, NULL),
diff -ur tor/src/or/connection_edge.c tor-MP/src/or/connection_edge.c
--- tor/src/or/connection_edge.c 2005-01-30 01:40:46.000000000 -0800
+++ tor-MP/src/or/connection_edge.c 2005-01-30 01:49:15.000000000 -0800
@@ -320,6 +320,32 @@
}
}
+strmap_t *addressmap;
+
+void addressmap_remap(socks_request_t *socks) {
+ addressmap_entry_t *ent;
+
+ if(!addressmap) addressmap = strmap_new();
+ ent = strmap_get(addressmap, socks->address);
+
+ if(ent) {
+ if(ent->last_used + ent->max_age < time(NULL)) {
+ log_fn(LOG_NOTICE, "Addressmap: expiring %s to %s",
+ socks->address, ent->address);
+
+ free(ent->address);
+ strmap_remove(addressmap, socks->address);
+ free(ent);
+ } else {
+ log_fn(LOG_NOTICE, "Addressmap: remaping %s to %s",
+ socks->address, ent->address);
+ ent->last_used = time(NULL);
+ strncpy(socks->address, ent->address, sizeof(socks->address)-1);
+ socks->address[sizeof(socks->address)-1] = 0;
+ }
+ }
+}
+
/** connection_edge_process_inbuf() found a conn in state
* socks_wait. See if conn->inbuf has the right bytes to proceed with
* the socks handshake.
@@ -363,6 +389,9 @@
return sockshere;
} /* else socks handshake is done, continue processing */
+ /* For address map controls, remap the address */
+ addressmap_remap(socks);
+
/* Parse the address provided by SOCKS. Modify it in-place if it
* specifies a hidden-service (.onion) or particular exit node (.exit).
*/
@@ -381,7 +410,6 @@
if (addresstype != ONION_HOSTNAME) {
/* not a hidden-service request (i.e. normal or .exit) */
-
if (socks->command == SOCKS_COMMAND_RESOLVE) {
uint32_t answer = 0;
struct in_addr in;
diff -ur tor/src/or/or.h tor-MP/src/or/or.h
--- tor/src/or/or.h 2005-01-30 01:40:46.000000000 -0800
+++ tor-MP/src/or/or.h 2005-01-30 01:42:41.000000000 -0800
@@ -483,6 +483,13 @@
typedef struct buf_t buf_t;
typedef struct socks_request_t socks_request_t;
+typedef struct {
+ char *address;
+ time_t max_age;
+ time_t last_used;
+} addressmap_entry_t;
+extern strmap_t *addressmap;
+
#define CONNECTION_MAGIC 0x7C3C304Eu
/** Description of a connection to another host or process, and associated
* data. */
@@ -942,6 +949,8 @@
int IgnoreVersion; /**< If true, run no matter what versions of Tor the
* directory recommends. */
int RunAsDaemon; /**< If true, run in the background. (Unix only) */
+ smartlist_t *TrackHostExits; /**< Should we try to reuse the same exit node for a given host */
+ uint32_t TrackHostExitsExpire; /**< Number of minutes until we expire a connection */
int FascistFirewall; /**< Whether to prefer ORs reachable on open ports. */
smartlist_t *FirewallPorts; /**< Which ports our firewall allows (strings). */
/** Application ports that require all nodes in circ to have sufficient uptime. */