mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
addr: Attempt to learn our address with ORPort
If no Address statement are found in the configuration file, attempt to learn our address by looking at the ORPort address if any. Specifying an address is optional so if we can't find one, it is fine, we move on to the next discovery mechanism. Note that specifying a hostname on the ORPort is not yet supported at this commit. Closes #33236 Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
bc63f59f3c
commit
809c864707
4
changes/ticket33236
Normal file
4
changes/ticket33236
Normal file
@ -0,0 +1,4 @@
|
||||
o Minor feature (relay, address discovery):
|
||||
- If Address is not found in torrc, attempt to learn our address with the
|
||||
configured ORPort address if any. Closes ticket 33236.
|
||||
|
@ -370,6 +370,63 @@ get_address_from_interface(const or_options_t *options, int warn_severity,
|
||||
return FN_RET_OK;
|
||||
}
|
||||
|
||||
/** @brief Get IP address from the ORPort (if any).
|
||||
*
|
||||
* @param options Global configuration options.
|
||||
* @param warn_severity Log level that should be used on error.
|
||||
* @param family IP address family. Only AF_INET and AF_INET6 are supported.
|
||||
* @param method_out OUT: Always "CONFIGURED_ORPORT" on success which is
|
||||
* detailed in the control-spec.txt as actions
|
||||
* for "STATUS_SERVER".
|
||||
* @param hostname_out OUT: String containing the ORPort hostname if any.
|
||||
* @param addr_out OUT: Tor address found if any.
|
||||
*
|
||||
* @return Return 0 on success that is an address has been found. Return
|
||||
* error code ERR_* found at the top of the file.
|
||||
*/
|
||||
static fn_address_ret_t
|
||||
get_address_from_orport(const or_options_t *options, int warn_severity,
|
||||
int family, const char **method_out,
|
||||
char **hostname_out, tor_addr_t *addr_out)
|
||||
{
|
||||
int ret;
|
||||
const tor_addr_t *addr;
|
||||
|
||||
tor_assert(method_out);
|
||||
tor_assert(hostname_out);
|
||||
tor_assert(addr_out);
|
||||
|
||||
log_debug(LD_CONFIG, "Attempting to get address from ORPort");
|
||||
|
||||
if (!options->ORPort_set) {
|
||||
log_info(LD_CONFIG, "No ORPort found in configuration.");
|
||||
/* No ORPort statement, inform caller to try next method. */
|
||||
return FN_RET_NEXT;
|
||||
}
|
||||
|
||||
/* Get ORPort for requested family. */
|
||||
addr = get_orport_addr(family);
|
||||
if (!addr) {
|
||||
/* No address configured for the ORPort. Ignore. */
|
||||
return FN_RET_NEXT;
|
||||
}
|
||||
|
||||
/* We found the ORPort address. Just make sure it can be used. */
|
||||
ret = address_can_be_used(addr, options, warn_severity, true);
|
||||
if (ret < 0) {
|
||||
/* Unable to use address. Inform caller to try next method. */
|
||||
return FN_RET_NEXT;
|
||||
}
|
||||
|
||||
/* Found it! */
|
||||
*method_out = "CONFIGURED_ORPORT";
|
||||
tor_addr_copy(addr_out, addr);
|
||||
|
||||
log_fn(warn_severity, LD_CONFIG, "Address found from ORPort: %s",
|
||||
fmt_addr(addr_out));
|
||||
return FN_RET_OK;
|
||||
}
|
||||
|
||||
/** @brief Update the last resolved address cache using the given address.
|
||||
*
|
||||
* A log notice is emitted if the given address has changed from before. Not
|
||||
@ -450,6 +507,7 @@ static fn_address_ret_t
|
||||
{
|
||||
/* These functions are in order for our find address algorithm. */
|
||||
get_address_from_config,
|
||||
get_address_from_orport,
|
||||
get_address_from_interface,
|
||||
get_address_from_hostname,
|
||||
};
|
||||
|
@ -9,8 +9,14 @@
|
||||
#ifndef TOR_CONFIG_RESOLVE_ADDR_H
|
||||
#define TOR_CONFIG_RESOLVE_ADDR_H
|
||||
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
|
||||
#include "app/config/or_options_st.h"
|
||||
|
||||
#define get_orport_addr(family) \
|
||||
(get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER, family))
|
||||
|
||||
bool find_my_address(const or_options_t *options, int family,
|
||||
int warn_severity, tor_addr_t *addr_out,
|
||||
const char **method_out, char **hostname_out);
|
||||
|
@ -1259,6 +1259,8 @@ get_interface_address6_failure(int severity, sa_family_t family,
|
||||
#define CLEANUP_FOUND_ADDRESS \
|
||||
do { \
|
||||
config_free_lines(options->Address); \
|
||||
config_free_lines(options->ORPort_lines); \
|
||||
options->ORPort_set = 0; \
|
||||
tor_free(options->DirAuthorities); \
|
||||
tor_free(hostname_out); \
|
||||
tor_addr_make_unspec(&resolved_addr); \
|
||||
@ -1418,6 +1420,7 @@ typedef struct find_my_address_params_t {
|
||||
int family;
|
||||
const char *public_ip;
|
||||
const char *internal_ip;
|
||||
const char *orport;
|
||||
} find_my_address_params_t;
|
||||
|
||||
static find_my_address_params_t addr_param_v4 = {
|
||||
@ -1430,8 +1433,8 @@ static find_my_address_params_t addr_param_v4 = {
|
||||
static find_my_address_params_t addr_param_v6 = {
|
||||
.idx = 1,
|
||||
.family = AF_INET6,
|
||||
.public_ip = "4242::4242",
|
||||
.internal_ip = "::1",
|
||||
.public_ip = "[4242::4242]",
|
||||
.internal_ip = "[::1]",
|
||||
};
|
||||
|
||||
static void
|
||||
@ -1733,6 +1736,75 @@ test_config_find_my_address(void *arg)
|
||||
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
|
||||
CLEANUP_FOUND_ADDRESS;
|
||||
|
||||
/*
|
||||
* Case 13:
|
||||
* 1. Address is NULL.
|
||||
* 2. ORPort has a valid public address.
|
||||
*/
|
||||
{
|
||||
char *msg = NULL;
|
||||
int n, w, ret;
|
||||
char *orport_line = NULL;
|
||||
|
||||
options->Address = NULL;
|
||||
tor_asprintf(&orport_line, "%s:9001", p->public_ip);
|
||||
config_line_append(&options->ORPort_lines, "ORPort", orport_line);
|
||||
tor_free(orport_line);
|
||||
|
||||
if (p->family == AF_INET6) {
|
||||
/* XXX: Tor does _not_ allow an IPv6 only ORPort thus we need to add a
|
||||
* bogus IPv4 at the moment. */
|
||||
config_line_append(&options->ORPort_lines, "ORPort", "1.1.1.1:9001");
|
||||
}
|
||||
|
||||
ret = parse_ports(options, 0, &msg, &n, &w);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
tor_addr_parse(&test_addr, p->public_ip);
|
||||
}
|
||||
|
||||
retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
VALIDATE_FOUND_ADDRESS(true, "CONFIGURED_ORPORT", NULL);
|
||||
CLEANUP_FOUND_ADDRESS;
|
||||
|
||||
/*
|
||||
* Case 14:
|
||||
* 1. Address is NULL.
|
||||
* 2. ORPort has an internal address thus fails.
|
||||
* 3. Interface as a valid address.
|
||||
*/
|
||||
{
|
||||
char *msg = NULL;
|
||||
int n, w, ret;
|
||||
char *orport_line = NULL;
|
||||
|
||||
options->Address = NULL;
|
||||
tor_asprintf(&orport_line, "%s:9001", p->internal_ip);
|
||||
config_line_append(&options->ORPort_lines, "ORPort", orport_line);
|
||||
tor_free(orport_line);
|
||||
|
||||
if (p->family == AF_INET6) {
|
||||
/* XXX: Tor does _not_ allow an IPv6 only ORPort thus we need to add a
|
||||
* bogus IPv4 at the moment. */
|
||||
config_line_append(&options->ORPort_lines, "ORPort", "1.1.1.1:9001");
|
||||
}
|
||||
|
||||
ret = parse_ports(options, 0, &msg, &n, &w);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
}
|
||||
tor_addr_parse(&test_addr, ret_get_interface_address6_08080808[p->idx]);
|
||||
|
||||
MOCK(get_interface_address6, get_interface_address6_08080808);
|
||||
|
||||
prev_n_get_interface_address6 = n_get_interface_address6;
|
||||
|
||||
retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
|
||||
&method_used, &hostname_out);
|
||||
|
||||
tt_int_op(n_get_interface_address6, OP_EQ, ++prev_n_get_interface_address6);
|
||||
VALIDATE_FOUND_ADDRESS(true, "INTERFACE", NULL);
|
||||
CLEANUP_FOUND_ADDRESS;
|
||||
|
||||
UNMOCK(get_interface_address6);
|
||||
UNMOCK(tor_gethostname);
|
||||
UNMOCK(tor_addr_lookup);
|
||||
|
Loading…
Reference in New Issue
Block a user