Browse Source

Tor: don't do seed queries if we're supposed to always use proxy.

Risks leakage.  We could do lookup via the proxy, but that's a TODO.

There's only one occurance of getaddrinfo (and no gethostbyname), so
we add a flag to the callers.

Note: the use of --always-use-proxy suppresses *all* DNS lookups, even
those from connect commands and the command line.

FIXME: An implicit setting of use_proxy_always is done in gossipd if it
determines that we are announcing nothing but Tor addresses, but that
does *not* suppress 'connect'.

This is fixed in a later patch.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
5a0bc83b20
  1. 16
      common/test/run-ip_port_parsing.c
  2. 13
      common/wireaddr.c
  3. 9
      common/wireaddr.h
  4. 9
      gossipd/gossip.c
  5. 1
      lightningd/connect_control.c
  6. 13
      lightningd/options.c
  7. 2
      lightningd/tor.c
  8. 2
      wallet/wallet.c

16
common/test/run-ip_port_parsing.c

@ -85,35 +85,35 @@ int main(void)
assert(!separate_address_and_port(tmpctx, "[::1]:http", &ip, &port));
// localhost hostnames for backward compat
assert(parse_wireaddr("localhost", &addr, 200, NULL));
assert(parse_wireaddr("localhost", &addr, 200, false, NULL));
assert(addr.port == 200);
// string should win the port battle
assert(parse_wireaddr("[::1]:9735", &addr, 500, NULL));
assert(parse_wireaddr("[::1]:9735", &addr, 500, false, NULL));
assert(addr.port == 9735);
ip = fmt_wireaddr(tmpctx, &addr);
assert(streq(ip, "[::1]:9735"));
// should use argument if we have no port in string
assert(parse_wireaddr("2001:db8:85a3::8a2e:370:7334", &addr, 9777, NULL));
assert(parse_wireaddr("2001:db8:85a3::8a2e:370:7334", &addr, 9777, false, NULL));
assert(addr.port == 9777);
ip = fmt_wireaddr(tmpctx, &addr);
assert(streq(ip, "[2001:db8:85a3::8a2e:370:7334]:9777"));
assert(parse_wireaddr("[::ffff:127.0.0.1]:49150", &addr, 1, NULL));
assert(parse_wireaddr("[::ffff:127.0.0.1]:49150", &addr, 1, false, NULL));
assert(addr.port == 49150);
assert(parse_wireaddr("4ruvswpqec5i2gogopxl4vm5bruzknbvbylov2awbo4rxiq4cimdldad.onion:49150", &addr, 1, NULL));
assert(parse_wireaddr("4ruvswpqec5i2gogopxl4vm5bruzknbvbylov2awbo4rxiq4cimdldad.onion:49150", &addr, 1, false, NULL));
assert(addr.port == 49150);
assert(parse_wireaddr("4ruvswpqec5i2gogopxl4vm5bruzknbvbylov2awbo4rxiq4cimdldad.onion", &addr, 1, NULL));
assert(parse_wireaddr("4ruvswpqec5i2gogopxl4vm5bruzknbvbylov2awbo4rxiq4cimdldad.onion", &addr, 1, false, NULL));
assert(addr.port == 1);
assert(parse_wireaddr("odpzvneidqdf5hdq.onion:49150", &addr, 1, NULL));
assert(parse_wireaddr("odpzvneidqdf5hdq.onion:49150", &addr, 1, false, NULL));
assert(addr.port == 49150);
assert(parse_wireaddr("odpzvneidqdf5hdq.onion", &addr, 1, NULL));
assert(parse_wireaddr("odpzvneidqdf5hdq.onion", &addr, 1, false, NULL));
assert(addr.port == 1);
tal_free(tmpctx);
return 0;

13
common/wireaddr.c

@ -262,7 +262,7 @@ static bool separate_address_and_port(const tal_t *ctx, const char *arg,
}
bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname,
const u16 port, const char **err_msg)
const u16 port, bool dns_ok, const char **err_msg)
{
struct sockaddr_in6 *sa6;
struct sockaddr_in *sa4;
@ -296,6 +296,8 @@ bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname,
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG;
if (!dns_ok)
hints.ai_flags = AI_NUMERICHOST;
gai_err = getaddrinfo(hostname, tal_fmt(tmpctx, "%d", port),
&hints, &addrinfo);
if (gai_err != 0) {
@ -320,7 +322,7 @@ bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname,
}
bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport,
const char **err_msg)
bool dns_ok, const char **err_msg)
{
struct in6_addr v6;
struct in_addr v4;
@ -353,7 +355,7 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport,
/* Resolve with getaddrinfo */
if (!res)
res = wireaddr_from_hostname(addr, ip, port, err_msg);
res = wireaddr_from_hostname(addr, ip, port, dns_ok, err_msg);
finish:
if (!res && err_msg && !*err_msg)
@ -362,7 +364,8 @@ finish:
}
bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr,
u16 port, bool wildcard_ok, const char **err_msg)
u16 port, bool wildcard_ok, bool dns_ok,
const char **err_msg)
{
u16 wildport;
char *ip;
@ -392,7 +395,7 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr,
}
addr->itype = ADDR_INTERNAL_WIREADDR;
return parse_wireaddr(arg, &addr->u.wireaddr, port, err_msg);
return parse_wireaddr(arg, &addr->u.wireaddr, port, dns_ok, err_msg);
}
void wireaddr_from_sockname(struct wireaddr_internal *addr,

9
common/wireaddr.h

@ -67,13 +67,14 @@ enum addr_listen_announce fromwire_addr_listen_announce(const u8 **cursor,
size_t *max);
void towire_addr_listen_announce(u8 **pptr, enum addr_listen_announce ala);
bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 port, const char **err_msg);
bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 port,
bool dns_ok, const char **err_msg);
char *fmt_wireaddr(const tal_t *ctx, const struct wireaddr *a);
char *fmt_wireaddr_without_port(const tal_t *ctx, const struct wireaddr *a);
bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname,
const u16 port, const char **err_msg);
const u16 port, bool dns_ok, const char **err_msg);
void wireaddr_from_ipv4(struct wireaddr *addr,
const struct in_addr *ip4,
@ -104,7 +105,9 @@ struct wireaddr_internal {
char sockname[sizeof(((struct sockaddr_un *)0)->sun_path)];
} u;
};
bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, u16 port, bool wildcard_ok, const char **err_msg);
bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr,
u16 port, bool wildcard_ok, bool dns_ok,
const char **err_msg);
void towire_wireaddr_internal(u8 **pptr,
const struct wireaddr_internal *addr);

9
gossipd/gossip.c

