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. 15
      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)); assert(!separate_address_and_port(tmpctx, "[::1]:http", &ip, &port));
// localhost hostnames for backward compat // localhost hostnames for backward compat
assert(parse_wireaddr("localhost", &addr, 200, NULL)); assert(parse_wireaddr("localhost", &addr, 200, false, NULL));
assert(addr.port == 200); assert(addr.port == 200);
// string should win the port battle // 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); assert(addr.port == 9735);
ip = fmt_wireaddr(tmpctx, &addr); ip = fmt_wireaddr(tmpctx, &addr);
assert(streq(ip, "[::1]:9735")); assert(streq(ip, "[::1]:9735"));
// should use argument if we have no port in string // 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); assert(addr.port == 9777);
ip = fmt_wireaddr(tmpctx, &addr); ip = fmt_wireaddr(tmpctx, &addr);
assert(streq(ip, "[2001:db8:85a3::8a2e:370:7334]:9777")); 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(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(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(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(addr.port == 49150);
assert(parse_wireaddr("odpzvneidqdf5hdq.onion", &addr, 1, NULL)); assert(parse_wireaddr("odpzvneidqdf5hdq.onion", &addr, 1, false, NULL));
assert(addr.port == 1); assert(addr.port == 1);
tal_free(tmpctx); tal_free(tmpctx);
return 0; 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, 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_in6 *sa6;
struct sockaddr_in *sa4; 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_socktype = SOCK_STREAM;
hints.ai_protocol = 0; hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG; hints.ai_flags = AI_ADDRCONFIG;
if (!dns_ok)
hints.ai_flags = AI_NUMERICHOST;
gai_err = getaddrinfo(hostname, tal_fmt(tmpctx, "%d", port), gai_err = getaddrinfo(hostname, tal_fmt(tmpctx, "%d", port),
&hints, &addrinfo); &hints, &addrinfo);
if (gai_err != 0) { 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, 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 in6_addr v6;
struct in_addr v4; struct in_addr v4;
@ -353,7 +355,7 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport,
/* Resolve with getaddrinfo */ /* Resolve with getaddrinfo */
if (!res) if (!res)
res = wireaddr_from_hostname(addr, ip, port, err_msg); res = wireaddr_from_hostname(addr, ip, port, dns_ok, err_msg);
finish: finish:
if (!res && err_msg && !*err_msg) if (!res && err_msg && !*err_msg)
@ -362,7 +364,8 @@ finish:
} }
bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, 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; u16 wildport;
char *ip; char *ip;
@ -392,7 +395,7 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr,
} }
addr->itype = ADDR_INTERNAL_WIREADDR; 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, 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); size_t *max);
void towire_addr_listen_announce(u8 **pptr, enum addr_listen_announce ala); 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(const tal_t *ctx, const struct wireaddr *a);
char *fmt_wireaddr_without_port(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, 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, void wireaddr_from_ipv4(struct wireaddr *addr,
const struct in_addr *ip4, const struct in_addr *ip4,
@ -104,7 +105,9 @@ struct wireaddr_internal {
char sockname[sizeof(((struct sockaddr_un *)0)->sun_path)]; char sockname[sizeof(((struct sockaddr_un *)0)->sun_path)];
} u; } 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, void towire_wireaddr_internal(u8 **pptr,
const struct wireaddr_internal *addr); 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 * 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; struct addrhint *a;
char bech32[100], *addr; 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 = tal(ctx, struct addrhint);
a->addr.itype = ADDR_INTERNAL_WIREADDR; 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); status_trace("Could not resolve %s", addr);
return tal_free(a); return tal_free(a);
} else { } else {
@ -2033,7 +2035,8 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id,
id); id);
if (!a) if (!a)
a = seed_resolve_addr(tmpctx, id, 9735); a = seed_resolve_addr(tmpctx, id, 9735,
!daemon->use_proxy_always);
if (!a) { if (!a) {
status_debug("No address known for %s, giving up", 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; port = DEFAULT_PORT;
} }
if (!parse_wireaddr_internal(name, &addr, port, false, if (!parse_wireaddr_internal(name, &addr, port, false,
!cmd->ld->use_proxy_always,
&err_msg)) { &err_msg)) {
command_fail(cmd, "Host %s:%u not valid: %s", command_fail(cmd, "Host %s:%u not valid: %s",
name, port, err_msg ? err_msg : "port is 0"); name, port, err_msg ? err_msg : "port is 0");

15
lightningd/options.c

@ -159,7 +159,7 @@ static char *opt_add_addr_withtype(const char *arg,
ld->proposed_listen_announce[n] = ala; ld->proposed_listen_announce[n] = ala;
if (!parse_wireaddr_internal(arg, &ld->proposed_wireaddr[n], ld->portnum, 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); 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 */ /* We use a tal_arr here, so we can marshal it to gossipd */
ld->proxyaddr = tal_arr(ld, struct wireaddr, 1); 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'", return tal_fmt(NULL, "Unable to parse Tor proxy address '%s'",
arg); arg);
} }
@ -313,7 +314,8 @@ static char *opt_add_tor_service_addr(const char *arg, struct lightningd *ld)
{ {
tal_free(ld->tor_serviceaddr); tal_free(ld->tor_serviceaddr);
ld->tor_serviceaddr = tal(ld, struct wireaddr); 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'", return tal_fmt(NULL, "Unable to parse Tor service address '%s'",
arg); arg);
} }
@ -432,8 +434,11 @@ static void config_register_opts(struct lightningd *ld)
"Set a Tor hidden service password"); "Set a Tor hidden service password");
opt_register_arg("--tor-auto-listen", opt_set_bool_arg, opt_show_bool, 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"); &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,
&ld->use_proxy_always, "Use the proxy always"); /* 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");
} }
#if DEVELOPER #if DEVELOPER

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); tal_resize(&ld->proposed_listen_announce, n + 1);
parse_wireaddr_internal(tal_fmt(tmpctx, "%s.onion", line), parse_wireaddr_internal(tal_fmt(tmpctx, "%s.onion", line),
&ld->proposed_wireaddr[n], &ld->proposed_wireaddr[n],
ld->portnum, false, NULL); ld->portnum, false, false, NULL);
ld->proposed_listen_announce[n] = ADDR_ANNOUNCE; ld->proposed_listen_announce[n] = ADDR_ANNOUNCE;
discard_remaining_response(ld, rbuf); discard_remaining_response(ld, rbuf);
return; 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); addrstr = sqlite3_column_text(stmt, 2);
if (addrstr) { if (addrstr) {
addrp = &addr; 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); db_stmt_done(stmt);
return NULL; return NULL;
} }

Loading…
Cancel
Save