Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

25691/25692: Distinguish "has preferred descriptor" from "has any descriptor" #48

Closed
wants to merge 18 commits into from

Conversation

Labels
None yet
Projects
None yet
2 participants
@nmathewson
Copy link
Contributor

@nmathewson nmathewson commented Apr 16, 2018

No description provided.

nmathewson added 6 commits Apr 16, 2018
This patch adds a new node_has_preferred_descriptor() function, and
replaces most users of node_has_descriptor() with it.  That's an
important change, since as of d1874b4 (our fix for #25213),
we are willing to say that a node has _some_ descriptor, but not the
_right_ descriptor for a particular use case.

Part of a fix for 25691 and 25692.
In router_add_running_nodes_to_smartlist(), we had an inline
implementation of the logic from node_has_descriptor(), which should
be changed to node_has_preferred_descriptor().
In order to fix 25691 and 25692, we need to pass the "direct_conn"
flag to more places -- particularly when choosing single-hop
tunnels.  The right way to do this involves having a couple more
functions accept router_crn_flags_t, rather than a big list of
boolean arguments.

This commit also makes sure that choose_good_exit_server_general()
honors the direct_conn flag, to fix 25691 and 25692.
Changing the name of this function should help keep us from misusing
it when node_has_preferred_descriptor() would be more appropriate.
It tried to pick nodes for which only routerinfo_t items are set,
but without setting UseMicroDescriptors to 0.  This won't work any
more, now that we're strict about using the right descriptor types
due to 25691/25692/25213.
Copy link
Contributor

@teor2345 teor2345 left a comment

There are a few places where I think we should be using node_has_preferred_descriptor(). The large changes should probably be split into other tickets.

Otherwise, it looks good, and it works. Most of my comments ask for comment changes.

/* Otherwise we need an md. */
if (node->rs == NULL || node->md == NULL)
return NULL;
if (!node_has_preferred_descriptor(node, for_direct_connect)) {
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

An earlier fix for this bug changed how for_direct_connect works.
Do we need to update this part of the function comment?

     May return NULL if there is not enough
  * info about <b>node</b> to extend to it--for example, if there is no
  * routerinfo_t or microdesc_t, or if for_direct_connect is true and none of
  * the node's addresses are allowed by tor's firewall and IP version config.

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

I think we do. Done with 1d06778.

@@ -192,7 +192,7 @@ guard_has_descriptor(const entry_guard_t *guard)
const node_t *node = node_get_by_id(guard->identity);
if (!node)
return 0;
return node_has_descriptor(node);
return node_has_preferred_descriptor(node, 1);
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

Function comment: "know a preferred descriptor"

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

cea472f fixes this.

@@ -1281,7 +1281,7 @@ node_has_hsdir_index(const node_t *node)

/* A node can't have an HSDir index without a descriptor since we need desc
* to get its ed25519 key */
if (!node_has_descriptor(node)) {
if (!node_has_preferred_descriptor(node, 0)) {
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

Note: Using for_direct_connect = 0 is always correct for the HSDir hash ring, because we use non-bridge descriptors for the HSDir hash ring. This is true even though Tor2web connects directly to HSDirs.

Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

Hmm, does this need a comment?

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

5398bf0 has that comment.

@@ -1617,7 +1617,7 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str)
time_t last = hs_lookup_last_hid_serv_request(dir, req_key_str, 0, 0);
const node_t *node = node_get_by_id(dir->identity_digest);
if (last + hs_hsdir_requery_period(options) >= now ||
!node || !node_has_descriptor(node)) {
!node || !node_has_preferred_descriptor(node, 0)) {
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

Does this need a comment about Tor2web, similar to the last comment?

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

03494da is the fixup for this.

@@ -1139,6 +1140,27 @@ node_has_descriptor(const node_t *node)
(node->rs && node->md));
}

/** DOCDOC */
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

Please document the function

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

80ac049 does that.

src/or/control.c Outdated
@@ -3498,7 +3498,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
goto done;
}
if (!node_has_descriptor(node)) {
if (!node_has_any_descriptor(node)) {
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

The log message at line 3525 is now incorrect:

                "controller tried to connect to a node that doesn't have any "
                "addresses that are allowed by the firewall configuration; "
                "circuit marked for closing."

We can fail because we are missing the preferred descriptor for the node, too.
Should we do int first_node = zero_circ; first_node = 0; in this loop, too?

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

e480c11 does it here.

@@ -1134,7 +1134,7 @@ node_is_dir(const node_t *node)
/** Return true iff <b>node</b> has either kind of usable descriptor -- that
* is, a routerdescriptor or a microdescriptor. */
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

Add to the function comment: You should probably use node_has_preferred_descriptor() instead of this function.

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

f5a472c does that.

@@ -2243,7 +2243,8 @@ compute_frac_paths_available(const networkstatus_t *consensus,
nu);

SMARTLIST_FOREACH_BEGIN(myexits_unflagged, const node_t *, node) {
if (node_has_descriptor(node) && node_exit_policy_rejects_all(node)) {
if (node_has_any_descriptor(node) &&
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

count_usable_descriptors() counts mds if we have an md consensus, and ris if we have an ns consensus.
So I think we want node_has_preferred_descriptor(node, 0) here.

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

looks good; done in 632899c.

@@ -2758,15 +2758,15 @@ frac_nodes_with_descriptors(const smartlist_t *sl,
total <= 0.0) {
int n_with_descs = 0;
SMARTLIST_FOREACH(sl, const node_t *, node, {
if (node_has_descriptor(node))
if (node_has_any_descriptor(node))
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

We should pass for_direct_conn into this function, and use node_has_preferred_descriptor().

For the mid and exit case:
We won't bootstrap unless we have enough actual mid and exit bandwidth, even if we have mids or exits listed as our bridges.

For the guard case:
The guard case is unchanged for non-bridge clients.

The bridge client case could be tricky, because:

  1. compute_frac_paths_available() only checks guard-flagged nodes, not bridges
  2. even if it did check bridges, they don't have bandwidths
  3. even if we used a weight of 1 for each bridge, we don't require 65% of bridges to be up to bootstrap

To workaround this issue, I suggest we make f_guard = 1.0 in compute_frac_paths_available() if we are using bridges, and have at least one bridge with the preferred descriptor.

Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

This change might cause bootstrapping issues. Let's defer it to 0.3.4 Tor: unspecified in another ticket?

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

Opened trac:25886 for this.

@@ -305,7 +305,7 @@ helper_add_hsdir_to_networkstatus(networkstatus_t *ns,
node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
tt_assert(node);
node->rs = rs;
/* We need this to exist for node_has_descriptor() to return true. */
/* We need this to exist for node_has_any_descriptor() to return true. */
Copy link
Contributor

@teor2345 teor2345 Apr 18, 2018

hsdirs use node_has_preferred_descriptor(), so I think this comment is wrong

Copy link
Contributor Author

@nmathewson nmathewson Apr 22, 2018

3455d87 is the fix here.

nmathewson added 10 commits Apr 22, 2018
Fix comment for guard_has_descriptor(), per code review from teor.
Add a comment explaining why for_direct_connect should be zero when
building hsdir hash ring.
Another comment about hsdir index and for_direct_connnect.
Document that you shouldn't use node_has_any_descriptor() for most things.
Suggested by teor during code review for 25691.
Should use has_preferred_descriptor() in count_frac_paths_available

(Especially since this usage is about exit nodes)
@teor2345
Copy link
Contributor

@teor2345 teor2345 commented Apr 22, 2018

@teor2345
Copy link
Contributor

@teor2345 teor2345 commented Apr 22, 2018

@nmathewson
Copy link
Contributor Author

@nmathewson nmathewson commented May 7, 2018

This was squashed and merged with 6773102

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment