[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-dev] Patch: Hidden service: use inbound bind-address based on circuit ID (effectively giving each circuit a temporarily-unique IP address)



Hi,

I've written this (ugly, unconfigurable) patch for Tor which is designed to allow hidden services more information about their users, by giving each inbound circuit its own temporary "IP address" in the 127.x range. This technique works on Linux (I've not tried it on anything else) and allows the application server to do some useful things which were previously difficult:

* Identify TCP connections coming from the same client, in a short space of time, for example, for diagnostic log analysis, identifying traffic trends
* Rate-limit operations coming from the same client, to defend against some types of DoS attacks
* Temporarily block abusive clients (at least, until they make a new Tor circuit)

More importantly, it can do this with an unmodified application-server (e.g. web servers typically have these features built-in) because it effectively "spoofs" the client ID as an ip-address, in the 127.x range.

The patch is currently not configurable (the feature can't be turned off). It only works with hidden services which are routed to "localhost".

Request for comments. What do you think?

--
Harry SeventyOne
Only in tor-0.2.4.21/src/common: .dirstamp
Only in tor-0.2.4.21/src/config: torrc.sample
Only in tor-0.2.4.21/src/ext/curve25519_donna: .dirstamp
Only in tor-0.2.4.21/src/ext: .dirstamp
diff -ur tor-0.2.4.21-orig/src/or/connection.c tor-0.2.4.21/src/or/connection.c
--- tor-0.2.4.21-orig/src/or/connection.c	2014-02-25 20:04:22.000000000 +0000
+++ tor-0.2.4.21/src/or/connection.c	2014-03-19 17:46:35.624154811 +0000
@@ -1474,6 +1474,24 @@
 connection_connect(connection_t *conn, const char *address,
                    const tor_addr_t *addr, uint16_t port, int *socket_error)
 {
+    return connection_connect_withbind(conn, address, addr, port, socket_error,
+        (in_addr_t) 0 );
+
+}
+
+/**
+ * 
+ * like connection_connect, except: 
+ * 
+ * If the connection is to localhost, an optionally supplied in_addr 
+ * will be used to bind (instead of the configured bind addr). Connections
+ * to other destinations unaffected. local_bind_addr arrives in network order.
+ */
+int
+connection_connect_withbind(connection_t *conn, const char *address,
+                   const tor_addr_t *addr, uint16_t port, int *socket_error,
+                    in_addr_t local_bind_addr )
+{
   tor_socket_t s;
   int inprogress = 0;
   struct sockaddr_storage addrbuf;
@@ -1544,6 +1562,21 @@
         }
       }
     }
+  } else {
+      if (local_bind_addr != 0) {
+          // tor_addr_is_loopback.
+          // DO IPv4 bind
+          struct sockaddr_in bindaddr_in;
+          bindaddr_in.sin_family = AF_INET;
+          bindaddr_in.sin_port = 0;
+          bindaddr_in.sin_addr.s_addr = local_bind_addr;
+          if (bind(s, (struct sockaddr *) &bindaddr_in, sizeof(bindaddr_in)) < 0)
+          {
+              log_warn(LD_NET,
+                "XXX: Unable to bind to the desired loopback bind address.");
+              // Then continue and work anyway..
+          }
+      }
   }
 
   if (set_socket_nonblocking(s) == -1) {
diff -ur tor-0.2.4.21-orig/src/or/connection_edge.c tor-0.2.4.21/src/or/connection_edge.c
--- tor-0.2.4.21-orig/src/or/connection_edge.c	2014-02-25 20:04:22.000000000 +0000
+++ tor-0.2.4.21/src/or/connection_edge.c	2014-03-19 17:46:25.764278795 +0000
@@ -2641,8 +2641,9 @@
   uint16_t port;
   connection_t *conn = TO_CONN(edge_conn);
   int socket_error = 0;
+  int is_rendezvous = connection_edge_is_rendezvous_stream(edge_conn);
 
-  if ( (!connection_edge_is_rendezvous_stream(edge_conn) &&
+  if ( (!is_rendezvous &&
         router_compare_to_my_exit_policy(&edge_conn->base_.addr,
                                          edge_conn->base_.port)) ||
        (tor_addr_family(&conn->addr) == AF_INET6 &&
@@ -2662,7 +2663,39 @@
     conn->socket_family = AF_INET6;
 
   log_debug(LD_EXIT,"about to try connecting");
-  switch (connection_connect(conn, conn->address, addr, port, &socket_error)) {
+  // XXX POI
+  // This is where it actually connects, either to a HS or origin
+  // server, in the case of a Tor exit node.
+
+  in_addr_t local_bind_addr = 0;
+  if (is_rendezvous) {
+      // About to make the inbound HS connection.
+      // edge_conn->on_circuit - struct circuit_t *on_circuit
+      // on_circuit - circid_t n_circ_id
+      log_notice(LD_REND, "XXX: rv incoming circuit ID=%08x", edge_conn->on_circuit->n_circ_id);
+      {
+          // Convert the circuit ID (u_int32_t) into an IPv4
+          // Bind address in the 127.x.x.x range.
+          // Calculate what address we want to bind to.
+          uint32_t mybindaddr = edge_conn->on_circuit->n_circ_id; // circuit ID
+          // The top byte needs to be 0x7f (127.x.x.x)
+          uint32_t topbyte = mybindaddr & 0xff000000;
+          // XOR the top byte into the next byte.
+          topbyte = topbyte >> 8; // Move it down.
+          mybindaddr = mybindaddr & 0x00ffffff; // Mask out the previous top byte
+          // XOR it in.
+          mybindaddr = mybindaddr ^ topbyte;
+          // Put 0x7f into the new top byte (which should now be 0)
+          mybindaddr = mybindaddr | 0x7f000000;
+          struct in_addr mybindaddr_in;
+          mybindaddr_in.s_addr = htonl(mybindaddr);
+          log_notice(LD_REND, "XXX: will bind from %s", inet_ntoa(mybindaddr_in));
+          local_bind_addr = mybindaddr_in.s_addr; // used below.
+      }      
+  }
+  
+  switch (connection_connect_withbind(conn, conn->address, addr, port, &socket_error,
+        local_bind_addr)) {
     case -1: {
       int reason = errno_to_stream_end_reason(socket_error);
       connection_edge_end(edge_conn, reason);
@@ -2671,6 +2704,7 @@
       return;
     }
     case 0:
+      
       conn->state = EXIT_CONN_STATE_CONNECTING;
 
       connection_watch_events(conn, READ_EVENT | WRITE_EVENT);
diff -ur tor-0.2.4.21-orig/src/or/connection.h tor-0.2.4.21/src/or/connection.h
--- tor-0.2.4.21-orig/src/or/connection.h	2014-02-25 20:04:22.000000000 +0000
+++ tor-0.2.4.21/src/or/connection.h	2014-03-19 15:07:59.939908235 +0000
@@ -85,6 +85,10 @@
 
 void connection_expire_held_open(void);
 
+int connection_connect_withbind(connection_t *conn, const char *address,
+                   const tor_addr_t *addr, uint16_t port, int *socket_error,
+                    in_addr_t local_bind_addr );
+
 int connection_connect(connection_t *conn, const char *address,
                        const tor_addr_t *addr,
                        uint16_t port, int *socket_error);
Only in tor-0.2.4.21/src/or: .dirstamp
Only in tor-0.2.4.21-orig/src/or: or_sha1.i
Only in tor-0.2.4.21/src/tools: .dirstamp
_______________________________________________
tor-dev mailing list
tor-dev@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev