mirror of
https://github.com/ZmnSCPxj/clboss.git
synced 2026-08-14 12:43:19 +02:00
244 lines
7.8 KiB
C++
244 lines
7.8 KiB
C++
#include"Boss/Mod/ConnectFinderByDns.hpp"
|
|
#include"Boss/Msg/Begin.hpp"
|
|
#include"Boss/Msg/Init.hpp"
|
|
#include"Boss/Msg/ProposeConnectCandidates.hpp"
|
|
#include"Boss/Msg/Network.hpp"
|
|
#include"Boss/Msg/SolicitConnectCandidates.hpp"
|
|
#include"Boss/concurrent.hpp"
|
|
#include"Boss/log.hpp"
|
|
#include"Boss/random_engine.hpp"
|
|
#include"DnsSeed/get.hpp"
|
|
#include"Ev/Io.hpp"
|
|
#include"Ev/map.hpp"
|
|
#include"S/Bus.hpp"
|
|
#include"Util/make_unique.hpp"
|
|
#include<algorithm>
|
|
#include<map>
|
|
#include<string>
|
|
#include<utility>
|
|
#include<vector>
|
|
|
|
namespace {
|
|
|
|
auto const all_dnsseeds =
|
|
std::map<Boss::Msg::Network, std::vector<std::pair< std::string
|
|
, std::string
|
|
>>>
|
|
{ {Boss::Msg::Network_Bitcoin, { {"1.0.0.1", "lseed.bitcoinstats.com"}
|
|
, {"8.8.8.8", "lseed.darosior.ninja"}
|
|
}}
|
|
};
|
|
/*
|
|
<zmnscpxj> What other Lightning DNS seeds are there? lseed.darosior.ninja is not reliable from my connection, even with @1.1.1.1 or @8.8.8.8
|
|
<zmnscpxj> lseed.bitcoinstats.com works with @1.1.1.1
|
|
<zmnscpxj> I mean for SRV requests
|
|
* jonatack (~jon@37.167.109.160) has joined
|
|
* yzernik (~yzernik@12.203.56.101) has joined
|
|
<cdecker> zmnscpxj: that's usually an issue with the size of the response, since recursive resolvers cache the result they'll refuse to relay large results.
|
|
<cdecker> In my experience around 5 SRV results still work with most recursive resolvers, any more than that and they start simply timing out the requests
|
|
<cdecker> Not sure how many darosior has configured
|
|
<zmnscpxj> dig @1.1.1.1 n5.lseed.darosior.ninja SRV still gives me no answers
|
|
<zmnscpxj> I used to be able to get 25 when using @8.8.8.8 but no longer recently, hmmm
|
|
<zmnscpxj> using my ISP resolver gives me 0 results on bitcoinstats.com, I have to use @1.1.1.1
|
|
<cdecker> Yes, ISP resolvers are notoriously flaky
|
|
<zmnscpxj> dig @1.1.1.1 lseed.bitcoinstats.com SRV is fairly reliable on my ISP, wonder how reliable it is for others...?
|
|
<zmnscpxj> who is willing to try?
|
|
<cdecker> Works for me xD (no surprise there I run the resolver)
|
|
<zmnscpxj> yes, I expected that, haha
|
|
<zmnscpxj> who else runs an lseed?
|
|
<cdecker> I think roasbeef has a heavily modified version
|
|
* riclas (riclas@77.7.37.188.rev.vodafone.pt) has joined
|
|
* rdymac (uid31665@gateway/web/irccloud.com/x-lijpykrklflhqpgf) has joined
|
|
<zmnscpxj> what addr?
|
|
<zmnscpxj> what URI I mean?
|
|
<cdecker> https://github.com/lightningnetwork/lnd/blob/e135047304723024dbb72cb01932ad1a3e367804/chainregistry.go#L619-L643
|
|
<cdecker> They sidestep the recursive resolver issue by forcing TCP connections
|
|
<cdecker> dig +tcp srv nodes.lightning.directory
|
|
<zmnscpxj> okay, that works directly for me
|
|
* __gotcha (~Thunderbi@plone/gotcha) has joined
|
|
<cdecker> Downside is that the DNS server learns the IP address of all nodes querying it, whereas with recursive resolving the DNS server only sees the ISP IP
|
|
<zmnscpxj> ...ah
|
|
<zmnscpxj> is it possible to proxy that somehow? It is over TCP...?
|
|
<cdecker> See the TLS over TCP querying debate for Cloudflare
|
|
<zmnscpxj> <--- is happily ignorant of basic DNS architecture and just uses Tor browser and trusts it works
|
|
<cdecker> Hehe, DNS is pretty much just decades of clutter accumulating, and different generations of ideas clashing with each other
|
|
<cdecker> Just look at the security story to ensure cryptographic integrity of records (DNSSEC et al)
|
|
<zmnscpxj> `dig @1.1.1.1 nodes.lightning.directory SRV` works, but has this scary ";; Truncated, retrying in TCP mode." comment, is that what you refer to?
|
|
<cdecker> Yep, you can go directly to TCP mode with the `+tcp` flag
|
|
<zmnscpxj> there is no way to say "do not go into TCP mode"?
|
|
<cdecker> Dunno
|
|
<cdecker> DNS over TCP is pretty new to me as well xD
|
|
<zmnscpxj> heh
|
|
<zmnscpxj> TCP mode is the reason the dns seed can see the IP of the querier, or something else?
|
|
<zmnscpxj> +notcp stll falls back to TCP, hmmm
|
|
<zmnscpxj> though `torify dig @1.1.1.1 +tcp nodes.lightning.directory SRV` works....
|
|
<zmnscpxj> cannot find a proxy flag for dig though, sigh
|
|
<zmnscpxj> Ah, +ignore
|
|
<zmnscpxj> +ignore prevents the fallback
|
|
<zmnscpxj> hmmm
|
|
<cdecker> Yep, afaik TCP mode will directly contact the authoritative DNS server and query it.
|
|
<zmnscpxj> thanks
|
|
<cdecker> Nope, apparently I'm mistaken, and recursive resolving works with TCP
|
|
<cdecker> Need to recalibrate my mental model then xD
|
|
<zmnscpxj> haha
|
|
*/
|
|
|
|
}
|
|
|
|
namespace Boss { namespace Mod {
|
|
|
|
class ConnectFinderByDns::Impl {
|
|
private:
|
|
S::Bus& bus;
|
|
|
|
struct DnsSeedT {
|
|
std::string seed;
|
|
std::string resolver;
|
|
bool torify;
|
|
};
|
|
typedef
|
|
std::vector<DnsSeedT> DnsSeeds;
|
|
|
|
std::unique_ptr<DnsSeeds> dnsseeds;
|
|
|
|
bool always_use_proxy;
|
|
|
|
void start() {
|
|
bus.subscribe<Msg::Begin>([this](Msg::Begin const& _) {
|
|
return begin();
|
|
});
|
|
}
|
|
|
|
Ev::Io<void> begin() {
|
|
return DnsSeed::can_get().then([this](std::string why) {
|
|
if (why == "")
|
|
return enable();
|
|
return Boss::log( bus, Warn
|
|
, "DnsSeed: Cannot seed by DNS: %s"
|
|
, why.c_str()
|
|
);
|
|
});
|
|
}
|
|
|
|
Ev::Io<void> enable() {
|
|
bus.subscribe<Msg::Init>([this](Msg::Init const& init) {
|
|
always_use_proxy = init.always_use_proxy;
|
|
|
|
auto it = all_dnsseeds.find(init.network);
|
|
if ( it != all_dnsseeds.end()
|
|
&& it->second.size() != 0
|
|
) {
|
|
auto f = [](std::pair< std::string
|
|
, std::string
|
|
> e) {
|
|
auto resolver = e.first;
|
|
auto seed = e.second;
|
|
return DnsSeed::can_torify(
|
|
seed, resolver
|
|
).then([seed, resolver](bool torify) {
|
|
return Ev::lift(DnsSeedT{
|
|
seed, resolver, torify
|
|
});
|
|
});
|
|
};
|
|
auto code = Ev::map(std::move(f), it->second
|
|
).then([this
|
|
](DnsSeeds n_seeds
|
|
) {
|
|
dnsseeds = Util::make_unique<DnsSeeds>(
|
|
std::move(n_seeds)
|
|
);
|
|
return check_dnsseeds();
|
|
});
|
|
return Boss::concurrent(std::move(code));
|
|
}
|
|
return Boss::log( bus, Warn
|
|
, "DnsSeed: Cannot seed by DNS: %s"
|
|
, "No known seeds for this network."
|
|
);
|
|
});
|
|
bus.subscribe<Msg::SolicitConnectCandidates>([this](Msg::SolicitConnectCandidates const& _) {
|
|
return solicit();
|
|
});
|
|
return Ev::lift();
|
|
}
|
|
|
|
Ev::Io<void> solicit() {
|
|
if (!dnsseeds || dnsseeds->size() == 0)
|
|
return Ev::lift();
|
|
/* Pick a DNS seed, any DNS seed. */
|
|
auto& deck = *dnsseeds;
|
|
auto dist = std::uniform_int_distribution<size_t>
|
|
(0, deck.size() - 1);
|
|
auto i = dist(random_engine);
|
|
auto& seed = deck[i];
|
|
|
|
return DnsSeed::get(
|
|
seed.seed, seed.resolver, seed.torify
|
|
).then([this](std::vector<std::string> ns) {
|
|
return bus.raise(Msg::ProposeConnectCandidates{
|
|
std::move(ns)
|
|
});
|
|
});
|
|
}
|
|
|
|
/* FIXME: we should use dns-over-tcp directly (implement it
|
|
* directly somewhere in CLBOSS) and if there is a `proxy`
|
|
* setting just always assume always-use-proxy and connect
|
|
* over TCP-proxy.
|
|
*/
|
|
Ev::Io<void> check_dnsseeds() {
|
|
if (!always_use_proxy)
|
|
/* Opportunistically use torify if we could access
|
|
* over torify. */
|
|
return have_seeds();
|
|
|
|
/* If always-use-proxy, only use seeds we could
|
|
* get by torify. */
|
|
auto it = std::remove_if( dnsseeds->begin(), dnsseeds->end()
|
|
, [](DnsSeedT const& e) {
|
|
return !e.torify;
|
|
});
|
|
dnsseeds->erase(it, dnsseeds->end());
|
|
|
|
/* Is it empty now? */
|
|
if (dnsseeds->size() == 0) {
|
|
dnsseeds = nullptr;
|
|
return Boss::log( bus, Warn
|
|
, "DnsSeed: always-use-proxy set, "
|
|
"but none of our known seeds "
|
|
"could be accessed over `torify`. "
|
|
"Is `torify` installed?"
|
|
);
|
|
}
|
|
|
|
return have_seeds();
|
|
}
|
|
Ev::Io<void> have_seeds() {
|
|
return Boss::log( bus, Info
|
|
, "DnsSeed: Have %zu seeds."
|
|
, dnsseeds->size()
|
|
);
|
|
}
|
|
|
|
public:
|
|
explicit
|
|
Impl( S::Bus& bus_
|
|
) : bus(bus_)
|
|
, dnsseeds(nullptr)
|
|
{
|
|
start();
|
|
}
|
|
};
|
|
|
|
ConnectFinderByDns::ConnectFinderByDns
|
|
( S::Bus& bus
|
|
) : pimpl(Util::make_unique<Impl>(bus))
|
|
{ }
|
|
ConnectFinderByDns::ConnectFinderByDns
|
|
( ConnectFinderByDns&& o
|
|
) : pimpl(std::move(o.pimpl))
|
|
{ }
|
|
ConnectFinderByDns::~ConnectFinderByDns() { }
|
|
|
|
}}
|