Opened 11 years ago

Last modified 7 years ago

#814 closed defect (Fixed)

Fetching v0 and v2 rendezvous descriptors in parallel sometimes fails

Reported by: karsten Owned by: karsten
Priority: Low Milestone:
Component: Core Tor/Tor Version: 0.2.1.4-alpha
Severity: Keywords:
Cc: karsten, nickm Actual Points:
Parent ID: Points:
Reviewer: Sponsor:

Description

The logic to download v0 and v2 rendezvous descriptors in parallel does not
work correctly. If the v0 request returns first and unsuccessfully, the
hidden service connection is closed with the statement "[notice] Closing
stream for '[...].onion': hidden service is unavailable (try again later)."
A subsequent successful result of a v2 request cannot be processed
correctly; while the descriptor is stored for later use, it cannot be used
for the requesting connection any more.

This is a minor problem, since hidden services that only publish v2
descriptors are still rare (unless people perform tests with them).

Patch follows.

[Automatically added by flyspray2trac: Operating System: All]

Child Tickets

Change History (6)

comment:1 Changed 11 years ago by karsten

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/src/or/rendclient.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/src/or/rendclient.c (revision 16810)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/src/or/rendclient.c (working copy)
@@ -666,9 +666,22 @@

connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);

}

} else { /* 404, or fetch didn't get that far */

  • log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
  • "unavailable (try again later).", safe_str(query));
  • connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);

+ /* Are there fetch requests for this descriptor going on in parallel?
+ * If so, don't close the connection just because of this request
+ * failing. */
+ int parallel_fetches = 0;
+ SMARTLIST_FOREACH(conns, connection_t *, c, {
+ if (c->type == CONN_TYPE_DIR &&

+ (c->purpose == DIR_PURPOSE_FETCH_RENDDESC

+ c->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) &&
+ !rend_cmp_service_ids(query, TO_DIR_CONN(c)->rend_query))
+ parallel_fetches++;
+ });
+ if (parallel_fetches < 2) {
+ log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
+ "unavailable (try again later).", safe_str(query));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+ }

}

});

}

comment:2 Changed 11 years ago by karsten

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/ChangeLog
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/ChangeLog (revision 16818)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/ChangeLog (working copy)
@@ -25,6 +25,10 @@

for bug 811.

  • Catch and report a few more bootstrapping failure cases when Tor fails to establish a TCP connection. Cleanup on 0.2.1.x.

+ - When fetching v0 and v2 rendezvous service descriptors in parallel,
+ do not fail the whole hidden service request only because the v0
+ descriptor fetch request fails; the v2 request might still succeed.
+ Fixes bug 814. Bugfix on 0.2.0.10-alpha.

o Minor features:

  • Use a lockfile to make sure that two Tor processes are not

comment:3 Changed 11 years ago by karsten

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog (revision 16835)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog (working copy)
@@ -24,6 +24,12 @@

for bug 811.

  • Catch and report a few more bootstrapping failure cases when Tor fails to establish a TCP connection. Cleanup on 0.2.1.x.

+ - When fetching v0 and v2 rendezvous service descriptors in parallel,
+ do not fail the whole hidden service request only because the v0
+ descriptor fetch request fails; the v2 request might still succeed.
+ The other way round, when the last v2 request fails and no v0 request
+ is going on, do fail the hidden service request. Fixes bug 814.
+ Bugfix on 0.2.0.10-alpha.

o Minor features:

  • Use a lockfile to make sure that two Tor processes are not

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c (revision 16835)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c (working copy)
@@ -462,6 +462,8 @@

log_info(LD_REND, "Could not pick one of the responsible hidden "

"service directories to fetch descriptors, because "
"we already tried them all unsuccessfully.");

+ /* Close pending connections (unless a rend desc has arrived by magic). */
+ rend_client_desc_here(query);

return;

}


@@ -666,9 +668,13 @@

connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);

}

} else { /* 404, or fetch didn't get that far */

  • log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
  • "unavailable (try again later).", safe_str(query));
  • connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);

+ /* Unless there are requests for another descriptor version pending,
+ * close the connection. */
+ if (!connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query, -1)) {
+ log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
+ "unavailable (try again later).", safe_str(query));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+ }

}

});

}

