mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
Make option OutboundBindAddress accept IPv6 addresses too.
Implements ticket 6786.
This commit is contained in:
parent
cff3b8c93c
commit
1cbf45bed1
@ -472,8 +472,10 @@ GENERAL OPTIONS
|
||||
**OutboundBindAddress** __IP__::
|
||||
Make all outbound connections originate from the IP address specified. This
|
||||
is only useful when you have multiple network interfaces, and you want all
|
||||
of Tor's outgoing connections to use a single one. This setting will be
|
||||
ignored for connections to the loopback addresses (127.0.0.0/8 and ::1).
|
||||
of Tor's outgoing connections to use a single one. This option may
|
||||
be used twice, once with an IPv4 address and once with an IPv6 address.
|
||||
This setting will be ignored for connections to the loopback addresses
|
||||
(127.0.0.0/8 and ::1).
|
||||
|
||||
**PidFile** __FILE__::
|
||||
On startup, write our PID to FILE. On clean shutdown, remove
|
||||
|
@ -302,7 +302,7 @@ static config_var_t _option_vars[] = {
|
||||
V(NumEntryGuards, UINT, "3"),
|
||||
V(ORListenAddress, LINELIST, NULL),
|
||||
VPORT(ORPort, LINELIST, NULL),
|
||||
V(OutboundBindAddress, STRING, NULL),
|
||||
V(OutboundBindAddress, LINELIST, NULL),
|
||||
|
||||
V(PathBiasCircThreshold, INT, "-1"),
|
||||
V(PathBiasNoticeRate, DOUBLE, "-1"),
|
||||
@ -474,6 +474,8 @@ static int options_init_logs(or_options_t *options, int validate_only);
|
||||
|
||||
static void init_libevent(const or_options_t *options);
|
||||
static int opt_streq(const char *s1, const char *s2);
|
||||
static int parse_outbound_addresses(or_options_t *options, int validate_only,
|
||||
char **msg);
|
||||
|
||||
/** Magic value for or_options_t. */
|
||||
#define OR_OPTIONS_MAGIC 9090909
|
||||
@ -1390,6 +1392,12 @@ options_act(const or_options_t *old_options)
|
||||
tor_free(http_authenticator);
|
||||
}
|
||||
|
||||
if (parse_outbound_addresses(options, 0, &msg) < 0) {
|
||||
log_warn(LD_BUG, "Failed parsing oubound bind addresses: %s", msg);
|
||||
tor_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check for transitions that need action. */
|
||||
if (old_options) {
|
||||
int revise_trackexithosts = 0;
|
||||
@ -2164,6 +2172,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
if (parse_ports(options, 1, msg, &n_ports) < 0)
|
||||
return -1;
|
||||
|
||||
if (parse_outbound_addresses(options, 1, msg) < 0)
|
||||
return -1;
|
||||
|
||||
if (validate_data_directory(options)<0)
|
||||
REJECT("Invalid DataDirectory");
|
||||
|
||||
@ -5482,3 +5493,57 @@ getinfo_helper_config(control_connection_t *conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Parse outbound bind address option lines. If <b>validate_only</b>
|
||||
* is not 0 update _OutboundBindAddressIPv4 and
|
||||
* _OutboundBindAddressIPv6 in <b>options</b>. On failure, set
|
||||
* <b>msg</b> (if provided) to a newly allocated string containing a
|
||||
* description of the problem and return -1. */
|
||||
static int
|
||||
parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
|
||||
{
|
||||
const config_line_t *lines = options->OutboundBindAddress;
|
||||
int found_v4 = 0, found_v6 = 0;
|
||||
|
||||
if (!validate_only) {
|
||||
memset(&options->_OutboundBindAddressIPv4, 0,
|
||||
sizeof(options->_OutboundBindAddressIPv4));
|
||||
memset(&options->_OutboundBindAddressIPv6, 0,
|
||||
sizeof(options->_OutboundBindAddressIPv6));
|
||||
}
|
||||
while (lines) {
|
||||
tor_addr_t addr, *dst_addr = NULL;
|
||||
int af = tor_addr_parse(&addr, lines->value);
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
if (found_v4) {
|
||||
if (msg)
|
||||
tor_asprintf(msg, "Multiple IPv4 outbound bind addresses "
|
||||
"configured: %s", lines->value);
|
||||
return -1;
|
||||
}
|
||||
found_v4 = 1;
|
||||
dst_addr = &options->_OutboundBindAddressIPv4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (found_v6) {
|
||||
if (msg)
|
||||
tor_asprintf(msg, "Multiple IPv6 outbound bind addresses "
|
||||
"configured: %s", lines->value);
|
||||
return -1;
|
||||
}
|
||||
found_v6 = 1;
|
||||
dst_addr = &options->_OutboundBindAddressIPv6;
|
||||
break;
|
||||
default:
|
||||
if (msg)
|
||||
tor_asprintf(msg, "Outbound bind address '%s' didn't parse.",
|
||||
lines->value);
|
||||
return -1;
|
||||
}
|
||||
if (!validate_only)
|
||||
tor_addr_copy(dst_addr, &addr);
|
||||
lines = lines->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1377,26 +1377,37 @@ connection_connect(connection_t *conn, const char *address,
|
||||
|
||||
make_socket_reuseable(s);
|
||||
|
||||
if (options->OutboundBindAddress && !tor_addr_is_loopback(addr)) {
|
||||
struct sockaddr_in ext_addr;
|
||||
|
||||
memset(&ext_addr, 0, sizeof(ext_addr));
|
||||
ext_addr.sin_family = AF_INET;
|
||||
ext_addr.sin_port = 0;
|
||||
if (!tor_inet_aton(options->OutboundBindAddress, &ext_addr.sin_addr)) {
|
||||
log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.",
|
||||
options->OutboundBindAddress);
|
||||
if (!tor_addr_is_loopback(addr)) {
|
||||
const tor_addr_t *ext_addr = NULL;
|
||||
if (protocol_family == AF_INET &&
|
||||
!tor_addr_is_null(&options->_OutboundBindAddressIPv4))
|
||||
ext_addr = &options->_OutboundBindAddressIPv4;
|
||||
else if (protocol_family == AF_INET6 &&
|
||||
!tor_addr_is_null(&options->_OutboundBindAddressIPv6))
|
||||
ext_addr = &options->_OutboundBindAddressIPv6;
|
||||
if (ext_addr) {
|
||||
struct sockaddr_storage ext_addr_sa;
|
||||
socklen_t ext_addr_len = 0;
|
||||
memset(&ext_addr_sa, 0, sizeof(ext_addr_sa));
|
||||
ext_addr_len = tor_addr_to_sockaddr(ext_addr, 0,
|
||||
(struct sockaddr *) &ext_addr_sa,
|
||||
sizeof(ext_addr_sa));
|
||||
if (ext_addr_len == 0) {
|
||||
log_warn(LD_NET,
|
||||
"Error converting OutboundBindAddress %s into sockaddr. "
|
||||
"Ignoring.", fmt_addr(ext_addr));
|
||||
} else {
|
||||
if (bind(s, (struct sockaddr*)&ext_addr,
|
||||
(socklen_t)sizeof(ext_addr)) < 0) {
|
||||
if (bind(s, (struct sockaddr *) &ext_addr_sa, ext_addr_len) < 0) {
|
||||
*socket_error = tor_socket_errno(s);
|
||||
log_warn(LD_NET,"Error binding network socket: %s",
|
||||
log_warn(LD_NET,"Error binding network socket to %s: %s",
|
||||
fmt_addr(ext_addr),
|
||||
tor_socket_strerror(*socket_error));
|
||||
tor_close_socket(s);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_socket_nonblocking(s);
|
||||
|
||||
|
@ -3028,7 +3028,11 @@ typedef struct {
|
||||
/** Addresses to bind for listening for control connections. */
|
||||
config_line_t *ControlListenAddress;
|
||||
/** Local address to bind outbound sockets */
|
||||
char *OutboundBindAddress;
|
||||
config_line_t *OutboundBindAddress;
|
||||
/** IPv4 address derived from OutboundBindAddress. */
|
||||
tor_addr_t _OutboundBindAddressIPv4;
|
||||
/** IPv6 address derived from OutboundBindAddress. */
|
||||
tor_addr_t _OutboundBindAddressIPv6;
|
||||
/** Directory server only: which versions of
|
||||
* Tor should we tell users to run? */
|
||||
config_line_t *RecommendedVersions;
|
||||
|
Loading…
Reference in New Issue
Block a user