Browse Source

gossipd: take over negotiation of autogenerated Tor addresses.

For the moment, this is a straight handing of current parameters through
from master to the gossip daemon.  Next we'll change that.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
a8c0bca6a8
  1. 8
      common/wireaddr.h
  2. 1
      gossipd/Makefile
  3. 21
      gossipd/gossip.c
  4. 5
      gossipd/gossip_wire.csv
  5. 144
      gossipd/tor_autoservice.c
  6. 14
      gossipd/tor_autoservice.h
  7. 1
      lightningd/Makefile
  8. 5
      lightningd/gossip_control.c
  9. 4
      lightningd/lightningd.c
  10. 7
      lightningd/lightningd.h
  11. 3
      lightningd/test/run-find_my_path.c
  12. 11
      lightningd/tor.h

8
common/wireaddr.h

@ -15,6 +15,14 @@ struct sockaddr_in6;
struct sockaddr_in; struct sockaddr_in;
struct sockaddr_un; struct sockaddr_un;
/* BOLT #1:
*
* The default TCP port is 9735. This corresponds to hexadecimal
* `0x2607`, the Unicode code point for LIGHTNING.
*/
#define DEFAULT_PORT 9735
/* BOLT #7: /* BOLT #7:
* *
* The following `address descriptor` types are defined: * The following `address descriptor` types are defined:

1
gossipd/Makefile

@ -19,6 +19,7 @@ LIGHTNINGD_GOSSIP_HEADERS := gossipd/gen_gossip_wire.h \
gossipd/handshake.h \ gossipd/handshake.h \
gossipd/netaddress.h \ gossipd/netaddress.h \
gossipd/routing.h \ gossipd/routing.h \
gossipd/tor_autoservice.h \
gossipd/tor.h \ gossipd/tor.h \
gossipd/broadcast.h gossipd/broadcast.h
LIGHTNINGD_GOSSIP_SRC := $(LIGHTNINGD_GOSSIP_HEADERS:.h=.c) LIGHTNINGD_GOSSIP_SRC := $(LIGHTNINGD_GOSSIP_HEADERS:.h=.c)

21
gossipd/gossip.c

@ -38,6 +38,7 @@
#include <gossipd/netaddress.h> #include <gossipd/netaddress.h>
#include <gossipd/routing.h> #include <gossipd/routing.h>
#include <gossipd/tor.h> #include <gossipd/tor.h>
#include <gossipd/tor_autoservice.h>
#include <hsmd/client.h> #include <hsmd/client.h>
#include <hsmd/gen_hsm_client_wire.h> #include <hsmd/gen_hsm_client_wire.h>
#include <inttypes.h> #include <inttypes.h>
@ -149,6 +150,11 @@ struct daemon {
struct addrinfo *proxyaddr; struct addrinfo *proxyaddr;
bool use_proxy_always; bool use_proxy_always;
bool tor_autoservice;
struct wireaddr *tor_serviceaddr;
char *tor_password;
}; };
/* Peers we're trying to reach. */ /* Peers we're trying to reach. */
@ -1748,7 +1754,8 @@ static struct io_plan *gossip_init(struct daemon_conn *master,
&daemon->proposed_listen_announce, daemon->rgb, &daemon->proposed_listen_announce, daemon->rgb,
daemon->alias, &update_channel_interval, &daemon->reconnect, daemon->alias, &update_channel_interval, &daemon->reconnect,
&proxyaddr, &daemon->use_proxy_always, &proxyaddr, &daemon->use_proxy_always,
&dev_allow_localhost)) { &dev_allow_localhost, &daemon->tor_autoservice,
&daemon->tor_serviceaddr, &daemon->tor_password)) {
master_badmsg(WIRE_GOSSIPCTL_INIT, msg); master_badmsg(WIRE_GOSSIPCTL_INIT, msg);
} }
/* Prune time is twice update time */ /* Prune time is twice update time */
@ -1784,9 +1791,17 @@ static struct io_plan *gossip_activate(struct daemon_conn *master,
if (!fromwire_gossipctl_activate(msg, &listen)) if (!fromwire_gossipctl_activate(msg, &listen))
master_badmsg(WIRE_GOSSIPCTL_ACTIVATE, msg); master_badmsg(WIRE_GOSSIPCTL_ACTIVATE, msg);
if (listen) if (listen) {
binding = setup_listeners(tmpctx, daemon); binding = setup_listeners(tmpctx, daemon);
else if (daemon->tor_autoservice) {
struct wireaddr *tor;
tor = tor_autoservice(tmpctx,
daemon->tor_serviceaddr,
daemon->tor_password,
binding);
add_announcable(daemon, tor);
}
} else
binding = NULL; binding = NULL;
/* If we only advertize Tor addresses, force everything through proxy /* If we only advertize Tor addresses, force everything through proxy

5
gossipd/gossip_wire.csv

@ -23,6 +23,11 @@ gossipctl_init,,num_tor_proxyaddrs,u16
gossipctl_init,,tor_proxyaddr,num_tor_proxyaddrs*struct wireaddr gossipctl_init,,tor_proxyaddr,num_tor_proxyaddrs*struct wireaddr
gossipctl_init,,use_tor_proxy_always,bool gossipctl_init,,use_tor_proxy_always,bool
gossipctl_init,,dev_allow_localhost,bool gossipctl_init,,dev_allow_localhost,bool
gossipctl_init,,tor_autoservice,bool
# This is 0 or 1.
gossipctl_init,,num_tor_serviceaddrs,u16
gossipctl_init,,tor_serviceaddr,num_tor_serviceaddrs*struct wireaddr
gossipctl_init,,tor_password,wirestring
# Activate the gossip daemon, so others can connect. # Activate the gossip daemon, so others can connect.
gossipctl_activate,3025 gossipctl_activate,3025

Can't render this file because it has a wrong number of fields in line 6.

144
lightningd/tor.c → gossipd/tor_autoservice.c

@ -12,8 +12,8 @@
#include <common/wireaddr.h> #include <common/wireaddr.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <gossipd/tor_autoservice.h>
#include <lightningd/log.h> #include <lightningd/log.h>
#include <lightningd/tor.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -32,28 +32,30 @@ static void *buf_resize(void *buf, size_t len)
return buf; return buf;
} }
static void tor_send_cmd(struct lightningd *ld, static void tor_send_cmd(struct rbuf *rbuf, const char *cmd)
struct rbuf *rbuf, const char *cmd)
{ {
log_io(ld->log, LOG_IO_OUT, "torcontrol", cmd, strlen(cmd)); status_io(LOG_IO_OUT, "torcontrol", cmd, strlen(cmd));
if (!write_all(rbuf->fd, cmd, strlen(cmd))) if (!write_all(rbuf->fd, cmd, strlen(cmd)))
err(1, "Writing '%s' to Tor socket", cmd); status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Writing '%s' to Tor socket", cmd);
log_io(ld->log, LOG_IO_OUT, "torcontrol", "\r\n", 2); status_io(LOG_IO_OUT, "torcontrol", "\r\n", 2);
if (!write_all(rbuf->fd, "\r\n", 2)) if (!write_all(rbuf->fd, "\r\n", 2))
err(1, "Writing CRLF to Tor socket"); status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Writing CRLF to Tor socket");
} }
static char *tor_response_line(struct lightningd *ld, struct rbuf *rbuf) static char *tor_response_line(struct rbuf *rbuf)
{ {
char *line; char *line;
while ((line = rbuf_read_str(rbuf, '\n', buf_resize)) != NULL) { while ((line = rbuf_read_str(rbuf, '\n', buf_resize)) != NULL) {
log_io(ld->log, LOG_IO_IN, "torcontrol", line, strlen(line)); status_io(LOG_IO_IN, "torcontrol", line, strlen(line));
/* Weird response */ /* Weird response */
if (!strstarts(line, "250")) if (!strstarts(line, "250"))
errx(1, "Tor returned '%s'", line); status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Tor returned '%s'", line);
/* Last line */ /* Last line */
if (strstarts(line, "250 ")) if (strstarts(line, "250 "))
@ -64,23 +66,27 @@ static char *tor_response_line(struct lightningd *ld, struct rbuf *rbuf)
return NULL; return NULL;
} }
static void discard_remaining_response(struct lightningd *ld, struct rbuf *rbuf) static void discard_remaining_response(struct rbuf *rbuf)
{ {
while (tor_response_line(ld, rbuf)); while (tor_response_line(rbuf));
} }
static void make_onion(struct lightningd *ld, struct rbuf *rbuf) static struct wireaddr *make_onion(const tal_t *ctx,
struct rbuf *rbuf,
const struct wireaddr *local)
{ {
char *line; char *line;
struct wireaddr *onion;
//V3 tor after 3.3.3.aplha FIXME: TODO SAIBATO //V3 tor after 3.3.3.aplha FIXME: TODO SAIBATO
//sprintf((char *)reach->buffer,"ADD_ONION NEW:ED25519-V3 Port=9735,127.0.0.1:9735\r\n"); //sprintf((char *)reach->buffer,"ADD_ONION NEW:ED25519-V3 Port=9735,127.0.0.1:9735\r\n");
tor_send_cmd(ld, rbuf, tor_send_cmd(rbuf,
tal_fmt(tmpctx, "ADD_ONION NEW:RSA1024 Port=%d,127.0.0.1:%d Flags=DiscardPK,Detach", tal_fmt(tmpctx, "ADD_ONION NEW:RSA1024 Port=%d,%s Flags=DiscardPK,Detach",
ld->portnum, ld->portnum)); /* FIXME: We *could* allow user to set Tor port */
DEFAULT_PORT, fmt_wireaddr(tmpctx, local)));
while ((line = tor_response_line(ld, rbuf)) != NULL) { while ((line = tor_response_line(rbuf)) != NULL) {
size_t n; const char *name;
if (!strstarts(line, "ServiceID=")) if (!strstarts(line, "ServiceID="))
continue; continue;
@ -89,17 +95,16 @@ static void make_onion(struct lightningd *ld, struct rbuf *rbuf)
if (strchr(line, '\r')) if (strchr(line, '\r'))
*strchr(line, '\r') = '\0'; *strchr(line, '\r') = '\0';
n = tal_count(ld->proposed_wireaddr); name = tal_fmt(tmpctx, "%s.onion", line);
tal_resize(&ld->proposed_wireaddr, n + 1); onion = tal(ctx, struct wireaddr);
tal_resize(&ld->proposed_listen_announce, n + 1); if (!parse_wireaddr(name, onion, 0, false, NULL))
parse_wireaddr_internal(tal_fmt(tmpctx, "%s.onion", line), status_failed(STATUS_FAIL_INTERNAL_ERROR,
&ld->proposed_wireaddr[n], "Tor gave bad onion name '%s'", name);
ld->portnum, false, false, NULL); discard_remaining_response(rbuf);
ld->proposed_listen_announce[n] = ADDR_ANNOUNCE; return onion;
discard_remaining_response(ld, rbuf);
return;
} }
errx(1, "Tor didn't give us a ServiceID"); status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Tor didn't give us a ServiceID");
} }
/* https://gitweb.torproject.org/torspec.git/tree/control-spec.txt: /* https://gitweb.torproject.org/torspec.git/tree/control-spec.txt:
@ -111,32 +116,32 @@ static void make_onion(struct lightningd *ld, struct rbuf *rbuf)
* ReplyText = XXXX * ReplyText = XXXX
* StatusCode = 3DIGIT * StatusCode = 3DIGIT
*/ */
static void negotiate_auth(struct lightningd *ld, struct rbuf *rbuf) static void negotiate_auth(struct rbuf *rbuf, const char *tor_password)
{ {
char *line; char *line;
char *cookiefile = NULL; char *cookiefile = NULL;
int cookiefileerrno; int cookiefileerrno;
tor_send_cmd(ld, rbuf, "PROTOCOLINFO 1"); tor_send_cmd(rbuf, "PROTOCOLINFO 1");
while ((line = tor_response_line(ld, rbuf)) != NULL) { while ((line = tor_response_line(rbuf)) != NULL) {
const char *p; const char *p;
if (!strstarts(line, "AUTH METHODS=")) if (!strstarts(line, "AUTH METHODS="))
continue; continue;
if (strstr(line, "NULL")) { if (strstr(line, "NULL")) {
discard_remaining_response(ld, rbuf); discard_remaining_response(rbuf);
tor_send_cmd(ld, rbuf, "AUTHENTICATE"); tor_send_cmd(rbuf, "AUTHENTICATE");
discard_remaining_response(ld, rbuf); discard_remaining_response(rbuf);
return; return;
} else if (strstr(line, "HASHEDPASSWORD") } else if (strstr(line, "HASHEDPASSWORD")
&& strlen(ld->tor_service_password)) { && strlen(tor_password)) {
discard_remaining_response(ld, rbuf); discard_remaining_response(rbuf);
tor_send_cmd(ld, rbuf, tor_send_cmd(rbuf,
tal_fmt(tmpctx, "AUTHENTICATE \"%s\"", tal_fmt(tmpctx, "AUTHENTICATE \"%s\"",
ld->tor_service_password)); tor_password));
discard_remaining_response(ld, rbuf); discard_remaining_response(rbuf);
return; return;
} else if ((p = strstr(line, "COOKIEFILE=\"")) != NULL) { } else if ((p = strstr(line, "COOKIEFILE=\"")) != NULL) {
char *contents, *end; char *contents, *end;
@ -144,7 +149,9 @@ static void negotiate_auth(struct lightningd *ld, struct rbuf *rbuf)
p += strlen("COOKIEFILE=\""); p += strlen("COOKIEFILE=\"");
end = strstr(p, "\""); end = strstr(p, "\"");
if (!end) if (!end)
errx(1, "Tor protocolinfo bad line '%s'", line); status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Tor protocolinfo bad line '%s'",
line);
*end = '\0'; *end = '\0';
/* If we can't access this, try other methods */ /* If we can't access this, try other methods */
@ -152,44 +159,59 @@ static void negotiate_auth(struct lightningd *ld, struct rbuf *rbuf)
contents = grab_file(tmpctx, p); contents = grab_file(tmpctx, p);
if (!contents) { if (!contents) {
cookiefileerrno = errno; cookiefileerrno = errno;
fprintf(stderr, "No cookies for me!\n");
continue; continue;
} }
discard_remaining_response(ld, rbuf); discard_remaining_response(rbuf);
tor_send_cmd(ld, rbuf, tor_send_cmd(rbuf,
tal_fmt(tmpctx, "AUTHENTICATE %s", tal_fmt(tmpctx, "AUTHENTICATE %s",
tal_hexstr(tmpctx, tal_hexstr(tmpctx,
contents, contents,
tal_len(contents)-1))); tal_len(contents)-1)));
discard_remaining_response(ld, rbuf); discard_remaining_response(rbuf);
return; return;
} }
} }
/* Now report if we tried cookie file and it failed */ /* Now report if we tried cookie file and it failed */
if (cookiefile) { if (cookiefile)
errno = cookiefileerrno; status_failed(STATUS_FAIL_INTERNAL_ERROR,
err(1, "Could not open Tor cookie file '%s'", cookiefile); "Could not open Tor cookie file '%s': %s",
} cookiefile, strerror(cookiefileerrno));
errx(1, "Tor protocolinfo did not give auth"); status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Tor protocolinfo did not give auth");
} }
void tor_init(struct lightningd *ld) /* We need to have a bound address we can tell Tor to connect to */
static const struct wireaddr *
find_local_address(const struct wireaddr_internal *bindings)
{
for (size_t i = 0; i < tal_count(bindings); i++) {
if (bindings[i].itype != ADDR_INTERNAL_WIREADDR)
continue;
if (bindings[i].u.wireaddr.type != ADDR_TYPE_IPV4
&& bindings[i].u.wireaddr.type != ADDR_TYPE_IPV6)
continue;
return &bindings[i].u.wireaddr;
}
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"No local address found to tell Tor to connect to");
}
struct wireaddr *tor_autoservice(const tal_t *ctx,
const struct wireaddr *tor_serviceaddr,
const char *tor_password,
const struct wireaddr_internal *bindings)
{ {
int fd; int fd;
const struct wireaddr *laddr;
struct wireaddr *onion;
struct addrinfo *ai_tor; struct addrinfo *ai_tor;
struct rbuf rbuf; struct rbuf rbuf;
char *buffer; char *buffer;
if (!ld->config.tor_enable_auto_hidden_service) laddr = find_local_address(bindings);
return; ai_tor = wireaddr_to_addrinfo(tmpctx, tor_serviceaddr);
/* FIXME: Need better way to convert wireaddr to addrinfo... */
if (getaddrinfo(fmt_wireaddr_without_port(ld, ld->tor_serviceaddr),
tal_fmt(tmpctx, "%d", ld->tor_serviceaddr->port), NULL,
&ai_tor) != 0)
errx(1, "getaddrinfo failed for Tor service");
fd = socket(ai_tor->ai_family, SOCK_STREAM, 0); fd = socket(ai_tor->ai_family, SOCK_STREAM, 0);
if (fd < 0) if (fd < 0)
@ -201,8 +223,8 @@ void tor_init(struct lightningd *ld)
buffer = tal_arr(tmpctx, char, rbuf_good_size(fd)); buffer = tal_arr(tmpctx, char, rbuf_good_size(fd));
rbuf_init(&rbuf, fd, buffer, tal_len(buffer)); rbuf_init(&rbuf, fd, buffer, tal_len(buffer));
negotiate_auth(ld, &rbuf); negotiate_auth(&rbuf, tor_password);
make_onion(ld, &rbuf); onion = make_onion(ctx, &rbuf, laddr);
/*on the other hand we can stay connected until ln finish to keep onion alive and then vanish */ /*on the other hand we can stay connected until ln finish to keep onion alive and then vanish */
//because when we run with Detach flag as we now do every start of LN creates a new addr while the old //because when we run with Detach flag as we now do every start of LN creates a new addr while the old
@ -210,4 +232,6 @@ void tor_init(struct lightningd *ld)
//read_partial to keep it open until LN drops //read_partial to keep it open until LN drops
//FIXME: SAIBATO we might not want to close this conn //FIXME: SAIBATO we might not want to close this conn
close(fd); close(fd);
return onion;
} }

