mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 23:53:32 +01:00
Make Single Onion Service intro points respect ReachableAddresses
This commit is contained in:
parent
b560f852f2
commit
75ebbed557
@ -5077,7 +5077,8 @@ typedef struct rend_encoded_v2_service_descriptor_t {
|
|||||||
* the service side) and in rend_service_descriptor_t (on both the
|
* the service side) and in rend_service_descriptor_t (on both the
|
||||||
* client and service side). */
|
* client and service side). */
|
||||||
typedef struct rend_intro_point_t {
|
typedef struct rend_intro_point_t {
|
||||||
extend_info_t *extend_info; /**< Extend info of this introduction point. */
|
extend_info_t *extend_info; /**< Extend info for connecting to this
|
||||||
|
* introduction point via a multi-hop path. */
|
||||||
crypto_pk_t *intro_key; /**< Introduction key that replaces the service
|
crypto_pk_t *intro_key; /**< Introduction key that replaces the service
|
||||||
* key, if this descriptor is V2. */
|
* key, if this descriptor is V2. */
|
||||||
|
|
||||||
|
@ -1581,13 +1581,25 @@ static int
|
|||||||
rend_service_use_direct_connection(const or_options_t* options,
|
rend_service_use_direct_connection(const or_options_t* options,
|
||||||
const extend_info_t* ei)
|
const extend_info_t* ei)
|
||||||
{
|
{
|
||||||
/* The prefer_ipv6 argument to fascist_firewall_allows_address_addr is
|
/* We'll connect directly all reachable addresses, whether preferred or not.
|
||||||
|
* The prefer_ipv6 argument to fascist_firewall_allows_address_addr is
|
||||||
* ignored, because pref_only is 0. */
|
* ignored, because pref_only is 0. */
|
||||||
return (rend_service_allow_direct_connection(options) &&
|
return (rend_service_allow_non_anonymous_connection(options) &&
|
||||||
fascist_firewall_allows_address_addr(&ei->addr, ei->port,
|
fascist_firewall_allows_address_addr(&ei->addr, ei->port,
|
||||||
FIREWALL_OR_CONNECTION, 0, 0));
|
FIREWALL_OR_CONNECTION, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Like rend_service_use_direct_connection, but to a node. */
|
||||||
|
static int
|
||||||
|
rend_service_use_direct_connection_node(const or_options_t* options,
|
||||||
|
const node_t* node)
|
||||||
|
{
|
||||||
|
/* We'll connect directly all reachable addresses, whether preferred or not.
|
||||||
|
*/
|
||||||
|
return (rend_service_allow_non_anonymous_connection(options) &&
|
||||||
|
fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, 0));
|
||||||
|
}
|
||||||
|
|
||||||
/******
|
/******
|
||||||
* Handle cells
|
* Handle cells
|
||||||
******/
|
******/
|
||||||
@ -2797,29 +2809,71 @@ rend_service_launch_establish_intro(rend_service_t *service,
|
|||||||
{
|
{
|
||||||
origin_circuit_t *launched;
|
origin_circuit_t *launched;
|
||||||
int flags = CIRCLAUNCH_NEED_UPTIME|CIRCLAUNCH_IS_INTERNAL;
|
int flags = CIRCLAUNCH_NEED_UPTIME|CIRCLAUNCH_IS_INTERNAL;
|
||||||
|
const or_options_t *options = get_options();
|
||||||
|
extend_info_t *launch_ei = intro->extend_info;
|
||||||
|
extend_info_t *direct_ei = NULL;
|
||||||
|
|
||||||
if (rend_service_allow_direct_connection(get_options())) {
|
/* Are we in single onion mode? */
|
||||||
flags = flags | CIRCLAUNCH_ONEHOP_TUNNEL;
|
if (rend_service_allow_non_anonymous_connection(options)) {
|
||||||
|
/* Do we have a descriptor for the node?
|
||||||
|
* We've either just chosen it from the consensus, or we've just reviewed
|
||||||
|
* our intro points to see which ones are still valid, and deleted the ones
|
||||||
|
* that aren't in the consensus any more. */
|
||||||
|
const node_t *node = node_get_by_id(launch_ei->identity_digest);
|
||||||
|
if (BUG(!node)) {
|
||||||
|
/* The service has kept an intro point after it went missing from the
|
||||||
|
* consensus. If we did anything else here, it would be a consensus
|
||||||
|
* distinguisher. Which are less of an issue for single onion services,
|
||||||
|
* but still a bug. */
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
/* Can we connect to the node directly? If so, replace launch_ei
|
||||||
|
* (a multi-hop extend_info) with one suitable for direct connection. */
|
||||||
|
if (rend_service_use_direct_connection_node(options, node)) {
|
||||||
|
direct_ei = extend_info_from_node(node, 1);
|
||||||
|
if (BUG(!direct_ei)) {
|
||||||
|
/* rend_service_use_direct_connection_node and extend_info_from_node
|
||||||
|
* disagree about which addresses on this node are permitted. This
|
||||||
|
* should never happen. Avoiding the connection is a safe response. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
flags = flags | CIRCLAUNCH_ONEHOP_TUNNEL;
|
||||||
|
launch_ei = direct_ei;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* launch_ei is either intro->extend_info, or has been replaced with a valid
|
||||||
|
* extend_info for single onion service direct connection. */
|
||||||
|
tor_assert(launch_ei);
|
||||||
|
/* We must have the same intro when making a direct connection. */
|
||||||
|
tor_assert(tor_memeq(intro->extend_info->identity_digest,
|
||||||
|
launch_ei->identity_digest,
|
||||||
|
DIGEST_LEN));
|
||||||
|
|
||||||
log_info(LD_REND,
|
log_info(LD_REND,
|
||||||
"Launching circuit to introduction point %s for service %s",
|
"Launching circuit to introduction point %s%s%s for service %s",
|
||||||
safe_str_client(extend_info_describe(intro->extend_info)),
|
safe_str_client(extend_info_describe(intro->extend_info)),
|
||||||
|
direct_ei ? " via direct address " : "",
|
||||||
|
direct_ei ? safe_str_client(extend_info_describe(direct_ei)) : "",
|
||||||
service->service_id);
|
service->service_id);
|
||||||
|
|
||||||
rep_hist_note_used_internal(time(NULL), 1, 0);
|
rep_hist_note_used_internal(time(NULL), 1, 0);
|
||||||
|
|
||||||
++service->n_intro_circuits_launched;
|
++service->n_intro_circuits_launched;
|
||||||
launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
|
launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
|
||||||
intro->extend_info, flags);
|
launch_ei, flags);
|
||||||
|
|
||||||
if (!launched) {
|
if (!launched) {
|
||||||
log_info(LD_REND,
|
log_info(LD_REND,
|
||||||
"Can't launch circuit to establish introduction at %s.",
|
"Can't launch circuit to establish introduction at %s%s%s.",
|
||||||
safe_str_client(extend_info_describe(intro->extend_info)));
|
safe_str_client(extend_info_describe(intro->extend_info)),
|
||||||
|
direct_ei ? " via direct address " : "",
|
||||||
|
direct_ei ? safe_str_client(extend_info_describe(direct_ei)) : ""
|
||||||
|
);
|
||||||
|
extend_info_free(direct_ei);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* We must have the same exit node even if cannibalized. */
|
/* We must have the same exit node even if cannibalized or direct connection.
|
||||||
|
*/
|
||||||
tor_assert(tor_memeq(intro->extend_info->identity_digest,
|
tor_assert(tor_memeq(intro->extend_info->identity_digest,
|
||||||
launched->build_state->chosen_exit->identity_digest,
|
launched->build_state->chosen_exit->identity_digest,
|
||||||
DIGEST_LEN));
|
DIGEST_LEN));
|
||||||
@ -2830,6 +2884,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
|
|||||||
launched->intro_key = crypto_pk_dup_key(intro->intro_key);
|
launched->intro_key = crypto_pk_dup_key(intro->intro_key);
|
||||||
if (launched->base_.state == CIRCUIT_STATE_OPEN)
|
if (launched->base_.state == CIRCUIT_STATE_OPEN)
|
||||||
rend_service_intro_has_opened(launched);
|
rend_service_intro_has_opened(launched);
|
||||||
|
extend_info_free(direct_ei);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3669,6 +3724,9 @@ rend_consider_services_intro_points(void)
|
|||||||
int i;
|
int i;
|
||||||
time_t now;
|
time_t now;
|
||||||
const or_options_t *options = get_options();
|
const or_options_t *options = get_options();
|
||||||
|
/* Are we in single onion mode? */
|
||||||
|
const int allow_direct = rend_service_allow_non_anonymous_connection(
|
||||||
|
get_options());
|
||||||
/* List of nodes we need to _exclude_ when choosing a new node to
|
/* List of nodes we need to _exclude_ when choosing a new node to
|
||||||
* establish an intro point to. */
|
* establish an intro point to. */
|
||||||
smartlist_t *exclude_nodes;
|
smartlist_t *exclude_nodes;
|
||||||
@ -3764,8 +3822,24 @@ rend_consider_services_intro_points(void)
|
|||||||
router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
|
router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
|
||||||
if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION)
|
if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION)
|
||||||
flags |= CRN_ALLOW_INVALID;
|
flags |= CRN_ALLOW_INVALID;
|
||||||
|
router_crn_flags_t direct_flags = flags;
|
||||||
|
direct_flags |= CRN_PREF_ADDR;
|
||||||
|
direct_flags |= CRN_DIRECT_CONN;
|
||||||
|
|
||||||
|
node = router_choose_random_node(exclude_nodes,
|
||||||
|
options->ExcludeNodes,
|
||||||
|
allow_direct ? direct_flags : flags);
|
||||||
|
/* If we are in single onion mode, retry node selection for a 3-hop
|
||||||
|
* path */
|
||||||
|
if (allow_direct && !node) {
|
||||||
|
log_info(LD_REND,
|
||||||
|
"Unable to find an intro point that we can connect to "
|
||||||
|
"directly for %s, falling back to a 3-hop path.",
|
||||||
|
safe_str_client(service->service_id));
|
||||||
node = router_choose_random_node(exclude_nodes,
|
node = router_choose_random_node(exclude_nodes,
|
||||||
options->ExcludeNodes, flags);
|
options->ExcludeNodes, flags);
|
||||||
|
}
|
||||||
|
|
||||||
if (!node) {
|
if (!node) {
|
||||||
log_warn(LD_REND,
|
log_warn(LD_REND,
|
||||||
"We only have %d introduction points established for %s; "
|
"We only have %d introduction points established for %s; "
|
||||||
@ -3779,8 +3853,10 @@ rend_consider_services_intro_points(void)
|
|||||||
* pick it again in the next iteration. */
|
* pick it again in the next iteration. */
|
||||||
smartlist_add(exclude_nodes, (void*)node);
|
smartlist_add(exclude_nodes, (void*)node);
|
||||||
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
|
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
|
||||||
intro->extend_info = extend_info_from_node(node,
|
/* extend_info is for clients, so we want the multi-hop primary ORPort,
|
||||||
rend_service_allow_direct_connection(options));
|
* even if we are a single onion service and intend to connect to it
|
||||||
|
* directly ourselves. */
|
||||||
|
intro->extend_info = extend_info_from_node(node, 0);
|
||||||
intro->intro_key = crypto_pk_new();
|
intro->intro_key = crypto_pk_new();
|
||||||
const int fail = crypto_pk_generate_key(intro->intro_key);
|
const int fail = crypto_pk_generate_key(intro->intro_key);
|
||||||
tor_assert(!fail);
|
tor_assert(!fail);
|
||||||
|
Loading…
Reference in New Issue
Block a user