@ -1930,7 +1930,8 @@ static struct io_plan *conn_tor_init(struct io_conn *conn,
}
static struct addrhint *
seed_resolve_addr(const tal_t *ctx, const struct pubkey *id, const u16 port)
seed_resolve_addr(const tal_t *ctx, const struct pubkey *id, const u16 port,
bool dns_ok)
{
struct addrhint *a;
char bech32[100], *addr;
@ -1946,7 +1947,8 @@ seed_resolve_addr(const tal_t *ctx, const struct pubkey *id, const u16 port)
a = tal(ctx, struct addrhint);
a->addr.itype = ADDR_INTERNAL_WIREADDR;
if (!wireaddr_from_hostname(&a->addr.u.wireaddr, addr, port, NULL)) {
if (!wireaddr_from_hostname(&a->addr.u.wireaddr, addr, port, dns_ok,
NULL)) {
status_trace("Could not resolve %s", addr);
return tal_free(a);
} else {
@ -2033,7 +2035,8 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id,
id);
if (!a)
a = seed_resolve_addr(tmpctx, id, 9735);
a = seed_resolve_addr(tmpctx, id, 9735,
!daemon->use_proxy_always);
if (!a) {
status_debug("No address known for %s, giving up",

1
lightningd/connect_control.c

@ -152,6 +152,7 @@ static void json_connect(struct command *cmd,
port = DEFAULT_PORT;
}
if (!parse_wireaddr_internal(name, &addr, port, false,
!cmd->ld->use_proxy_always,
&err_msg)) {
command_fail(cmd, "Host %s:%u not valid: %s",
name, port, err_msg ? err_msg : "port is 0");

13
lightningd/options.c

@ -159,7 +159,7 @@ static char *opt_add_addr_withtype(const char *arg,
ld->proposed_listen_announce[n] = ala;
if (!parse_wireaddr_internal(arg, &ld->proposed_wireaddr[n], ld->portnum,
true, &err_msg)) {
true, !ld->use_proxy_always, &err_msg)) {
return tal_fmt(NULL, "Unable to parse address '%s': %s", arg, err_msg);
}
@ -302,7 +302,8 @@ static char *opt_add_proxy_addr(const char *arg, struct lightningd *ld)
/* We use a tal_arr here, so we can marshal it to gossipd */
ld->proxyaddr = tal_arr(ld, struct wireaddr, 1);
if (!parse_wireaddr(arg, ld->proxyaddr, 9050, NULL)) {
if (!parse_wireaddr(arg, ld->proxyaddr, 9050, !ld->use_proxy_always,
NULL)) {
return tal_fmt(NULL, "Unable to parse Tor proxy address '%s'",
arg);
}
@ -313,7 +314,8 @@ static char *opt_add_tor_service_addr(const char *arg, struct lightningd *ld)
{
tal_free(ld->tor_serviceaddr);
ld->tor_serviceaddr = tal(ld, struct wireaddr);
if (!parse_wireaddr(arg, ld->tor_serviceaddr, 9051, NULL)) {
if (!parse_wireaddr(arg, ld->tor_serviceaddr, 9051,
!ld->use_proxy_always, NULL)) {
return tal_fmt(NULL, "Unable to parse Tor service address '%s'",
arg);
}
@ -432,7 +434,10 @@ static void config_register_opts(struct lightningd *ld)
"Set a Tor hidden service password");
opt_register_arg("--tor-auto-listen", opt_set_bool_arg, opt_show_bool,
&ld->config.tor_enable_auto_hidden_service , "Generate and use a temp auto hidden-service and show the onion address");
opt_register_arg("--always-use-proxy", opt_set_bool_arg, opt_show_bool,
/* Early, as it suppresses DNS lookups from cmdline too. */
opt_register_early_arg("--always-use-proxy",
opt_set_bool_arg, opt_show_bool,
&ld->use_proxy_always, "Use the proxy always");
}

2
lightningd/tor.c

@ -94,7 +94,7 @@ static void make_onion(struct lightningd *ld, struct rbuf *rbuf)
tal_resize(&ld->proposed_listen_announce, n + 1);
parse_wireaddr_internal(tal_fmt(tmpctx, "%s.onion", line),
&ld->proposed_wireaddr[n],
ld->portnum, false, NULL);
ld->portnum, false, false, NULL);
ld->proposed_listen_announce[n] = ADDR_ANNOUNCE;
discard_remaining_response(ld, rbuf);
return;

2
wallet/wallet.c

@ -510,7 +510,7 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
addrstr = sqlite3_column_text(stmt, 2);
if (addrstr) {
addrp = &addr;
if (!parse_wireaddr_internal((const char*)addrstr, addrp, DEFAULT_PORT, false, NULL)) {
if (!parse_wireaddr_internal((const char*)addrstr, addrp, DEFAULT_PORT, false, false, NULL)) {
db_stmt_done(stmt);
return NULL;
}

Loading…
Cancel
Save