From f6006f43a9ab7c12d8df43c27682a8efde56eaf0 Mon Sep 17 00:00:00 2001 From: Saibato Date: Fri, 15 Nov 2019 09:44:22 +0100 Subject: [PATCH] Init commit to be able to create a tor static service on the fly. We want to have a static Tor service created from a blob bound to our node on cmdline Changelog-added: persistent Tor address support Changelog-added: allow the Tor inbound service port differ from 9735 Signed-off-by: Saibato Add base64 encode/decode to common We need this to encode the blob for the tor service Signed-off-by: Saibato --- common/Makefile | 1 + common/base64.c | 37 ++++++++++ common/base64.h | 10 +++ common/wireaddr.c | 118 ++++++++++++++++++++++++++++--- common/wireaddr.h | 12 +++- connectd/Makefile | 1 + connectd/connectd.c | 81 ++++++++++++++++++---- connectd/tor_autoservice.c | 138 ++++++++++++++++++++++++++++++++----- connectd/tor_autoservice.h | 13 +++- devtools/gossipwith.c | 1 + lightningd/Makefile | 1 + lightningd/json.c | 8 ++- lightningd/lightningd.h | 2 +- lightningd/options.c | 6 ++ 14 files changed, 385 insertions(+), 44 deletions(-) create mode 100644 common/base64.c create mode 100644 common/base64.h diff --git a/common/Makefile b/common/Makefile index 28ddaab6d..1c5055af5 100644 --- a/common/Makefile +++ b/common/Makefile @@ -2,6 +2,7 @@ COMMON_SRC_NOGEN := \ common/addr.c \ common/amount.c \ common/base32.c \ + common/base64.c \ common/bech32.c \ common/bech32_util.c \ common/bigsize.c \ diff --git a/common/base64.c b/common/base64.c new file mode 100644 index 000000000..0e00c3236 --- /dev/null +++ b/common/base64.c @@ -0,0 +1,37 @@ +#include +#include +#include + +/* Decode/encode from/to base64, base64 helper functions. + * We import base64 from libsodium to generate tor V3 ED25519-V3 onions from blobs +*/ + +char *b64_encode(const tal_t *ctx, const u8 *data, size_t len) +{ + char *str = tal_arr(ctx, char, sodium_base64_encoded_len(len, sodium_base64_VARIANT_ORIGINAL) + 1); + + str = sodium_bin2base64(str, tal_count(str), data, + len, sodium_base64_VARIANT_ORIGINAL); + return str; +} + +u8 *b64_decode(const tal_t *ctx, const char *str, size_t len) +{ + size_t bin_len = len + 1; + + u8 *ret = tal_arr(ctx, u8, bin_len); + + if (!sodium_base642bin(ret, + tal_count(ret), + (const char * const)str, + len, + NULL, + &bin_len, + NULL, + sodium_base64_VARIANT_ORIGINAL)) + return tal_free(ret); + + ret[bin_len] = 0; + tal_resize(&ret, bin_len + 1); + return ret; +} diff --git a/common/base64.h b/common/base64.h new file mode 100644 index 000000000..065a1af6b --- /dev/null +++ b/common/base64.h @@ -0,0 +1,10 @@ +#ifndef LIGHTNING_COMMON_BASE64_H +#define LIGHTNING_COMMON_BASE64_H +#include "config.h" +#include +#include + +char *b64_encode(const tal_t *ctx, const u8 *data, size_t len); +u8 *b64_decode(const tal_t *ctx, const char *str, size_t len); + +#endif /* LIGHTNING_COMMON_BASE64_H */ diff --git a/common/wireaddr.c b/common/wireaddr.c index 492eed0be..041513368 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -80,7 +82,14 @@ void towire_wireaddr_internal(u8 **pptr, const struct wireaddr_internal *addr) sizeof(addr->u.sockname)); return; case ADDR_INTERNAL_AUTOTOR: - towire_wireaddr(pptr, &addr->u.torservice); + towire_wireaddr(pptr, &addr->u.torservice.address); + towire_u16(pptr, addr->u.torservice.port); + return; + case ADDR_INTERNAL_STATICTOR: + towire_wireaddr(pptr, &addr->u.torservice.address); + towire_u8_array(pptr, (const u8 *)addr->u.torservice.blob, + sizeof(addr->u.torservice.blob)); + towire_u16(pptr, addr->u.torservice.port); return; case ADDR_INTERNAL_ALLPROTO: towire_u16(pptr, addr->u.port); @@ -113,7 +122,15 @@ bool fromwire_wireaddr_internal(const u8 **cursor, size_t *max, addr->u.port = fromwire_u16(cursor, max); return *cursor != NULL; case ADDR_INTERNAL_AUTOTOR: - return fromwire_wireaddr(cursor, max, &addr->u.torservice); + fromwire_wireaddr(cursor, max, &addr->u.torservice.address); + addr->u.torservice.port = fromwire_u16(cursor, max); + return *cursor != NULL; + case ADDR_INTERNAL_STATICTOR: + fromwire_wireaddr(cursor, max, &addr->u.torservice.address); + fromwire_u8_array(cursor, max, (u8 *)addr->u.torservice.blob, + sizeof(addr->u.torservice.blob)); + addr->u.torservice.port = fromwire_u16(cursor, max); + return *cursor != NULL; case ADDR_INTERNAL_WIREADDR: return fromwire_wireaddr(cursor, max, &addr->u.wireaddr); case ADDR_INTERNAL_FORPROXY: @@ -204,8 +221,11 @@ char *fmt_wireaddr_internal(const tal_t *ctx, a->u.unresolved.name, a->u.unresolved.port); case ADDR_INTERNAL_AUTOTOR: return tal_fmt(ctx, "autotor:%s", - fmt_wireaddr(tmpctx, &a->u.torservice)); - } + fmt_wireaddr(tmpctx, &a->u.torservice.address)); + case ADDR_INTERNAL_STATICTOR: + return tal_fmt(ctx, "statictor:%s", + fmt_wireaddr(tmpctx, &a->u.torservice.address)); +} abort(); } REGISTER_TYPE_TO_STRING(wireaddr_internal, fmt_wireaddr_internal); @@ -429,7 +449,8 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, const char **err_msg) { u16 splitport; - char *ip; + char *ip = NULL; + char *service_addr; bool needed_dns = false; /* Addresses starting with '/' are local socket paths */ @@ -452,8 +473,87 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, * an onion address. */ if (strstarts(arg, "autotor:")) { addr->itype = ADDR_INTERNAL_AUTOTOR; - return parse_wireaddr(arg + strlen("autotor:"), - &addr->u.torservice, 9051, + addr->u.torservice.port = DEFAULT_PORT; + /* Format is separated by slash. */ + char **parts = tal_strsplit(tmpctx, arg, "/", STR_EMPTY_OK); + + for (size_t i = 1; i < tal_count(parts)-1; i++) { + if (tal_strreg(tmpctx, parts[i], "torport")) { + char *endp = NULL; + char **parts_2 = tal_strsplit(tmpctx, parts[i], "=", STR_EMPTY_OK); + if (tal_count(parts_2) == 3) { + addr->u.torservice.port = strtol((const char *)parts_2[1], &endp, 10); + if (addr->u.torservice.port <= 0 || *endp != '\0') { + if (err_msg) + *err_msg = "Bad :torport: number"; + return false; + } + } else { + if (err_msg) + *err_msg = "Bad :torport: format"; + return false; + } + } + } + + service_addr = tal_fmt(tmpctx, "%s", parts[0] + strlen("autotor:")); + + return parse_wireaddr(service_addr, + &addr->u.torservice.address, 9051, + dns_ok ? NULL : &needed_dns, + err_msg); + } + + /* 'statictor:' is a special prefix meaning talk to Tor to create + * an static onion address from a blob or node id */ + if (strstarts(arg, "statictor:")) { + bool use_magic_blob = true; + addr->itype = ADDR_INTERNAL_STATICTOR; + addr->u.torservice.port = DEFAULT_PORT; + memset(&(addr->u.torservice.blob[0]), 0, sizeof(addr->u.torservice.blob)); + + /* Format is separated by slash. */ + char **parts = tal_strsplit(tmpctx, arg, "/", STR_EMPTY_OK); + for (size_t i = 1; i < tal_count(parts)-1; i++) { + if (tal_strreg(tmpctx, parts[i], "torport")) { + char *endp = NULL; + char **parts_eq = tal_strsplit(tmpctx, parts[i], "=", STR_EMPTY_OK); + if (tal_count(parts_eq) == 3) { + addr->u.torservice.port = strtol((const char *)parts_eq[1], &endp, 10); + if (addr->u.torservice.port <= 0 || *endp != '\0') { + if (err_msg) + *err_msg = "Bad :torport: number"; + return false; + } + } else { + if (err_msg) + *err_msg = "Bad :torport: format"; + return false; + } + } + if (tal_strreg(tmpctx, parts[i], "torblob")) { + char **parts_eq = tal_strsplit(tmpctx, parts[i], "=", STR_EMPTY_OK); + if (tal_count(parts_eq) == 3) { + if (strlen((char *)parts_eq[1]) == 0) { + if (err_msg) + *err_msg = "Blob too short"; + return false; + } + strncpy((char *)&(addr->u.torservice.blob[0]), (const char *)parts_eq[1], TOR_V3_BLOBLEN); + use_magic_blob = false; + } + } + } + + if (use_magic_blob) { + /* when statictor called just with the service address and or port generate the unique onion */ + strncpy((char *)&(addr->u.torservice.blob[0]), tal_fmt(tmpctx, STATIC_TOR_MAGIC_STRING), strlen(STATIC_TOR_MAGIC_STRING)); + } + + service_addr = tal_fmt(tmpctx, "%s", parts[0] + strlen("statictor:")); + + return parse_wireaddr(service_addr, + &addr->u.torservice.address, 9051, dns_ok ? NULL : &needed_dns, err_msg); } @@ -461,7 +561,7 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, splitport = port; if (!separate_address_and_port(tmpctx, arg, &ip, &splitport)) { if (err_msg) { - *err_msg = "Error parsing hostname"; + *err_msg = tal_fmt(tmpctx, "Error parsing hostname %s %s", (char *)arg, ip); } return false; } @@ -541,6 +641,7 @@ struct addrinfo *wireaddr_internal_to_addrinfo(const tal_t *ctx, return ai; case ADDR_INTERNAL_ALLPROTO: case ADDR_INTERNAL_AUTOTOR: + case ADDR_INTERNAL_STATICTOR: case ADDR_INTERNAL_FORPROXY: break; case ADDR_INTERNAL_WIREADDR: @@ -591,6 +692,7 @@ bool all_tor_addresses(const struct wireaddr_internal *wireaddr) case ADDR_INTERNAL_ALLPROTO: return false; case ADDR_INTERNAL_AUTOTOR: + case ADDR_INTERNAL_STATICTOR: continue; case ADDR_INTERNAL_WIREADDR: switch (wireaddr[i].u.wireaddr.type) { diff --git a/common/wireaddr.h b/common/wireaddr.h index 45cda2902..f0aaa1986 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -43,6 +43,8 @@ struct sockaddr_un; #define TOR_V2_ADDRLEN 10 #define TOR_V3_ADDRLEN 35 #define LARGEST_ADDRLEN TOR_V3_ADDRLEN +#define TOR_V3_BLOBLEN 64 +#define STATIC_TOR_MAGIC_STRING "gen-default-toraddress" enum wire_addr_type { ADDR_TYPE_IPV4 = 1, @@ -110,6 +112,7 @@ enum wireaddr_internal_type { ADDR_INTERNAL_AUTOTOR, ADDR_INTERNAL_FORPROXY, ADDR_INTERNAL_WIREADDR, + ADDR_INTERNAL_STATICTOR, }; /* For internal use, where we can also supply a local socket, wildcard. */ @@ -120,8 +123,13 @@ struct wireaddr_internal { struct wireaddr wireaddr; /* ADDR_INTERNAL_ALLPROTO */ u16 port; - /* ADDR_INTERNAL_AUTOTOR */ - struct wireaddr torservice; + /* ADDR_INTERNAL_AUTOTOR + * ADDR_INTERNAL_STATICTOR */ + struct torservice { + struct wireaddr address; + u16 port; + u8 blob[TOR_V3_BLOBLEN + 1]; + } torservice; /* ADDR_INTERNAL_FORPROXY */ struct unresolved { char name[256]; diff --git a/connectd/Makefile b/connectd/Makefile index 7e0b5b39b..472328b16 100644 --- a/connectd/Makefile +++ b/connectd/Makefile @@ -39,6 +39,7 @@ LIGHTNINGD_HEADERS_GEN += $(LIGHTNINGD_CONNECT_HEADERS) CONNECTD_COMMON_OBJS := \ common/amount.o \ common/base32.o \ + common/base64.o \ common/bech32.o \ common/bech32_util.o \ common/bigsize.o \ diff --git a/connectd/connectd.c b/connectd/connectd.c index c256d0a33..a1bbbaf39 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -149,7 +150,7 @@ struct daemon { /* File descriptors to listen on once we're activated. */ struct listen_fd *listen_fds; - /* Allow to define the default behavior of tot services calls*/ + /* Allow to define the default behavior of tor services calls*/ bool use_v3_autotor; }; @@ -652,6 +653,10 @@ static struct io_plan *conn_init(struct io_conn *conn, status_failed(STATUS_FAIL_INTERNAL_ERROR, "Can't connect to autotor address"); break; + case ADDR_INTERNAL_STATICTOR: + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Can't connect to statictor address"); + break; case ADDR_INTERNAL_FORPROXY: status_failed(STATUS_FAIL_INTERNAL_ERROR, "Can't connect to forproxy address"); @@ -688,6 +693,7 @@ static struct io_plan *conn_proxy_init(struct io_conn *conn, case ADDR_INTERNAL_SOCKNAME: case ADDR_INTERNAL_ALLPROTO: case ADDR_INTERNAL_AUTOTOR: + case ADDR_INTERNAL_STATICTOR: break; } @@ -731,6 +737,9 @@ static void try_connect_one_addr(struct connecting *connect) case ADDR_INTERNAL_AUTOTOR: status_failed(STATUS_FAIL_INTERNAL_ERROR, "Can't connect AUTOTOR"); + case ADDR_INTERNAL_STATICTOR: + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Can't connect STATICTOR"); case ADDR_INTERNAL_FORPROXY: use_proxy = true; break; @@ -993,6 +1002,10 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx, struct sockaddr_un addrun; int fd; struct wireaddr_internal *binding; + const u8 *blob = NULL; + struct secret random; + struct pubkey pb; + struct wireaddr *toraddr; /* Start with empty arrays, for tal_arr_expand() */ binding = tal_arr(ctx, struct wireaddr_internal, 0); @@ -1018,7 +1031,6 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx, for (size_t i = 0; i < tal_count(proposed_wireaddr); i++) { struct wireaddr_internal wa = proposed_wireaddr[i]; bool announce = (proposed_listen_announce[i] & ADDR_ANNOUNCE); - if (!(proposed_listen_announce[i] & ADDR_LISTEN)) continue; @@ -1042,6 +1054,9 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx, case ADDR_INTERNAL_AUTOTOR: /* We handle these after we have all bindings. */ continue; + case ADDR_INTERNAL_STATICTOR: + /* We handle these after we have all bindings. */ + continue; /* Special case meaning IPv6 and IPv4 */ case ADDR_INTERNAL_ALLPROTO: { bool ipv6_ok; @@ -1102,25 +1117,63 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx, for (size_t i = 0; i < tal_count(proposed_wireaddr); i++) { if (!(proposed_listen_announce[i] & ADDR_LISTEN)) continue; - if (proposed_wireaddr[i].itype != ADDR_INTERNAL_AUTOTOR) continue; + toraddr = tor_autoservice(tmpctx, + &proposed_wireaddr[i], + tor_password, + binding, + daemon->use_v3_autotor); + if (!(proposed_listen_announce[i] & ADDR_ANNOUNCE)) { - tor_autoservice(tmpctx, - &proposed_wireaddr[i].u.torservice, - tor_password, - binding, - daemon->use_v3_autotor); continue; }; - add_announcable(announcable, - tor_autoservice(tmpctx, - &proposed_wireaddr[i].u.torservice, - tor_password, - binding, - daemon->use_v3_autotor)); + add_announcable(announcable, toraddr); } + /* Now we have bindings, set up any Tor static addresses: we will point + * it at the first bound IPv4 or IPv6 address we have. */ + for (size_t i = 0; i < tal_count(proposed_wireaddr); i++) { + if (!(proposed_listen_announce[i] & ADDR_LISTEN)) + continue; + if (proposed_wireaddr[i].itype != ADDR_INTERNAL_STATICTOR) + continue; + blob = proposed_wireaddr[i].u.torservice.blob; + + if (tal_strreg(tmpctx, (char *)proposed_wireaddr[i].u.torservice.blob, STATIC_TOR_MAGIC_STRING)) { + if (pubkey_from_node_id(&pb, &daemon->id)) { + if (sodium_mlock(&random, sizeof(random)) != 0) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not lock the random prf key memory."); + randombytes_buf((void * const)&random, 32); + /* generate static tor node address, take first 32 bytes from secret of node_id plus 32 random bytes from sodiom */ + struct sha256 sha; + /* let's sha, that will clear ctx of hsm data */ + sha256(&sha, hsm_do_ecdh(tmpctx, &pb), 32); + /* even if it's a secret pub derived, tor shall see only the single sha */ + memcpy((void *)&blob[0], &sha, 32); + memcpy((void *)&blob[32], &random, 32); + /* clear our temp buffer, don't leak by extern libs core-dumps, our blob we/tal handle later */ + sodium_munlock(&random, sizeof(random)); + + } else status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not get the pub of our node id from hsm"); + } + + toraddr = tor_fixed_service(tmpctx, + &proposed_wireaddr[i], + tor_password, + blob, + find_local_address(binding), + 0); + /* get rid of blob data on our side of tor and add jitter */ + randombytes_buf((void * const)proposed_wireaddr[i].u.torservice.blob, TOR_V3_BLOBLEN); + + if (!(proposed_listen_announce[i] & ADDR_ANNOUNCE)) { + continue; + }; + add_announcable(announcable, toraddr); + } /* Sort and uniquify. */ finalize_announcable(announcable); diff --git a/connectd/tor_autoservice.c b/connectd/tor_autoservice.c index 98fd89c9b..bbc62dac3 100644 --- a/connectd/tor_autoservice.c +++ b/connectd/tor_autoservice.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -21,10 +22,6 @@ #include #include -#define MAX_TOR_COOKIE_LEN 32 -#define MAX_TOR_SERVICE_READBUFFER_LEN 255 -#define MAX_TOR_ONION_V2_ADDR_LEN 16 -#define MAX_TOR_ONION_V3_ADDR_LEN 56 static void *buf_resize(struct membuf *mb, void *buf, size_t len) { @@ -45,6 +42,30 @@ static void tor_send_cmd(struct rbuf *rbuf, const char *cmd) "Writing CRLF to Tor socket"); } +static char *tor_response_line_wfail(struct rbuf *rbuf) +{ + char *line = NULL; + + while ((line = rbuf_read_str(rbuf, '\n')) != NULL) { + status_io(LOG_IO_IN, NULL, "torcontrol", line, strlen(line)); + + /* Weird response */ + if (!strstarts(line, "250") && !strstarts(line, "550")) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tor returned '%s'", line); + + /* Last line */ + if (strstarts(line, "250 ") || strstarts(line, "550 ")) + break; + + return line + 4; + } + if (line) + return line + 4; + else + return NULL; +} + static char *tor_response_line(struct rbuf *rbuf) { char *line; @@ -74,13 +95,14 @@ static void discard_remaining_response(struct rbuf *rbuf) static struct wireaddr *make_onion(const tal_t *ctx, struct rbuf *rbuf, const struct wireaddr *local, - bool use_v3_autotor) + bool use_v3_autotor, + u16 port) { char *line; struct wireaddr *onion; -/* Now that V3 is out of Beta default to V3 autoservice onions if version is above 0.4 -*/ + /* Now that V3 is out of Beta default to V3 autoservice onions if version is above 0.4 + */ tor_send_cmd(rbuf, "PROTOCOLINFO 1"); while ((line = tor_response_line(rbuf)) != NULL) { @@ -101,13 +123,11 @@ static struct wireaddr *make_onion(const tal_t *ctx, if (!use_v3_autotor) { tor_send_cmd(rbuf, tal_fmt(tmpctx, "ADD_ONION NEW:RSA1024 Port=%d,%s Flags=DiscardPK,Detach", - /* FIXME: We *could* allow user to set Tor port */ - DEFAULT_PORT, fmt_wireaddr(tmpctx, local))); + port, fmt_wireaddr(tmpctx, local))); } else { tor_send_cmd(rbuf, tal_fmt(tmpctx, "ADD_ONION NEW:ED25519-V3 Port=%d,%s Flags=DiscardPK,Detach", - /* FIXME: We *could* allow user to set Tor port */ - DEFAULT_PORT, fmt_wireaddr(tmpctx, local))); + port, fmt_wireaddr(tmpctx, local))); } while ((line = tor_response_line(rbuf)) != NULL) { @@ -122,10 +142,10 @@ static struct wireaddr *make_onion(const tal_t *ctx, name = tal_fmt(tmpctx, "%s.onion", line); onion = tal(ctx, struct wireaddr); - if (!parse_wireaddr(name, onion, DEFAULT_PORT, false, NULL)) + if (!parse_wireaddr(name, onion, local->port, false, NULL)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Tor gave bad onion name '%s'", name); - status_info("New autotor service onion address: \"%s:%d\"", name, DEFAULT_PORT); + status_info("New autotor service onion address: \"%s:%d\" bound from extern port:%d", name, local->port, port); discard_remaining_response(rbuf); return onion; } @@ -133,6 +153,51 @@ static struct wireaddr *make_onion(const tal_t *ctx, "Tor didn't give us a ServiceID"); } +static struct wireaddr *make_fixed_onion(const tal_t *ctx, + struct rbuf *rbuf, + const struct wireaddr *local, const u8 *blob, u16 port) +{ + char *line; + struct wireaddr *onion; + char *blob64; + + blob64 = b64_encode(tmpctx, blob, 64); + + tor_send_cmd(rbuf, + tal_fmt(tmpctx, "ADD_ONION ED25519-V3:%s Port=%d,%s Flags=DiscardPK", + blob64, port, fmt_wireaddr(tmpctx, local))); + + while ((line = tor_response_line_wfail(rbuf))) { + const char *name; + if (strstarts(line, "Onion address collision")) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tor address in use"); + + if (!strstarts(line, "ServiceID=")) + continue; + line += strlen("ServiceID="); + /* Strip the trailing CR */ + if (strchr(line, '\r')) + *strchr(line, '\r') = '\0'; + + name = tal_fmt(tmpctx, "%s.onion", line); + onion = tal(ctx, struct wireaddr); + if (!parse_wireaddr(name, onion, local->port, false, NULL)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tor gave bad onion name '%s'", name); + #ifdef SUPERVERBOSE + status_info("Static Tor service onion address: \"%s:%d,%s\"from blob %s base64 %s ", + name, port ,fmt_wireaddr(tmpctx, local), blob ,blob64); + #else + status_info("Static Tor service onion address: \"%s:%d,%s\" bound from extern port %d ", + name, port ,fmt_wireaddr(tmpctx, local), port); + #endif + discard_remaining_response(rbuf); + return onion; + } + return NULL; +} + /* https://gitweb.torproject.org/torspec.git/tree/control-spec.txt: * * MidReplyLine = StatusCode "-" ReplyLine @@ -210,7 +275,7 @@ static void negotiate_auth(struct rbuf *rbuf, const char *tor_password) } /* We need to have a bound address we can tell Tor to connect to */ -static const struct wireaddr * +const struct wireaddr * find_local_address(const struct wireaddr_internal *bindings) { for (size_t i = 0; i < tal_count(bindings); i++) { @@ -226,7 +291,7 @@ find_local_address(const struct wireaddr_internal *bindings) } struct wireaddr *tor_autoservice(const tal_t *ctx, - const struct wireaddr *tor_serviceaddr, + const struct wireaddr_internal *tor_serviceaddr, const char *tor_password, const struct wireaddr_internal *bindings, const bool use_v3_autotor) @@ -239,7 +304,7 @@ struct wireaddr *tor_autoservice(const tal_t *ctx, char *buffer; laddr = find_local_address(bindings); - ai_tor = wireaddr_to_addrinfo(tmpctx, tor_serviceaddr); + ai_tor = wireaddr_to_addrinfo(tmpctx, &tor_serviceaddr->u.torservice.address); fd = socket(ai_tor->ai_family, SOCK_STREAM, 0); if (fd < 0) @@ -252,7 +317,7 @@ struct wireaddr *tor_autoservice(const tal_t *ctx, rbuf_init(&rbuf, fd, buffer, tal_count(buffer), buf_resize); negotiate_auth(&rbuf, tor_password); - onion = make_onion(ctx, &rbuf, laddr, use_v3_autotor); + onion = make_onion(ctx, &rbuf, laddr, use_v3_autotor, tor_serviceaddr->u.torservice.port); /*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 @@ -263,3 +328,42 @@ struct wireaddr *tor_autoservice(const tal_t *ctx, return onion; } + +struct wireaddr *tor_fixed_service(const tal_t *ctx, + const struct wireaddr_internal *tor_serviceaddr, + const char *tor_password, + const u8 *blob, + const struct wireaddr *bind, + const u8 index) +{ + int fd; + const struct wireaddr *laddr; + struct wireaddr *onion; + struct addrinfo *ai_tor; + struct rbuf rbuf; + char *buffer; + + laddr = bind; + ai_tor = wireaddr_to_addrinfo(tmpctx, &tor_serviceaddr->u.torservice.address); + + fd = socket(ai_tor->ai_family, SOCK_STREAM, 0); + if (fd < 0) + err(1, "Creating stream socket for Tor"); + + if (connect(fd, ai_tor->ai_addr, ai_tor->ai_addrlen) != 0) + err(1, "Connecting stream socket to Tor service"); + + buffer = tal_arr(tmpctx, char, rbuf_good_size(fd)); + rbuf_init(&rbuf, fd, buffer, tal_count(buffer), buf_resize); + + negotiate_auth(&rbuf, tor_password); + + onion = make_fixed_onion(ctx, &rbuf, laddr, blob, tor_serviceaddr->u.torservice.port); + /*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 + * stays valid until reboot this might not be desired so we can also drop Detach and use the + * read_partial to keep it open until LN drops + * DO NOT CLOSE FD TO KEEP ADDRESS ALIVE AS WE DO NOT DETACH WITH STATIC ADDRESS + */ + return onion; +} diff --git a/connectd/tor_autoservice.h b/connectd/tor_autoservice.h index 13b153c75..6906a40be 100644 --- a/connectd/tor_autoservice.h +++ b/connectd/tor_autoservice.h @@ -7,9 +7,20 @@ #include struct wireaddr *tor_autoservice(const tal_t *ctx, - const struct wireaddr *tor_serviceaddr, + const struct wireaddr_internal *tor_serviceaddr, const char *tor_password, const struct wireaddr_internal *bindings, const bool use_v3_autotor); +struct wireaddr *tor_fixed_service(const tal_t *ctx, + const struct wireaddr_internal *tor_serviceaddr, + const char *tor_password, + const u8 *blob, + const struct wireaddr *bind, + const u8 index); + +const struct wireaddr * +find_local_address(const struct wireaddr_internal *bindings); + + #endif /* LIGHTNING_CONNECTD_TOR_AUTOSERVICE_H */ diff --git a/devtools/gossipwith.c b/devtools/gossipwith.c index 49001ad9e..a0ce66f1f 100644 --- a/devtools/gossipwith.c +++ b/devtools/gossipwith.c @@ -311,6 +311,7 @@ int main(int argc, char *argv[]) break; case ADDR_INTERNAL_ALLPROTO: case ADDR_INTERNAL_AUTOTOR: + case ADDR_INTERNAL_STATICTOR: case ADDR_INTERNAL_FORPROXY: opt_usage_exit_fail("Don't support proxy use"); diff --git a/lightningd/Makefile b/lightningd/Makefile index 8dfff023c..47fbf8fc4 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -17,6 +17,7 @@ LIGHTNINGD_COMMON_OBJS := \ common/addr.o \ common/amount.o \ common/base32.o \ + common/base64.o \ common/bech32.o \ common/bech32_util.o \ common/bigsize.o \ diff --git a/lightningd/json.c b/lightningd/json.c index 0e423a086..b5b77c4da 100644 --- a/lightningd/json.c +++ b/lightningd/json.c @@ -249,7 +249,13 @@ void json_add_address_internal(struct json_stream *response, case ADDR_INTERNAL_AUTOTOR: json_object_start(response, fieldname); json_add_string(response, "type", "Tor generated address"); - json_add_address(response, "service", &addr->u.torservice); + json_add_address(response, "service", &addr->u.torservice.address); + json_object_end(response); + return; + case ADDR_INTERNAL_STATICTOR: + json_object_start(response, fieldname); + json_add_string(response, "type", "Tor from blob generated static address"); + json_add_address(response, "service", &addr->u.torservice.address); json_object_end(response); return; case ADDR_INTERNAL_FORPROXY: diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 90c2b5e03..7e1bfc85d 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -68,7 +68,7 @@ struct config { /* Minimal amount of effective funding_satoshis for accepting channels */ u64 min_capacity_sat; - /* Allow to define the default behavior of tot services calls*/ + /* Allow to define the default behavior of tor services calls*/ bool use_v3_autotor; /* This is the key we use to encrypt `hsm_secret`. */ diff --git a/lightningd/options.c b/lightningd/options.c index f4cd8de32..ef96b7fd3 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -136,6 +137,10 @@ static char *opt_add_announce_addr(const char *arg, struct lightningd *ld) if (strstarts(arg, "autotor:")) return opt_add_addr(arg, ld); + /* Check for statictor and reroute the call to --addr */ + if (strstarts(arg, "statictor:")) + return opt_add_addr(arg, ld); + err = opt_add_addr_withtype(arg, ld, ADDR_ANNOUNCE, false); if (err) return err; @@ -603,6 +608,7 @@ static const struct config mainnet_config = { /* Sets min_effective_htlc_capacity - at 1000$/BTC this is 10ct */ .min_capacity_sat = 10000, + /* Allow to define the default behavior of tor services calls*/ .use_v3_autotor = true, };