mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 14:23:30 +01:00
Fall back to direct descriptor request to bridges when
requests to authorities fail due to a network error. Bug#1138 "When a Tor client starts up using a bridge, and UpdateBridgesFromAuthority is set, Tor will go to the authority first and look up the bridge by fingerprint. If the bridge authority is filtered, Tor will never notice that the bridge authority lookup failed. So it will never fall back." Add connection_dir_bridge_routerdesc_failed(), a function for unpacking the bridge information from a failed request, and ensure connection_dir_request_failed() calls it if the failed request was for a bridge descriptor. Test: 1. for ip in `grep -iR 'router ' cached-descriptors|cut -d ' ' -f 3`; do sudo iptables -A OUTPUT -p tcp -d $ip -j DROP; done 2. remove all files from user tor directory 3. Put the following in torrc: UseBridges 1 UpdateBridgesFromAuthority 1 Bridge 85.108.88.19:443 7E1B28DB47C175392A0E8E4A287C7CB8686575B7 4. Launch tor - it should fall back to downloading descriptors directly from the bridge. Initial patch reviewed and corrected by mingw-san.
This commit is contained in:
parent
a207d9db4c
commit
d6744d611f
5
changes/bug1138
Normal file
5
changes/bug1138
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
o Major bugfixes:
|
||||||
|
- Fall back to direct descriptor request to bridges when
|
||||||
|
requests to authorities fail due to a network error.
|
||||||
|
Bugfix in 0.2.1.19, closes bug 1138.
|
||||||
|
|
@ -67,8 +67,10 @@ static void http_set_address_origin(const char *headers, connection_t *conn);
|
|||||||
static void connection_dir_download_networkstatus_failed(
|
static void connection_dir_download_networkstatus_failed(
|
||||||
dir_connection_t *conn, int status_code);
|
dir_connection_t *conn, int status_code);
|
||||||
static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
|
static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
|
||||||
|
static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
|
||||||
static void connection_dir_download_cert_failed(
|
static void connection_dir_download_cert_failed(
|
||||||
dir_connection_t *conn, int status_code);
|
dir_connection_t *conn, int status_code);
|
||||||
|
static void connection_dir_retry_bridges(smartlist_t* failed, int was_ei);
|
||||||
static void dir_networkstatus_download_failed(smartlist_t *failed,
|
static void dir_networkstatus_download_failed(smartlist_t *failed,
|
||||||
int status_code);
|
int status_code);
|
||||||
static void dir_routerdesc_download_failed(smartlist_t *failed,
|
static void dir_routerdesc_download_failed(smartlist_t *failed,
|
||||||
@ -592,6 +594,8 @@ connection_dir_request_failed(dir_connection_t *conn)
|
|||||||
conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
|
conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
|
||||||
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
|
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
|
||||||
conn->_base.address);
|
conn->_base.address);
|
||||||
|
if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
|
||||||
|
connection_dir_bridge_routerdesc_failed(conn);
|
||||||
connection_dir_download_routerdesc_failed(conn);
|
connection_dir_download_routerdesc_failed(conn);
|
||||||
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
|
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
|
||||||
networkstatus_consensus_download_failed(0);
|
networkstatus_consensus_download_failed(0);
|
||||||
@ -645,6 +649,25 @@ connection_dir_download_networkstatus_failed(dir_connection_t *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Helper: Attempt to fetch directly the descriptors of each bridge
|
||||||
|
* listed in <b>failed</b>.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
connection_dir_retry_bridges(smartlist_t* failed, int was_ei)
|
||||||
|
{
|
||||||
|
char digest[DIGEST_LEN];
|
||||||
|
tor_assert(!was_ei); /* not supported yet */
|
||||||
|
SMARTLIST_FOREACH(failed, const char *, cp,
|
||||||
|
{
|
||||||
|
if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
|
||||||
|
log_warn(LD_BUG, "Malformed fingerprint in list: %s",
|
||||||
|
escaped(cp));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
retry_bridge_descriptor_fetch_directly(digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** Called when an attempt to download one or more router descriptors
|
/** Called when an attempt to download one or more router descriptors
|
||||||
* or extra-info documents on connection <b>conn</b> failed.
|
* or extra-info documents on connection <b>conn</b> failed.
|
||||||
*/
|
*/
|
||||||
@ -662,6 +685,33 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn)
|
|||||||
(void) conn;
|
(void) conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Called when an attempt to download a bridge's routerdesc from
|
||||||
|
* one of the authorities failed due to a network error. If
|
||||||
|
* possible attempt to download descriptors from the bridge directly.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
|
||||||
|
{
|
||||||
|
int was_ei;
|
||||||
|
smartlist_t *which = NULL;
|
||||||
|
|
||||||
|
/* Requests for bridge descriptors are in the form 'fp/', so ignore
|
||||||
|
anything else. */
|
||||||
|
if (conn->requested_resource && strcmpstart(conn->requested_resource,"fp/"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
which = smartlist_create();
|
||||||
|
dir_split_resource_into_fingerprints(conn->requested_resource + 3,
|
||||||
|
which, NULL, 0);
|
||||||
|
|
||||||
|
was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
|
||||||
|
if (smartlist_len(which)) {
|
||||||
|
connection_dir_retry_bridges(which, was_ei);
|
||||||
|
SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
|
||||||
|
}
|
||||||
|
smartlist_free(which);
|
||||||
|
}
|
||||||
|
|
||||||
/** Called when an attempt to fetch a certificate fails. */
|
/** Called when an attempt to fetch a certificate fails. */
|
||||||
static void
|
static void
|
||||||
connection_dir_download_cert_failed(dir_connection_t *conn, int status)
|
connection_dir_download_cert_failed(dir_connection_t *conn, int status)
|
||||||
@ -3498,18 +3548,8 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
|
|||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
int server = directory_fetches_from_authorities(get_options());
|
int server = directory_fetches_from_authorities(get_options());
|
||||||
if (!was_descriptor_digests) {
|
if (!was_descriptor_digests) {
|
||||||
if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
|
if (router_purpose == ROUTER_PURPOSE_BRIDGE)
|
||||||
tor_assert(!was_extrainfo); /* not supported yet */
|
connection_dir_retry_bridges(failed, was_extrainfo);
|
||||||
SMARTLIST_FOREACH(failed, const char *, cp,
|
|
||||||
{
|
|
||||||
if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
|
|
||||||
log_warn(LD_BUG, "Malformed fingerprint in list: %s",
|
|
||||||
escaped(cp));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
retry_bridge_descriptor_fetch_directly(digest);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return; /* FFFF should implement for other-than-router-purpose someday */
|
return; /* FFFF should implement for other-than-router-purpose someday */
|
||||||
}
|
}
|
||||||
SMARTLIST_FOREACH(failed, const char *, cp,
|
SMARTLIST_FOREACH(failed, const char *, cp,
|
||||||
|
Loading…
Reference in New Issue
Block a user