mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
Merge #10446: net: avoid extra dns query per seed
c1be285
chainparams: make supported service bits option explicit (Cory Fields)d5c7c1c
net: use an internal address for fixed seeds (Cory Fields)6cdc488
net: switch to dummy internal ip for dns seed source (Cory Fields)6d0bd5b
net: do not allow resolving to an internal address (Cory Fields)7f31762
net: add an internal subnet for representing unresolved hostnames (Cory Fields) Tree-SHA512: 9bf1042bef546ac3ef0e0d3a9a5555eb21628ff2674a0cf8c6367194b22bfdab477adf452c0e7c56f44e0fb37debc5e14bdb623452e076fb9c492c7702601d7a
This commit is contained in:
parent
f68c7bc5c8
commit
64ef42c797
@ -313,10 +313,9 @@ public:
|
||||
assert(consensus.hashGenesisBlock == uint256S("0x00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6"));
|
||||
assert(genesis.hashMerkleRoot == uint256S("0xe0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7"));
|
||||
|
||||
|
||||
vSeeds.push_back(CDNSSeedData("dash.org", "dnsseed.dash.org"));
|
||||
vSeeds.push_back(CDNSSeedData("dashdot.io", "dnsseed.dashdot.io"));
|
||||
vSeeds.push_back(CDNSSeedData("masternode.io", "dnsseed.masternode.io"));
|
||||
vSeeds.emplace_back("dash.org", "dnsseed.dash.org");
|
||||
vSeeds.emplace_back("dashdot.io", "dnsseed.dashdot.io");
|
||||
vSeeds.emplace_back("masternode.io", "dnsseed.masternode.io");
|
||||
|
||||
// Dash addresses start with 'X'
|
||||
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,76);
|
||||
@ -493,8 +492,8 @@ public:
|
||||
|
||||
vSeeds.clear();
|
||||
// nodes with support for servicebits filtering should be at the top
|
||||
vSeeds.push_back(CDNSSeedData("dashdot.io", "testnet-seed.dashdot.io"));
|
||||
vSeeds.push_back(CDNSSeedData("masternode.io", "test.dnsseed.masternode.io"));
|
||||
vSeeds.emplace_back("dashdot.io", "testnet-seed.dashdot.io");
|
||||
vSeeds.emplace_back("masternode.io", "test.dnsseed.masternode.io");
|
||||
|
||||
// Testnet Dash addresses start with 'y'
|
||||
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,140);
|
||||
|
@ -15,9 +15,9 @@
|
||||
#include <vector>
|
||||
|
||||
struct CDNSSeedData {
|
||||
std::string name, host;
|
||||
std::string host;
|
||||
bool supportsServiceBitsFiltering;
|
||||
CDNSSeedData(const std::string &strName, const std::string &strHost, bool supportsServiceBitsFilteringIn = false) : name(strName), host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {}
|
||||
CDNSSeedData(const std::string &strHost, bool supportsServiceBitsFilteringIn) : host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {}
|
||||
};
|
||||
|
||||
struct SeedSpec6 {
|
||||
|
24
src/net.cpp
24
src/net.cpp
@ -250,7 +250,7 @@ bool RemoveLocal(const CService& addr)
|
||||
/** Make a particular network entirely off-limits (no automatic connects to it) */
|
||||
void SetLimited(enum Network net, bool fLimited)
|
||||
{
|
||||
if (net == NET_UNROUTABLE)
|
||||
if (net == NET_UNROUTABLE || net == NET_INTERNAL)
|
||||
return;
|
||||
LOCK(cs_mapLocalHost);
|
||||
vfLimited[net] = fLimited;
|
||||
@ -1713,7 +1713,12 @@ void CConnman::ThreadDNSAddressSeed()
|
||||
std::vector<CNetAddr> vIPs;
|
||||
std::vector<CAddress> vAdd;
|
||||
ServiceFlags requiredServiceBits = nRelevantServices;
|
||||
if (LookupHost(GetDNSHost(seed, &requiredServiceBits).c_str(), vIPs, 0, true))
|
||||
std::string host = GetDNSHost(seed, &requiredServiceBits);
|
||||
CNetAddr resolveSource;
|
||||
if (!resolveSource.SetInternal(host)) {
|
||||
continue;
|
||||
}
|
||||
if (LookupHost(host.c_str(), vIPs, 0, true))
|
||||
{
|
||||
for (const CNetAddr& ip : vIPs)
|
||||
{
|
||||
@ -1723,18 +1728,7 @@ void CConnman::ThreadDNSAddressSeed()
|
||||
vAdd.push_back(addr);
|
||||
found++;
|
||||
}
|
||||
}
|
||||
if (interruptNet) {
|
||||
return;
|
||||
}
|
||||
// TODO: The seed name resolve may fail, yielding an IP of [::], which results in
|
||||
// addrman assigning the same source to results from different seeds.
|
||||
// This should switch to a hard-coded stable dummy IP for each seed name, so that the
|
||||
// resolve is not required at all.
|
||||
if (!vIPs.empty()) {
|
||||
CService seedSource;
|
||||
Lookup(seed.name.c_str(), seedSource, 0, true);
|
||||
addrman.Add(vAdd, seedSource);
|
||||
addrman.Add(vAdd, resolveSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1833,7 +1827,7 @@ void CConnman::ThreadOpenConnections()
|
||||
if (!done) {
|
||||
LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
|
||||
CNetAddr local;
|
||||
LookupHost("127.0.0.1", local, false);
|
||||
local.SetInternal("fixedseeds");
|
||||
addrman.Add(convertSeed6(Params().FixedSeeds()), local);
|
||||
done = true;
|
||||
}
|
||||
|
@ -16,6 +16,9 @@
|
||||
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
|
||||
|
||||
// 0xFD + sha256("bitcoin")[0:5]
|
||||
static const unsigned char g_internal_prefix[] = { 0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 };
|
||||
|
||||
bool fAllowPrivateNet = DEFAULT_ALLOWPRIVATENET;
|
||||
|
||||
void CNetAddr::Init()
|
||||
@ -45,6 +48,18 @@ void CNetAddr::SetRaw(Network network, const uint8_t *ip_in)
|
||||
}
|
||||
}
|
||||
|
||||
bool CNetAddr::SetInternal(const std::string &name)
|
||||
{
|
||||
if (name.empty()) {
|
||||
return false;
|
||||
}
|
||||
unsigned char hash[32] = {};
|
||||
CSHA256().Write((const unsigned char*)name.data(), name.size()).Finalize(hash);
|
||||
memcpy(ip, g_internal_prefix, sizeof(g_internal_prefix));
|
||||
memcpy(ip + sizeof(g_internal_prefix), hash, sizeof(ip) - sizeof(g_internal_prefix));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetAddr::SetSpecial(const std::string &strName)
|
||||
{
|
||||
if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
|
||||
@ -87,7 +102,7 @@ bool CNetAddr::IsIPv4() const
|
||||
|
||||
bool CNetAddr::IsIPv6() const
|
||||
{
|
||||
return (!IsIPv4() && !IsTor());
|
||||
return (!IsIPv4() && !IsTor() && !IsInternal());
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC1918() const
|
||||
@ -202,6 +217,9 @@ bool CNetAddr::IsValid() const
|
||||
if (IsRFC3849())
|
||||
return false;
|
||||
|
||||
if (IsInternal())
|
||||
return false;
|
||||
|
||||
if (IsIPv4())
|
||||
{
|
||||
// INADDR_NONE
|
||||
@ -224,11 +242,19 @@ bool CNetAddr::IsRoutable() const
|
||||
return false;
|
||||
if (!fAllowPrivateNet && IsRFC1918())
|
||||
return false;
|
||||
return !(IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal());
|
||||
return !(IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal() || IsInternal());
|
||||
}
|
||||
|
||||
bool CNetAddr::IsInternal() const
|
||||
{
|
||||
return memcmp(ip, g_internal_prefix, sizeof(g_internal_prefix)) == 0;
|
||||
}
|
||||
|
||||
enum Network CNetAddr::GetNetwork() const
|
||||
{
|
||||
if (IsInternal())
|
||||
return NET_INTERNAL;
|
||||
|
||||
if (!IsRoutable())
|
||||
return NET_UNROUTABLE;
|
||||
|
||||
@ -245,6 +271,8 @@ std::string CNetAddr::ToStringIP(bool fUseGetnameinfo) const
|
||||
{
|
||||
if (IsTor())
|
||||
return EncodeBase32(&ip[6], 10) + ".onion";
|
||||
if (IsInternal())
|
||||
return EncodeBase32(ip + sizeof(g_internal_prefix), sizeof(ip) - sizeof(g_internal_prefix)) + ".internal";
|
||||
if (fUseGetnameinfo)
|
||||
{
|
||||
CService serv(*this, 0);
|
||||
@ -315,9 +343,15 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
nClass = 255;
|
||||
nBits = 0;
|
||||
}
|
||||
|
||||
// all unroutable addresses belong to the same group
|
||||
if (!IsRoutable())
|
||||
// all internal-usage addresses get their own group
|
||||
if (IsInternal())
|
||||
{
|
||||
nClass = NET_INTERNAL;
|
||||
nStartByte = sizeof(g_internal_prefix);
|
||||
nBits = (sizeof(ip) - sizeof(g_internal_prefix)) * 8;
|
||||
}
|
||||
// all other unroutable addresses belong to the same group
|
||||
else if (!IsRoutable())
|
||||
{
|
||||
nClass = NET_UNROUTABLE;
|
||||
nBits = 0;
|
||||
@ -403,7 +437,7 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
|
||||
REACH_PRIVATE
|
||||
};
|
||||
|
||||
if (!IsRoutable())
|
||||
if (!IsRoutable() || IsInternal())
|
||||
return REACH_UNREACHABLE;
|
||||
|
||||
int ourNet = GetExtNetwork(this);
|
||||
@ -562,7 +596,7 @@ std::string CService::ToStringPort() const
|
||||
|
||||
std::string CService::ToStringIPPort(bool fUseGetnameinfo) const
|
||||
{
|
||||
if (IsIPv4() || IsTor()) {
|
||||
if (IsIPv4() || IsTor() || IsInternal()) {
|
||||
return ToStringIP(fUseGetnameinfo) + ":" + ToStringPort();
|
||||
} else {
|
||||
return "[" + ToStringIP(fUseGetnameinfo) + "]:" + ToStringPort();
|
||||
|
@ -24,6 +24,7 @@ enum Network
|
||||
NET_IPV4,
|
||||
NET_IPV6,
|
||||
NET_TOR,
|
||||
NET_INTERNAL,
|
||||
|
||||
NET_MAX,
|
||||
};
|
||||
@ -47,6 +48,12 @@ class CNetAddr
|
||||
*/
|
||||
void SetRaw(Network network, const uint8_t *data);
|
||||
|
||||
/**
|
||||
* Transform an arbitrary string into a non-routable ipv6 address.
|
||||
* Useful for mapping resolved addresses back to their source.
|
||||
*/
|
||||
bool SetInternal(const std::string& name);
|
||||
|
||||
bool SetSpecial(const std::string &strName); // for Tor addresses
|
||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor)
|
||||
@ -66,6 +73,7 @@ class CNetAddr
|
||||
bool IsTor() const;
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsInternal() const;
|
||||
bool IsValid() const;
|
||||
enum Network GetNetwork() const;
|
||||
std::string ToString() const;
|
||||
|
@ -108,17 +108,22 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
|
||||
struct addrinfo *aiTrav = aiRes;
|
||||
while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
|
||||
{
|
||||
CNetAddr resolved;
|
||||
if (aiTrav->ai_family == AF_INET)
|
||||
{
|
||||
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
|
||||
vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr));
|
||||
resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr);
|
||||
}
|
||||
|
||||
if (aiTrav->ai_family == AF_INET6)
|
||||
{
|
||||
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
|
||||
struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
|
||||
vIP.push_back(CNetAddr(s6->sin6_addr, s6->sin6_scope_id));
|
||||
resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
|
||||
}
|
||||
/* Never allow resolving to an internal address. Consider any such result invalid */
|
||||
if (!resolved.IsInternal()) {
|
||||
vIP.push_back(resolved);
|
||||
}
|
||||
|
||||
aiTrav = aiTrav->ai_next;
|
||||
|
@ -398,7 +398,7 @@ static UniValue GetNetworksInfo()
|
||||
for(int n=0; n<NET_MAX; ++n)
|
||||
{
|
||||
enum Network network = static_cast<enum Network>(n);
|
||||
if(network == NET_UNROUTABLE)
|
||||
if(network == NET_UNROUTABLE || network == NET_INTERNAL)
|
||||
continue;
|
||||
proxyType proxy;
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
|
@ -26,6 +26,13 @@ static CSubNet ResolveSubNet(const char* subnet)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CNetAddr CreateInternal(const char* host)
|
||||
{
|
||||
CNetAddr addr;
|
||||
addr.SetInternal(host);
|
||||
return addr;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_networks)
|
||||
{
|
||||
BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
|
||||
@ -33,6 +40,7 @@ BOOST_AUTO_TEST_CASE(netbase_networks)
|
||||
BOOST_CHECK(ResolveIP("8.8.8.8").GetNetwork() == NET_IPV4);
|
||||
BOOST_CHECK(ResolveIP("2001::8888").GetNetwork() == NET_IPV6);
|
||||
BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR);
|
||||
BOOST_CHECK(CreateInternal("foo.com").GetNetwork() == NET_INTERNAL);
|
||||
|
||||
}
|
||||
|
||||
@ -59,6 +67,8 @@ BOOST_AUTO_TEST_CASE(netbase_properties)
|
||||
BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable());
|
||||
BOOST_CHECK(ResolveIP("2001::1").IsRoutable());
|
||||
BOOST_CHECK(ResolveIP("127.0.0.1").IsValid());
|
||||
BOOST_CHECK(CreateInternal("FD6B:88C0:8724:edb1:8e4:3588:e546:35ca").IsInternal());
|
||||
BOOST_CHECK(CreateInternal("bar.com").IsInternal());
|
||||
|
||||
}
|
||||
|
||||
@ -104,6 +114,11 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
|
||||
BOOST_CHECK(TestParse("[::]:9999", "[::]:9999"));
|
||||
BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535"));
|
||||
BOOST_CHECK(TestParse(":::", "[::]:0"));
|
||||
|
||||
// verify that an internal address fails to resolve
|
||||
BOOST_CHECK(TestParse("[fd6b:88c0:8724:1:2:3:4:5]", "[::]:0"));
|
||||
// and that a one-off resolves correctly
|
||||
BOOST_CHECK(TestParse("[fd6c:88c0:8724:1:2:3:4:5]", "[fd6c:88c0:8724:1:2:3:4:5]:65535"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(onioncat_test)
|
||||
@ -282,6 +297,9 @@ BOOST_AUTO_TEST_CASE(netbase_getgroup)
|
||||
BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net
|
||||
BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6
|
||||
|
||||
// baz.net sha256 hash: 12929400eb4607c4ac075f087167e75286b179c693eb059a01774b864e8fe505
|
||||
std::vector<unsigned char> internal_group = {NET_INTERNAL, 0x12, 0x92, 0x94, 0x00, 0xeb, 0x46, 0x07, 0xc4, 0xac, 0x07};
|
||||
BOOST_CHECK(CreateInternal("baz.net").GetGroup() == internal_group);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user