14
gossipd/tor_autoservice.h

@ -0,0 +1,14 @@
#ifndef LIGHTNING_GOSSIPD_TOR_AUTOSERVICE_H
#define LIGHTNING_GOSSIPD_TOR_AUTOSERVICE_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <stdbool.h>
#include <stdlib.h>
struct wireaddr *tor_autoservice(const tal_t *ctx,
const struct wireaddr *tor_serviceaddr,
const char *tor_password,
const struct wireaddr_internal *bindings);
#endif /* LIGHTNING_GOSSIPD_TOR_AUTOSERVICE_H */

1
lightningd/Makefile

@ -76,7 +76,6 @@ LIGHTNINGD_SRC := \
lightningd/peer_control.c \ lightningd/peer_control.c \
lightningd/peer_htlcs.c \ lightningd/peer_htlcs.c \
lightningd/subd.c \ lightningd/subd.c \
lightningd/tor.c \
lightningd/watch.c lightningd/watch.c
# Source files without corresponding headers # Source files without corresponding headers

5
lightningd/gossip_control.c

@ -227,7 +227,10 @@ void gossip_init(struct lightningd *ld)
listen_announce, ld->rgb, listen_announce, ld->rgb,
ld->alias, ld->config.channel_update_interval, ld->reconnect, ld->alias, ld->config.channel_update_interval, ld->reconnect,
ld->proxyaddr, ld->use_proxy_always, ld->proxyaddr, ld->use_proxy_always,
allow_localhost); allow_localhost,
ld->config.tor_enable_auto_hidden_service,
ld->tor_serviceaddr,
ld->tor_service_password ? ld->tor_service_password : "");
subd_send_msg(ld->gossip, msg); subd_send_msg(ld->gossip, msg);
} }

