mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-20 13:54:36 +01:00
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 <saibato.naga@pm.me> Add base64 encode/decode to common We need this to encode the blob for the tor service Signed-off-by: Saibato <saibato.naga@pm.me>
This commit is contained in:
parent
99ff86f6fe
commit
f6006f43a9
14 changed files with 385 additions and 44 deletions
|
@ -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 \
|
||||
|
|
37
common/base64.c
Normal file
37
common/base64.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include <common/base64.h>
|
||||
#include <sodium.h>
|
||||
#include <sodium/utils.h>
|
||||
|
||||
/* 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;
|
||||
}
|
10
common/base64.h
Normal file
10
common/base64.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef LIGHTNING_COMMON_BASE64_H
|
||||
#define LIGHTNING_COMMON_BASE64_H
|
||||
#include "config.h"
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
|
||||
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 */
|
|
@ -1,6 +1,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/mem/mem.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sodium/randombytes.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <wire/wire.h>
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <secp256k1_ecdh.h>
|
||||
#include <sodium.h>
|
||||
#include <sodium/randombytes.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/tal/grab_file/grab_file.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/base64.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <common/utils.h>
|
||||
#include <common/wireaddr.h>
|
||||
|
@ -21,10 +22,6 @@
|
|||
#include <unistd.h>
|
||||
#include <wire/wire.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -7,9 +7,20 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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`. */
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/tal/path/path.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/base64.h>
|
||||
#include <common/derive_basepoints.h>
|
||||
#include <common/features.h>
|
||||
#include <common/json_command.h>
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue