Explorar o código

Add `KeepAliveIsolateSOCKSAuth` as a SOCKSPort option.

This controls the circuit dirtyness reset behavior added for Tor
Browser's user experience fix (#15482). Unlike previous iterations
of this patch, the tunable actually works, and is documented.
Yawning Angel %!s(int64=9) %!d(string=hai) anos
pai
achega
54510d4d1a
Modificáronse 5 ficheiros con 34 adicións e 6 borrados
  1. 5 0
      changes/feature15482
  2. 6 1
      doc/tor.1.txt
  3. 5 5
      src/or/circuituse.c
  4. 11 0
      src/or/config.c
  5. 7 0
      src/or/or.h

+ 5 - 0
changes/feature15482

@@ -0,0 +1,5 @@
+  o Minor features (client-side privacy)
+    - Indefinitely extend circuit lifespan by resetting dirtyness, if
+      IsolateSOCKSAuth is in use, the new `KeepAliveIsolateSOCKSAuth`
+      option is set, and streams with SOCKS authentication are attached
+      to the circuit. Implements feature 15482.

+ 6 - 1
doc/tor.1.txt

@@ -934,7 +934,9 @@ The following options are useful only for clients (that is, if
     Feel free to reuse a circuit that was first used at most NUM seconds ago,
     but never attach a new stream to a circuit that is too old.  For hidden
     services, this applies to the __last__ time a circuit was used, not the
-    first.  (Default: 10 minutes)
+    first. Circuits with streams constructed with SOCKS authentication via
+    SocksPorts that have **KeepAliveIsolateSOCKSAuth** ignore this value.
+    (Default: 10 minutes)
 
 [[MaxClientCircuitsPending]] **MaxClientCircuitsPending** __NUM__::
     Do not allow more than NUM circuits to be pending at a time for handling
@@ -991,6 +993,9 @@ The following options are useful only for clients (that is, if
     **IsolateDestAddr**;;
         Don't share circuits with streams targeting a different
         destination address.
+    **KeepAliveIsolateSOCKSAuth**;;
+        If **IsolateSOCKSAuth** is enabled, keep alive circuits that have
+        streams with SOCKS authentication set indefinitely.
     **SessionGroup=**__INT__;;
         If no other isolation rules would prevent it, allow streams
         on this port to share circuits with streams from every other

+ 5 - 5
src/or/circuituse.c

@@ -2284,11 +2284,11 @@ connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
 
   base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
 
-  if (!circ->base_.timestamp_dirty) {
-    circ->base_.timestamp_dirty = approx_time();
-  } else if ((conn->entry_cfg.isolation_flags & ISO_SOCKSAUTH) &&
-             (conn->socks_request->usernamelen ||
-              conn->socks_request->passwordlen)) {
+  if (!circ->base_.timestamp_dirty ||
+      ((conn->entry_cfg.isolation_flags & ISO_SOCKSAUTH) &&
+       (conn->entry_cfg.socks_iso_keep_alive) &&
+       (conn->socks_request->usernamelen ||
+        conn->socks_request->passwordlen))) {
     /* When stream isolation is in use and controlled by an application
      * we are willing to keep using the stream. */
     circ->base_.timestamp_dirty = approx_time();

+ 11 - 0
src/or/config.c

@@ -6022,6 +6022,7 @@ parse_port_config(smartlist_t *out,
     int sessiongroup = SESSION_GROUP_UNSET;
     unsigned isolation = ISO_DEFAULT;
     int prefer_no_auth = 0;
+    int socks_iso_keep_alive = 0;
 
     char *addrport;
     uint16_t ptmp=0;
@@ -6246,6 +6247,8 @@ parse_port_config(smartlist_t *out,
           isoflag = ISO_CLIENTPROTO;
         } else if (!strcasecmp(elt, "IsolateClientAddr")) {
           isoflag = ISO_CLIENTADDR;
+        } else if (!strcasecmp(elt, "KeepAliveIsolateSOCKSAuth")) {
+          socks_iso_keep_alive = 1;
         } else {
           log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
                    portname, escaped(elt_orig));
@@ -6276,6 +6279,13 @@ parse_port_config(smartlist_t *out,
       goto err;
     }
 
+    if (!(isolation & ISO_SOCKSAUTH) && socks_iso_keep_alive) {
+      log_warn(LD_CONFIG, "You have a %sPort entry with both "
+               "NoIsolateSOCKSAuth and KeepAliveIsolateSOCKSAuth set.",
+               portname);
+      goto err;
+    }
+
     if (out && port) {
       size_t namelen = unix_socket_path ? strlen(unix_socket_path) : 0;
       port_cfg_t *cfg = port_cfg_new(namelen);
@@ -6309,6 +6319,7 @@ parse_port_config(smartlist_t *out,
       cfg->entry_cfg.socks_prefer_no_auth = prefer_no_auth;
       if (! (isolation & ISO_SOCKSAUTH))
         cfg->entry_cfg.socks_prefer_no_auth = 1;
+      cfg->entry_cfg.socks_iso_keep_alive = socks_iso_keep_alive;
 
       smartlist_add(out, cfg);
     }

+ 7 - 0
src/or/or.h

@@ -1155,6 +1155,8 @@ typedef struct entry_port_cfg_t {
   /** When both no-auth and user/pass are advertised by a SOCKS client, select
    * no-auth. */
   unsigned int socks_prefer_no_auth : 1;
+  /** When ISO_SOCKSAUTH is in use, Keep-Alive circuits indefinitely. */
+  unsigned int socks_iso_keep_alive : 1;
 
   /* Client port types only: */
   unsigned int ipv4_traffic : 1;
@@ -2877,6 +2879,11 @@ typedef struct circuit_t {
    * circuits entered certain states.  This usage probably won't
    * interfere with this field's primary purpose, but we should
    * document it more thoroughly to make sure of that.
+   *
+   * XXX027 The SocksPort option KeepaliveIsolateSOCKSAuth will artificially
+   * adjust this value forward each time a suitable stream is attached to an
+   * already constructed circuit, potentially keeping the circuit alive
+   * indefinitely.
    */
   time_t timestamp_dirty;