comment:4 Changed 11 years ago by karsten

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog (revision 16872)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog (working copy)
@@ -24,6 +24,12 @@

for bug 811.

  • Catch and report a few more bootstrapping failure cases when Tor fails to establish a TCP connection. Cleanup on 0.2.1.x.

+ - When fetching v0 and v2 rendezvous service descriptors in parallel,
+ do not fail the whole hidden service request only because the v0
+ descriptor fetch request fails; the v2 request might still succeed.
+ The other way round, when the last v2 request fails and no v0 request
+ is going on, do fail the hidden service request. Fixes bug 814.
+ Bugfix on 0.2.0.10-alpha.

o Minor features:

  • Use a lockfile to make sure that two Tor processes are not

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/connection.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/connection.c (revision 16838)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/connection.c (working copy)
@@ -522,8 +522,13 @@

  • failed: forget about this router, and maybe try again. */

connection_dir_request_failed(dir_conn);

}

  • if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
  • rend_client_desc_here(dir_conn->rend_query); /* give it a try */

+ if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC) {
+ /* Give it a try. However, there is no re-fetching for v0 rend
+ * descriptors; if the response is empty or the descriptor is
+ * unusable, close pending connections (unless a v2 request is
+ * still in progress). */
+ rend_client_desc_here(dir_conn->rend_query, 0);
+ }

/* If we were trying to fetch a v2 rend desc and did not succeed,

  • retry as needed. (If a fetch is successful, the connection state
  • is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/directory.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/directory.c (revision 16838)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/directory.c (working copy)
@@ -1893,7 +1893,7 @@

} else {

/* success. notify pending connections about this. */
conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;

  • rend_client_desc_here(conn->rend_query);

+ rend_client_desc_here(conn->rend_query, -1);

}
break;

case 404:

@@ -1939,7 +1939,7 @@

log_info(LD_REND, "Successfully fetched v2 rendezvous "

"descriptor.");

conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;

  • rend_client_desc_here(conn->rend_query);

+ rend_client_desc_here(conn->rend_query, -1);

break;

}
break;

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/or.h
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/or.h (revision 16838)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/or.h (working copy)
@@ -3839,7 +3839,7 @@

size_t request_len);

int rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,

size_t request_len);

-void rend_client_desc_here(const char *query);
+void rend_client_desc_here(const char *query, int rend_version);

extend_info_t *rend_client_get_random_intro(const char *query);


Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c (revision 16838)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c (working copy)
@@ -462,6 +462,8 @@

log_info(LD_REND, "Could not pick one of the responsible hidden "

"service directories to fetch descriptors, because "
"we already tried them all unsuccessfully.");

+ /* Close pending connections (unless a v0 request is still going on). */
+ rend_client_desc_here(query, 2);

return;

}


@@ -625,11 +627,14 @@

/ Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that

  • are waiting on query. If there's a working cache entry here
  • * with at least one intro point, move them to the next state;
  • * else fail them.

+ * with at least one intro point, move them to the next state. If
+ * <b>rend_version</b> is non-negative, fail connections that have
+ * requested <b>query</b> unless there are still descriptor fetch
+ * requests in progress for other descriptor versions than
+ * <b>rend_version</b>.

*/

void

-rend_client_desc_here(const char *query)
+rend_client_desc_here(const char *query, int rend_version)

{

edge_connection_t *conn;
rend_cache_entry_t *entry;

@@ -666,9 +671,15 @@

connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);

}

} else { /* 404, or fetch didn't get that far */

  • log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
  • "unavailable (try again later).", safe_str(query));
  • connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);

+ /* Unless there are requests for another descriptor version pending,
+ * close the connection. */
+ if (rend_version >= 0 &&
+ !connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query,
+ rend_version == 0 ? 2 : 0)) {
+ log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
+ "unavailable (try again later).", safe_str(query));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+ }

}

});

}

comment:5 Changed 11 years ago by arma

flyspray2trac: bug closed.

comment:6 Changed 7 years ago by nickm

Component: Tor ClientTor
Note: See TracTickets for help on using tickets.