4
lightningd/lightningd.c

@ -32,7 +32,6 @@
#include <lightningd/log.h> #include <lightningd/log.h>
#include <lightningd/onchain_control.h> #include <lightningd/onchain_control.h>
#include <lightningd/options.h> #include <lightningd/options.h>
#include <lightningd/tor.h>
#include <onchaind/onchain_wire.h> #include <onchaind/onchain_wire.h>
#include <signal.h> #include <signal.h>
#include <sys/types.h> #include <sys/types.h>
@ -316,9 +315,6 @@ int main(int argc, char *argv[])
/* Ignore SIGPIPE: we look at our write return values*/ /* Ignore SIGPIPE: we look at our write return values*/
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
/* tor support */
tor_init(ld);
/* Make sure we can reach other daemons, and versions match. */ /* Make sure we can reach other daemons, and versions match. */
test_daemons(ld); test_daemons(ld);

7
lightningd/lightningd.h

@ -12,13 +12,6 @@
#include <wallet/txfilter.h> #include <wallet/txfilter.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
/* BOLT #1:
*
* The default TCP port is 9735. This corresponds to hexadecimal
* `0x2607`, the Unicode code point for LIGHTNING.
*/
#define DEFAULT_PORT 9735
/* Various adjustable things. */ /* Various adjustable things. */
struct config { struct config {
/* How long do we want them to lock up their funds? (blocks) */ /* How long do we want them to lock up their funds? (blocks) */

3
lightningd/test/run-find_my_path.c

@ -104,9 +104,6 @@ void subd_shutdown(struct subd *subd UNNEEDED, unsigned int seconds UNNEEDED)
/* Generated stub for timer_expired */ /* Generated stub for timer_expired */
void timer_expired(tal_t *ctx UNNEEDED, struct timer *timer UNNEEDED) void timer_expired(tal_t *ctx UNNEEDED, struct timer *timer UNNEEDED)
{ fprintf(stderr, "timer_expired called!\n"); abort(); } { fprintf(stderr, "timer_expired called!\n"); abort(); }
/* Generated stub for tor_init */
void tor_init(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "tor_init called!\n"); abort(); }
/* Generated stub for txfilter_add_derkey */ /* Generated stub for txfilter_add_derkey */
void txfilter_add_derkey(struct txfilter *filter UNNEEDED, void txfilter_add_derkey(struct txfilter *filter UNNEEDED,
const u8 derkey[PUBKEY_DER_LEN]) const u8 derkey[PUBKEY_DER_LEN])

11
lightningd/tor.h

@ -1,11 +0,0 @@
#ifndef LIGHTNING_LIGHTNINGD_TOR_H
#define LIGHTNING_LIGHTNINGD_TOR_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <lightningd/lightningd.h>
#include <stdbool.h>
#include <stdlib.h>
void tor_init(struct lightningd *ld);
#endif /* LIGHTNING_LIGHTNINGD_TOR_H */
Loading…
Cancel
Save