mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
relay: Automatically Enable an IPv6 ORPort
This commit makes it that if the ORPort is set with a single port, it will bind to both global listen IPv4 and IPv6 addresses. To pin an "ORPort <PORT>" to be IPv4 or IPv6, the IPv4Only/IPv6Only flags are honored thus this will _only_ bind on IPv6 for that port value: ORPort 9050 IPv6Only Results in: [::]:9050 ORPort 9051 IPv4Only Results in: [0.0.0.0]:9051 Attempting to configure an explicit IPv4 address with IPv6Only flag is an error and vice versa. Closes #33246 Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
354eb0c010
commit
c3a0f75796
3
changes/ticket33246
Normal file
3
changes/ticket33246
Normal file
@ -0,0 +1,3 @@
|
||||
o Major feature (relay, IPv6):
|
||||
- Relays now automatically bind on IPv6 for their ORPort unless specified
|
||||
otherwise with the IPv4Only flag. Closes ticket 33246.
|
@ -5831,6 +5831,15 @@ port_parse_config(smartlist_t *out,
|
||||
int got_zero_port=0, got_nonzero_port=0;
|
||||
char *unix_socket_path = NULL;
|
||||
port_cfg_t *cfg = NULL;
|
||||
bool addr_is_explicit = false;
|
||||
int family = -1;
|
||||
|
||||
/* Parse default address. This can fail for Unix socket for instance so
|
||||
* family can be -1 and the default_addr will be made UNSPEC. */
|
||||
tor_addr_t default_addr = TOR_ADDR_NULL;
|
||||
if (defaultaddr) {
|
||||
family = tor_addr_parse(&default_addr, defaultaddr);
|
||||
}
|
||||
|
||||
/* If there's no FooPort, then maybe make a default one. */
|
||||
if (! ports) {
|
||||
@ -5907,8 +5916,8 @@ port_parse_config(smartlist_t *out,
|
||||
port = 1;
|
||||
} else if (!strcasecmp(addrport, "auto")) {
|
||||
port = CFG_AUTO_PORT;
|
||||
int af = tor_addr_parse(&addr, defaultaddr);
|
||||
tor_assert(af >= 0);
|
||||
tor_assert(family >= 0);
|
||||
tor_addr_copy(&addr, &default_addr);
|
||||
} else if (!strcasecmpend(addrport, ":auto")) {
|
||||
char *addrtmp = tor_strndup(addrport, strlen(addrport)-5);
|
||||
port = CFG_AUTO_PORT;
|
||||
@ -5924,14 +5933,20 @@ port_parse_config(smartlist_t *out,
|
||||
"9050" might be a valid address. */
|
||||
port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL);
|
||||
if (ok) {
|
||||
int af = tor_addr_parse(&addr, defaultaddr);
|
||||
tor_assert(af >= 0);
|
||||
tor_assert(family >= 0);
|
||||
tor_addr_copy(&addr, &default_addr);
|
||||
} else if (tor_addr_port_lookup(addrport, &addr, &ptmp) == 0) {
|
||||
if (ptmp == 0) {
|
||||
log_warn(LD_CONFIG, "%sPort line has address but no port", portname);
|
||||
goto err;
|
||||
}
|
||||
if (family != -1 && tor_addr_family(&addr) != family) {
|
||||
/* This means we are parsing another ORPort family but we are
|
||||
* attempting to find the default address' family ORPort. */
|
||||
goto ignore;
|
||||
}
|
||||
port = ptmp;
|
||||
addr_is_explicit = true;
|
||||
} else {
|
||||
log_warn(LD_CONFIG, "Couldn't parse address %s for %sPort",
|
||||
escaped(addrport), portname);
|
||||
@ -5942,6 +5957,7 @@ port_parse_config(smartlist_t *out,
|
||||
/* Default port_cfg_t object initialization */
|
||||
cfg = port_cfg_new(unix_socket_path ? strlen(unix_socket_path) : 0);
|
||||
|
||||
cfg->explicit_addr = addr_is_explicit;
|
||||
if (unix_socket_path && default_to_group_writable)
|
||||
cfg->is_group_writable = 1;
|
||||
|
||||
@ -5984,15 +6000,25 @@ port_parse_config(smartlist_t *out,
|
||||
}
|
||||
if (cfg->server_cfg.bind_ipv4_only &&
|
||||
tor_addr_family(&addr) != AF_INET) {
|
||||
log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
|
||||
portname);
|
||||
goto err;
|
||||
if (cfg->explicit_addr) {
|
||||
log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
|
||||
portname);
|
||||
goto err;
|
||||
}
|
||||
/* This ORPort is IPv4Only but the default address is IPv6, ignore it
|
||||
* since this will be configured with an IPv4 default address. */
|
||||
goto ignore;
|
||||
}
|
||||
if (cfg->server_cfg.bind_ipv6_only &&
|
||||
tor_addr_family(&addr) != AF_INET6) {
|
||||
log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
|
||||
portname);
|
||||
goto err;
|
||||
if (cfg->explicit_addr) {
|
||||
log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
|
||||
portname);
|
||||
goto err;
|
||||
}
|
||||
/* This ORPort is IPv6Only but the default address is IPv4, ignore it
|
||||
* since this will be configured with an IPv6 default address. */
|
||||
goto ignore;
|
||||
}
|
||||
} else {
|
||||
/* This is a client port; parse isolation options */
|
||||
@ -6205,9 +6231,10 @@ port_parse_config(smartlist_t *out,
|
||||
smartlist_add(out, cfg);
|
||||
/* out owns cfg now, don't re-use or free it */
|
||||
cfg = NULL;
|
||||
} else {
|
||||
tor_free(cfg);
|
||||
}
|
||||
|
||||
ignore:
|
||||
tor_free(cfg);
|
||||
SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
|
||||
smartlist_clear(elts);
|
||||
tor_free(addrport);
|
||||
|
@ -26,6 +26,8 @@ struct port_cfg_t {
|
||||
unsigned is_group_writable : 1;
|
||||
unsigned is_world_writable : 1;
|
||||
unsigned relax_dirmode_check : 1;
|
||||
unsigned explicit_addr : 1; /** Indicate if address was explicitly set or
|
||||
* we are using the default address. */
|
||||
|
||||
entry_port_cfg_t entry_cfg;
|
||||
|
||||
|
@ -270,6 +270,14 @@ port_parse_ports_relay(or_options_t *options,
|
||||
*msg = tor_strdup("Invalid ORPort configuration");
|
||||
goto err;
|
||||
}
|
||||
if (port_parse_config(ports,
|
||||
options->ORPort_lines,
|
||||
"OR", CONN_TYPE_OR_LISTENER,
|
||||
"[::]", 0,
|
||||
CL_PORT_SERVER_OPTIONS) < 0) {
|
||||
*msg = tor_strdup("Invalid ORPort configuration");
|
||||
goto err;
|
||||
}
|
||||
if (port_parse_config(ports,
|
||||
options->ExtORPort_lines,
|
||||
"ExtOR", CONN_TYPE_EXT_OR_LISTENER,
|
||||
|
@ -5162,6 +5162,44 @@ test_config_parse_port_config__ports__server_options(void *data)
|
||||
0, CL_PORT_SERVER_OPTIONS);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
|
||||
/* Default address is IPv4 but pass IPv6Only flag. Should be ignored. */
|
||||
config_free_lines(config_port_invalid); config_port_invalid = NULL;
|
||||
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
|
||||
smartlist_clear(slout);
|
||||
config_port_invalid = mock_config_line("ORPort", "9050 IPv6Only");
|
||||
ret = port_parse_config(slout, config_port_invalid, "ORPort", 0,
|
||||
"127.0.0.1", 0, CL_PORT_SERVER_OPTIONS);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
|
||||
/* Default address is IPv6 but pass IPv4Only flag. Should be ignored. */
|
||||
config_free_lines(config_port_invalid); config_port_invalid = NULL;
|
||||
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
|
||||
smartlist_clear(slout);
|
||||
config_port_invalid = mock_config_line("ORPort", "9050 IPv4Only");
|
||||
ret = port_parse_config(slout, config_port_invalid, "ORPort", 0,
|
||||
"[::]", 0, CL_PORT_SERVER_OPTIONS);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
|
||||
/* Explicit address is IPv6 but pass IPv4Only flag. Should error. */
|
||||
config_free_lines(config_port_invalid); config_port_invalid = NULL;
|
||||
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
|
||||
smartlist_clear(slout);
|
||||
config_port_invalid = mock_config_line("ORPort",
|
||||
"[4242::4242]:9050 IPv4Only");
|
||||
ret = port_parse_config(slout, config_port_invalid, "ORPort", 0,
|
||||
"[::]", 0, CL_PORT_SERVER_OPTIONS);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
|
||||
/* Explicit address is IPv4 but pass IPv6Only flag. Should error. */
|
||||
config_free_lines(config_port_invalid); config_port_invalid = NULL;
|
||||
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
|
||||
smartlist_clear(slout);
|
||||
config_port_invalid = mock_config_line("ORPort",
|
||||
"1.2.3.4:9050 IPv6Only");
|
||||
ret = port_parse_config(slout, config_port_invalid, "ORPort", 0,
|
||||
"127.0.0.1", 0, CL_PORT_SERVER_OPTIONS);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
|
||||
done:
|
||||
if (slout)
|
||||
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
|
||||
|
Loading…
Reference in New Issue
Block a user