diff --git a/libabyss/src/server.cpp b/libabyss/src/server.cpp index e85c29cdd6..d7e4bc5c3f 100644 --- a/libabyss/src/server.cpp +++ b/libabyss/src/server.cpp @@ -282,6 +282,7 @@ namespace abyss llarp::LogDebug("connection closed"); ConnImpl* self = static_cast< ConnImpl* >(conn->user); self->_conn = nullptr; + self->m_State = eCloseMe; } static void diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index 71a97f3043..b4c8477915 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -240,68 +240,61 @@ namespace llarp curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_RecvIdentKey); - do + + resp.clear(); + LogInfo("Getting Identity Keys from lokid..."); + if(curl_easy_perform(curl) == CURLE_OK) { - resp.clear(); - LogInfo("Getting Identity Keys from lokid..."); - if(curl_easy_perform(curl) == CURLE_OK) + try { - try + auto j = nlohmann::json::parse(resp); + if(not j.is_object()) + return false; + + const auto itr = j.find("result"); + if(itr == j.end()) + return false; + if(not itr->is_object()) + return false; + const auto k = + (*itr)["service_node_ed25519_privkey"].get< std::string >(); + if(k.size() != (identityKey.size() * 2)) { - auto j = nlohmann::json::parse(resp); - if(not j.is_object()) - continue; - - const auto itr = j.find("result"); - if(itr == j.end()) - continue; - if(not itr->is_object()) - continue; - const auto k = - (*itr)["service_node_ed25519_privkey"].get< std::string >(); - if(k.size() != (identityKey.size() * 2)) - { - if(k.empty()) - { - LogError("lokid gave no identity key"); - } - else - { - LogError("lokid gave invalid identity key"); - } - return false; - } - if(not HexDecode(k.c_str(), identityKey.data(), identityKey.size())) - continue; - if(CryptoManager::instance()->check_identity_privkey(identityKey)) + if(k.empty()) { - ret = true; + LogError("lokid gave no identity key"); } else { - LogError("lokid gave bogus identity key"); + LogError("lokid gave invalid identity key"); } + return false; } - catch(nlohmann::json::exception& ex) + if(not HexDecode(k.c_str(), identityKey.data(), identityKey.size())) + return false; + if(CryptoManager::instance()->check_identity_privkey(identityKey)) { - LogError("Bad response from lokid: ", ex.what()); + ret = true; + } + else + { + LogError("lokid gave bogus identity key"); } } - else - { - LogError("failed to get identity keys"); - } - if(ret) - { - LogInfo("Got Identity Keys from lokid: ", - RouterID(seckey_topublic(identityKey))); - break; - } - else + catch(nlohmann::json::exception& ex) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + LogError("Bad response from lokid: ", ex.what()); } - } while(true); + } + else + { + LogError("failed to get identity keys"); + } + if(ret) + { + LogInfo("Got Identity Keys from lokid: ", + RouterID(seckey_topublic(identityKey))); + } curl_easy_cleanup(curl); curl_slist_free_all(list); return ret; diff --git a/llarp/dns/message.cpp b/llarp/dns/message.cpp index 577debb4cc..602b0cba3c 100644 --- a/llarp/dns/message.cpp +++ b/llarp/dns/message.cpp @@ -84,8 +84,8 @@ namespace llarp hdr.fields = hdr_fields; hdr.qd_count = questions.size(); hdr.an_count = answers.size(); - hdr.ns_count = authorities.size(); - hdr.ar_count = additional.size(); + hdr.ns_count = 0; + hdr.ar_count = 0; if(!hdr.Encode(buf)) return false; @@ -98,14 +98,6 @@ namespace llarp if(!answer.Encode(buf)) return false; - for(const auto& auth : authorities) - if(!auth.Encode(buf)) - return false; - - for(const auto& rr : additional) - if(!rr.Encode(buf)) - return false; - return true; } @@ -125,28 +117,10 @@ namespace llarp { if(not an.Decode(buf)) { - llarp::LogError("failed to decode answer"); - return false; - } - } - /* - for(auto& auth : authorities) - { - if(!auth.Decode(buf)) - { - llarp::LogError("failed to decode auth"); + llarp::LogDebug("failed to decode answer"); return false; } } - for(auto& rr : additional) - { - if(!rr.Decode(buf)) - { - llarp::LogError("failed to decode additional"); - return false; - } - } - */ return true; } @@ -162,12 +136,18 @@ namespace llarp } } + static constexpr uint16_t + reply_flags(uint16_t setbits) + { + return setbits | flags_QR | flags_AA | flags_RA; + } + void Message::AddINReply(llarp::huint128_t ip, bool isV6, RR_TTL_t ttl) { if(questions.size()) { - hdr_fields |= flags_QR | flags_AA | flags_RA; + hdr_fields = reply_flags(hdr_fields); ResourceRecord rec; rec.rr_name = questions[0].qname; rec.rr_class = qClassIN; @@ -193,7 +173,8 @@ namespace llarp { if(questions.size()) { - hdr_fields |= flags_QR | flags_AA | flags_RA; + hdr_fields = reply_flags(hdr_fields); + const auto& question = questions[0]; answers.emplace_back(); auto& rec = answers.back(); @@ -212,12 +193,38 @@ namespace llarp } } + void + Message::AddNSReply(std::string name, RR_TTL_t ttl) + { + if(not questions.empty()) + { + hdr_fields = reply_flags(hdr_fields); + + const auto& question = questions[0]; + answers.emplace_back(); + auto& rec = answers.back(); + rec.rr_name = question.qname; + rec.rr_type = qTypeNS; + rec.rr_class = qClassIN; + rec.ttl = ttl; + std::array< byte_t, 512 > tmp = {{0}}; + llarp_buffer_t buf(tmp); + if(EncodeName(&buf, name)) + { + buf.sz = buf.cur - buf.base; + rec.rData.resize(buf.sz); + memcpy(rec.rData.data(), buf.base, buf.sz); + } + } + } + void Message::AddCNAMEReply(std::string name, RR_TTL_t ttl) { if(questions.size()) { - hdr_fields |= flags_QR | flags_AA | flags_RA; + hdr_fields = reply_flags(hdr_fields); + const auto& question = questions[0]; answers.emplace_back(); auto& rec = answers.back(); @@ -241,7 +248,8 @@ namespace llarp { if(questions.size()) { - hdr_fields |= flags_QR | flags_AA; + hdr_fields = reply_flags(hdr_fields); + const auto& question = questions[0]; answers.emplace_back(); auto& rec = answers.back(); @@ -266,7 +274,7 @@ namespace llarp if(questions.size()) { // authorative response with recursion available - hdr_fields |= flags_QR | flags_AA | flags_RA; + hdr_fields = reply_flags(hdr_fields); // don't allow recursion on this request hdr_fields &= ~flags_RD; hdr_fields |= flags_RCODENameError; diff --git a/llarp/dns/message.hpp b/llarp/dns/message.hpp index 108a437ab4..3d1987ece4 100644 --- a/llarp/dns/message.hpp +++ b/llarp/dns/message.hpp @@ -69,6 +69,9 @@ namespace llarp void AddAReply(std::string name, RR_TTL_t ttl = 1); + void + AddNSReply(std::string name, RR_TTL_t ttl = 1); + bool Encode(llarp_buffer_t* buf) const override; diff --git a/llarp/dns/rr.cpp b/llarp/dns/rr.cpp index 97511f4cc4..c29a4dce0f 100644 --- a/llarp/dns/rr.cpp +++ b/llarp/dns/rr.cpp @@ -58,22 +58,22 @@ namespace llarp return false; if(!buf->read_uint16(rr_type)) { - llarp::LogError("failed to decode rr type"); + llarp::LogDebug("failed to decode rr type"); return false; } if(!buf->read_uint16(rr_class)) { - llarp::LogError("failed to decode rr class"); + llarp::LogDebug("failed to decode rr class"); return false; } if(!buf->read_uint32(ttl)) { - llarp::LogError("failed to decode ttl"); + llarp::LogDebug("failed to decode ttl"); return false; } if(!DecodeRData(buf, rData)) { - llarp::LogError("failed to decode rr rdata ", *this); + llarp::LogDebug("failed to decode rr rdata ", *this); return false; } return true; diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 6d620c5f54..ea3ad169b1 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -53,10 +53,12 @@ namespace llarp bool BaseSession::ShouldBuildMore(llarp_time_t now) const { + if(BuildCooldownHit(now)) + return false; const size_t expect = (1 + (numPaths / 2)); // check 30 seconds into the future and see if we need more paths const llarp_time_t future = now + 30s + buildIntervalLimit; - return NumPathsExistingAt(future) < expect && !BuildCooldownHit(now); + return NumPathsExistingAt(future) < expect; } void @@ -259,6 +261,8 @@ namespace llarp bool BaseSession::UrgentBuild(llarp_time_t now) const { + if(BuildCooldownHit(now)) + return false; if(!IsReady()) return NumInStatus(path::ePathBuilding) < numPaths; return path::Builder::UrgentBuild(now); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index e4468ab723..7858f7dc09 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -448,7 +448,7 @@ namespace llarp } else { - auto replyMsg = std::make_shared< dns::Message >(msg); + auto replyMsg = std::make_shared< dns::Message >(std::move(msg)); using service::Address; using service::OutboundContext; return EnsurePathToService( @@ -509,12 +509,15 @@ namespace llarp else if(msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeAAAA) { - const bool isV6 = - msg.questions[0].qtype == dns::qTypeAAAA && SupportsV6(); + const bool isV6 = msg.questions[0].qtype == dns::qTypeAAAA; const bool isV4 = msg.questions[0].qtype == dns::qTypeA; llarp::service::Address addr; + if(isV6 && !SupportsV6()) + { // empty reply but not a NXDOMAIN so that client can retry IPv4 + msg.AddNSReply("localhost.loki."); + } // on MacOS this is a typeA query - if(is_random_snode(msg)) + else if(is_random_snode(msg)) { RouterID random; if(Router()->GetRandomGoodRouter(random)) @@ -554,7 +557,7 @@ namespace llarp } else { - auto replyMsg = std::make_shared< dns::Message >(std::move(msg)); + auto replyMsg = std::make_shared< dns::Message >(msg); using service::Address; using service::OutboundContext; return EnsurePathToService( diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 538a36abb6..4b564677fe 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -278,6 +278,7 @@ namespace llarp if(ctx) { huint128_t ip = ObtainIPForAddr(addr, snode); + query->answers.clear(); query->AddINReply(ip, sendIPv6); } else diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 8790b12b7e..df375a8c6f 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -146,11 +146,10 @@ namespace llarp return; util::Lock l(_mutex); - - m_PersistingSessions[remote] = - std::max(until, m_PersistingSessions[remote]); - LogDebug("persist session to ", remote, " until ", - m_PersistingSessions[remote].count()); + auto &curr = m_PersistingSessions[remote]; + if(until > curr) + curr = until; + LogDebug("persist session to ", remote, " until ", curr - time_now_ms()); } void @@ -307,7 +306,6 @@ namespace llarp auto link = GetLinkWithSessionTo(itr->first); if(link) { - LogDebug("keepalive to ", itr->first); link->KeepAliveSessionTo(itr->first); } else diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 9e67a3ab6c..b8550dbb0e 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -267,7 +267,11 @@ namespace llarp { Lock_t l(m_AuthedLinksMutex); if(m_AuthedLinks.count(rc.pubkey) >= MaxSessionsPerKey) + { + LogDebug("Too many links to ", RouterID{rc.pubkey}, + ", not establishing another one"); return false; + } } llarp::AddressInfo to; if(!PickAddress(rc, to)) @@ -276,7 +280,12 @@ namespace llarp { Lock_t l(m_PendingMutex); if(m_Pending.count(addr) >= MaxSessionsPerKey) + { + LogDebug("Too many pending connections to ", addr, + " while establishing to ", RouterID{rc.pubkey}, + ", not establishing another"); return false; + } } std::shared_ptr< ILinkSession > s = NewOutboundSession(rc, to); if(PutSession(s)) @@ -385,7 +394,10 @@ namespace llarp while(itr != range.second) { if(itr->second->ShouldPing()) + { + LogDebug("keepalive to ", remote); itr->second->SendKeepAlive(); + } ++itr; } } diff --git a/llarp/link/server.hpp b/llarp/link/server.hpp index c46d14899a..733cbaf047 100644 --- a/llarp/link/server.hpp +++ b/llarp/link/server.hpp @@ -69,9 +69,6 @@ namespace llarp bool HasSessionTo(const RouterID& pk); - bool - HasSessionVia(const Addr& addr); - void ForEachSession(std::function< void(const ILinkSession*) > visit, bool randomize = false) const EXCLUDES(m_AuthedLinksMutex); diff --git a/llarp/net/net_addr.cpp b/llarp/net/net_addr.cpp index d4a9a4df5b..31660af45e 100644 --- a/llarp/net/net_addr.cpp +++ b/llarp/net/net_addr.cpp @@ -379,11 +379,13 @@ namespace llarp bool Addr::operator==(const Addr& other) const { - if(af() == AF_INET && other.af() == AF_INET) - return port() == other.port() && addr4()->s_addr == other.addr4()->s_addr; + if(af() != other.af() || port() != other.port()) + return false; - return af() == other.af() && memcmp(addr6(), other.addr6(), 16) == 0 - && port() == other.port(); + if(af() == AF_INET) + return addr4()->s_addr == other.addr4()->s_addr; + + return memcmp(addr6(), other.addr6(), 16) == 0; } Addr& diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 6c2282a1b0..f16153bc79 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -525,52 +525,6 @@ llarp_nodedb::select_random_exit(llarp::RouterContact &result) return false; } -bool -llarp_nodedb::select_random_hop(const llarp::RouterContact &prev, - llarp::RouterContact &result, size_t N) -{ - llarp::util::Lock lock(access); - /// checking for "guard" status for N = 0 is done by caller inside of - /// pathbuilder's scope - size_t sz = entries.size(); - if(sz < 3) - return false; - if(!N) - return false; - llarp_time_t now = llarp::time_now_ms(); - - auto itr = entries.begin(); - size_t pos = llarp::randint() % sz; - std::advance(itr, pos); - auto start = itr; - while(itr == entries.end()) - { - if(prev.pubkey != itr->second.rc.pubkey) - { - if(itr->second.rc.addrs.size() && !itr->second.rc.IsExpired(now)) - { - result = itr->second.rc; - return true; - } - } - itr++; - } - itr = entries.begin(); - while(itr != start) - { - if(prev.pubkey != itr->second.rc.pubkey) - { - if(itr->second.rc.addrs.size() && !itr->second.rc.IsExpired(now)) - { - result = itr->second.rc; - return true; - } - } - ++itr; - } - return false; -} - bool llarp_nodedb::select_random_hop_excluding( llarp::RouterContact &result, const std::set< llarp::RouterID > &exclude) @@ -583,36 +537,24 @@ llarp_nodedb::select_random_hop_excluding( { return false; } - llarp_time_t now = llarp::time_now_ms(); - auto itr = entries.begin(); - size_t pos = llarp::randint() % sz; - std::advance(itr, pos); - auto start = itr; - while(itr == entries.end()) + const size_t pos = llarp::randint() % sz; + const auto start = std::next(entries.begin(), pos); + for(auto itr = start; itr != entries.end(); ++itr) { - if(exclude.count(itr->first) == 0) + if(exclude.count(itr->first) == 0 and itr->second.rc.IsPublicRouter()) { - if(itr->second.rc.addrs.size() && !itr->second.rc.IsExpired(now)) - { - result = itr->second.rc; - return true; - } + result = itr->second.rc; + return true; } - itr++; } - itr = entries.begin(); - while(itr != start) + for(auto itr = entries.begin(); itr != start; ++itr) { - if(exclude.count(itr->first) == 0) + if(exclude.count(itr->first) == 0 and itr->second.rc.IsPublicRouter()) { - if(itr->second.rc.addrs.size() && !itr->second.rc.IsExpired(now)) - { - result = itr->second.rc; - return true; - } + result = itr->second.rc; + return true; } - ++itr; } return false; } diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 90c959a5dd..90790e4603 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -154,10 +154,6 @@ struct llarp_nodedb bool select_random_exit(llarp::RouterContact &rc) EXCLUDES(access); - bool - select_random_hop(const llarp::RouterContact &prev, - llarp::RouterContact &result, size_t N) EXCLUDES(access); - bool select_random_hop_excluding(llarp::RouterContact &result, const std::set< llarp::RouterID > &exclude) diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 7208fdd75d..7b7bd9783a 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -725,18 +725,31 @@ namespace llarp { GossipRCIfNeeded(_rc); } - - if(isSvcNode && _rcLookupHandler.HaveReceivedWhitelist()) - { - // remove RCs for nodes that are no longer allowed by network policy - nodedb()->RemoveIf([&](const RouterContact &rc) -> bool { - if(IsBootstrapNode(rc.pubkey)) - return false; - if(not rc.IsPublicRouter()) - return true; - return !_rcLookupHandler.RemoteIsAllowed(rc.pubkey); - }); - } + const bool gotWhitelist = _rcLookupHandler.HaveReceivedWhitelist(); + // remove RCs for nodes that are no longer allowed by network policy + nodedb()->RemoveIf([&](const RouterContact &rc) -> bool { + // don't purge bootstrap nodes from nodedb + if(IsBootstrapNode(rc.pubkey)) + return false; + // if for some reason we stored an RC that isn't a valid router + // purge this entry + if(not rc.IsPublicRouter()) + return true; + // clients have a notion of a whilelist + // we short circuit logic here so we dont remove + // routers that are not whitelisted for first hops + if(not isSvcNode) + return false; + // if we have a whitelist enabled and we don't + // have the whitelist yet don't remove the entry + if(whitelistRouters and not gotWhitelist) + return false; + // if we have no whitelist enabled or we have + // the whitelist enabled and we got the whitelist + // check against the whitelist and remove if it's not + // in the whitelist OR if there is no whitelist don't remove + return not _rcLookupHandler.RemoteIsAllowed(rc.pubkey); + }); _linkManager.CheckPersistingSessions(now); diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 3d483dd064..41291e131c 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -667,7 +667,7 @@ namespace llarp auto range = serviceLookups.equal_range(addr); auto i = range.first; - if(i != range.second) + while(i != range.second) { i->second(addr, itr->second.get()); ++i; @@ -945,7 +945,7 @@ namespace llarp LogError(Name(), " failed to lookup ", addr.ToString(), " from ", endpoint); fails[endpoint] = fails[endpoint] + 1; - // inform all + // inform one auto range = lookups.equal_range(addr); auto itr = range.first; if(itr != range.second)