While fiddling around with the path to ADDRv2 and #19031 I noticed that it might be useful if we have already ED25519-V3 onions for the node created in torcontrol.
torcontrol: Create also a V3 ed25519-V3 onion address. #19485
pull Saibato wants to merge 1 commits into bitcoin:master from Saibato:add-ed25519 changing 1 files +57 −24-
Saibato commented at 3:55 PM on July 10, 2020: contributor
- fanquake added the label P2P on Jul 10, 2020
-
luke-jr commented at 3:59 PM on July 10, 2020: member
What's the point if we can't advertise the address?
Also, shouldn't it be possible to have both v2 and v3 addresses?
-
Saibato commented at 4:17 PM on July 10, 2020: contributor
What's the point if we can't advertise the address?
Also, shouldn't it be possible to have both v2 and v3 addresses?
If BIP155 get merged... ? I have a working patch for @vasild Tor v3/ADDRv2 implementation that i will post him now.
Btw. I use for myself a patch to tunnel V3 in V2 ADDR message that works ̶ ̶r̶i̶g̶h̶t̶ ̶n̶o̶w̶ ̶w̶i̶t̶h̶ ̶c̶u̶r̶r̶e̶n̶t̶ ̶m̶a̶s̶t̶e̶r̶.̶ on top of the current p2p ;protocol. The old nodes would barely notice and drop the new address, since they are unrouteable local ipv6. And only the patched nodes have full Tor v3 support. It uses FC00/7 address that we ignore and resembles on the end to a v3 address to drop in and out from the peers.dat, That should not even need a BIP since its fully transparent to the actual implementation, although a bit ugly and stealth.
Also, shouldn't it be possible to have both v2 and v3 addresses?
This PR create both V2 and V3 in one sweep.
-
luke-jr commented at 4:30 PM on July 10, 2020: member
It uses FC00/7 address that we ignore and resembles on the end to a v3 address to drop in and out from the peers.dat, That should not even need a BIP since its fully transparent to the actual implementation, although a bit ugly and stealth.
I don't know why it wouldn't need a BIP... it's a protocol change at the p2p layer still.
-
Saibato commented at 4:50 PM on July 10, 2020: contributor
I don't know why it wouldn't need a BIP... it's a protocol change at the p2p layer ...
So then we propose this ? I posted this tunnel patch in the comment as diff.
This v3 tunnel protocol is unrelated to this PR , Here we just create the service descriptor and do effectively none with it, but sure you can i.e. post the new v3 address grabbed from the log to your counterpart node and do a manual addnode on the remote side until BIP155 gets merged.
-
DrahtBot commented at 12:20 AM on July 11, 2020: member
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--174a7506f384e20aa4161008e828411d-->
Conflicts
Reviewers, this pull request conflicts with the following ones:
- #19991 (net: Use alternative port for incoming Tor connections by hebasto)
- #19954 (tor: complete the TORv3 implementation by vasild)
- #19288 (tests: Add fuzzing harness for TorController by practicalswift)
- #19043 (torcontrol: add -tortarget config by MDrollette)
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
-
Saibato commented at 12:25 AM on July 11, 2020: contributor
To add some fish here this POC tor v3 patch is in line with the current piggy pack of v2 onions in ipv6 <details><summary>Click here, to see the full diff of the POC ADDRv1 compatible tor v3 support </summary>
diff --git a/src/addrman.h b/src/addrman.h index 8e82020df..4a810e53f 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -61,6 +61,7 @@ public: SERIALIZE_METHODS(CAddrInfo, obj) { READWRITEAS(CAddress, obj); + READWRITEAS(CNetAddr, obj); READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts); } diff --git a/src/net.cpp b/src/net.cpp index 244b0094d..36af03d33 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -156,6 +156,7 @@ static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn struct in6_addr ip; memcpy(&ip, seed_in.addr, sizeof(ip)); CAddress addr(CService(ip, seed_in.port), GetDesirableServiceFlags(NODE_NONE)); + LogPrintf("seeds %s\n", CNetAddr(addr).ToString()); addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek; vSeedsOut.push_back(addr); } @@ -368,6 +369,9 @@ static CAddress GetBindAddress(SOCKET sock) return addr_bind; } +static CAddress getadrr(std::string name) { + return CAddress(CService(name,18444), NODE_NONE); +} CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, bool manual_connection, bool block_relay_only) { if (pszDest == nullptr) { @@ -384,16 +388,23 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo } /// debug print - LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n", - pszDest ? pszDest : addrConnect.ToString(), + LogPrint(BCLog::NET, "trying connection %s unresolved address %s lastseen=%.1fhrs\n", + pszDest ? pszDest:"", addrConnect.ToString(), pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0); + std::string strName = std::string( pszDest ? pszDest:""); // Resolve const int default_port = Params().GetDefaultPort(); if (pszDest) { std::vector<CService> resolved; if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) { + + // dont resolv local the onions + if (!strName.find(".onion")) { + addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE); + + if (!addrConnect.IsValid()) { LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest); return nullptr; @@ -410,6 +421,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo LogPrintf("Failed to open new connection, already connected\n"); return nullptr; } + } } } @@ -417,7 +429,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo bool connected = false; SOCKET hSocket = INVALID_SOCKET; proxyType proxy; - if (addrConnect.IsValid()) { + if (addrConnect.IsValid() && addrConnect.IsTor() && !pszDest) { bool proxyConnectionFailed = false; if (GetProxy(addrConnect.GetNetwork(), proxy)) { @@ -425,14 +437,21 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo if (hSocket == INVALID_SOCKET) { return nullptr; } - connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, proxyConnectionFailed); + + if (addrConnect.ToStringIP() != "") { + connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, proxyConnectionFailed); + } else return nullptr; + } else { - // no proxy needed (none set for target network) + // no proxy needed (none set for tastrName.find(".onion")rget network) hSocket = CreateSocket(addrConnect); if (hSocket == INVALID_SOCKET) { return nullptr; } - connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout, manual_connection); + + if (addrConnect.ToString() != "") { + connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout, manual_connection); + } else return nullptr; } if (!proxyConnectionFailed) { // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to @@ -444,14 +463,24 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo if (hSocket == INVALID_SOCKET) { return nullptr; } + std::string host; int port = default_port; SplitHostPort(std::string(pszDest), port, host); bool proxyConnectionFailed; - connected = ConnectThroughProxy(proxy, host, port, hSocket, nConnectTimeout, proxyConnectionFailed); + connected = false; + //proxyConnectionFailed = true; + + + if (strlen(pszDest) > 0) //strName.find(".onion")) + { + LogPrintf("Address to connect over proxz %s %d\n", host, port); + connected = ConnectThroughProxy(proxy, host, port, hSocket, nConnectTimeout, proxyConnectionFailed); + } else return nullptr; + } if (!connected) { - CloseSocket(hSocket); + if (hSocket) CloseSocket(hSocket); return nullptr; } @@ -1705,17 +1734,6 @@ void CConnman::ThreadDNSAddressSeed() LogPrintf("%d addresses found from DNS seeds\n", found); } - - - - - - - - - - - void CConnman::DumpAddresses() { int64_t nStart = GetTimeMillis(); @@ -2057,6 +2075,8 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai } } else if (FindNode(std::string(pszDest))) return; + // will "":port ever work? + if(!pszDest && (addrConnect.ToStringIP() == "")) return; CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, manual_connection, block_relay_only); @@ -2756,6 +2776,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn // peers (to prevent adversaries from inferring these links from addr // traffic). m_addr_known{block_relay_only ? nullptr : MakeUnique<CRollingBloomFilter>(5000, 0.001)}, + id(idIn), nLocalHostNonce(nLocalHostNonceIn), nLocalServices(nLocalServicesIn), diff --git a/src/net_processing.cpp b/src/net_processing.cpp index bfc60b18f..ecd83188e 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2454,14 +2454,47 @@ void ProcessMessage( std::vector<CAddress> vAddrOk; int64_t nNow = GetAdjustedTime(); int64_t nSince = nNow - 10 * 60; + int i = 0; + size_t len = 10; + CAddress Tor = CAddress(vAddr[0]); + char rawaddr[256] = {}; + for (CAddress& addr : vAddr) { if (interruptMsgProc) return; + if (addr.IsTorSequence(i)) { + if (i == 0 ) { + // LogPrintf("Adrress addr V3 raw rec ="); + Tor = addr; + } + //V3sequence()) + addr.SetSpecial_v3(addr, 256); //fill hostdata from ip; + memcpy(&rawaddr[i*10], &addr.fqdn.c_str()[0], 10); + i++; + if (i != 8) { + continue; + } + } else addr.fqdn = {}; + + //LogPrintf("\nAdrress add raw? %s\n", &rawaddr[0]); + + if (i == 8) { + Tor.SetSpecial_v3(addr, 255); // set clasic tor flag + Tor.fqdn = rawaddr; + if ( i == 8 ) Tor.fqdn = rawaddr; + addr = Tor; + } + + if (addr.IsTor() && strlen(addr.fqdn.c_str()) < 32) addr.SetSpecial_v3(addr, 255); // v2 stzle + LogPrint(BCLog::NET, "Adrress add? %s\n", addr.ToString()); + + // We only bother storing full nodes, though this may include // things which we would not make an outbound connection to, in // part because we may make feeler connections to them. + if (!MayHaveUsefulAddressDB(addr.nServices) && !HasAllDesirableServiceFlags(addr.nServices)) continue; @@ -3901,12 +3934,25 @@ bool PeerLogicValidation::SendMessages(CNode* pto) std::vector<CAddress> vAddr; vAddr.reserve(pto->vAddrToSend.size()); assert(pto->m_addr_known); + CAddress addr_add; for (const CAddress& addr : pto->vAddrToSend) { if (!pto->m_addr_known->contains(addr.GetKey())) { pto->m_addr_known->insert(addr.GetKey()); - vAddr.push_back(addr); + if (!addr.IsTor()) vAddr.push_back(addr); + if (addr.IsTor()) LogPrint(BCLog::NET, "Try to send onion address = %s\n", addr.fqdn); + + if (addr.IsTor() && strlen(addr.fqdn.c_str()) > 32) { + for (int i=0;i<8;i++) { + addr_add = addr; + addr_add.SetSpecial_v3(addr, (i)*10); + + vAddr.push_back(addr_add); + + } + } else vAddr.push_back(addr); //v2 tor + // receiver rejects addr messages larger than 1000 if (vAddr.size() >= 1000) { diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 674439161..8c8bad0f8 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -5,13 +5,17 @@ #include <cstdint> #include <netaddress.h> +#include <netbase.h> + #include <hash.h> #include <util/strencodings.h> #include <util/asmap.h> #include <tinyformat.h> +#include <util/system.h> 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}; +static const unsigned char pchOnionSeq[] = {0xFD,'l','o','r','3',0x00}; // 0xFD + sha256("bitcoin")[0:5] static const unsigned char g_internal_prefix[] = { 0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 }; @@ -47,6 +51,11 @@ void CNetAddr::SetRaw(Network network, const uint8_t *ip_in) } } +void CNetAddr::SetRawByte(char p , int pos) +{ + ip[6+pos] = p; +} + /** * Try to make this a dummy address that maps the specified name into IPv6 like * so: (0xFD + %sha256("bitcoin")[0:5]) + %sha256(name)[0:10]. Such dummy @@ -70,6 +79,7 @@ bool CNetAddr::SetInternal(const std::string &name) 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)); + fqdn = name; return true; } @@ -83,20 +93,51 @@ bool CNetAddr::SetInternal(const std::string &name) * * [@see](/bitcoin-bitcoin/contributor/see/) CNetAddr::IsTor(), CNetAddr::IsRFC4193() */ -bool CNetAddr::SetSpecial(const std::string &strName) +bool CNetAddr::SetSpecial(const std::string &strName, int flag) { if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { - std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str()); - if (vchAddr.size() != 16-sizeof(pchOnionCat)) + std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(flag*10, strName.size() - 6).c_str()); + if (vchAddr.size() != 16-sizeof(pchOnionCat) && vchAddr.size() != 35) return false; memcpy(ip, pchOnionCat, sizeof(pchOnionCat)); for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++) ip[i + sizeof(pchOnionCat)] = vchAddr[i]; + fqdn = strName; + LogPrint(BCLog::NET, "setspecail called with %s %d\n", strName, flag); return true; } return false; } +bool CNetAddr::SetSpecial_v3(CNetAddr ref , int flag) +{ + //fqdn.resize(256); + std::string cp = ref.fqdn; + cp.resize(256); + if( flag < 254 ) { memcpy(ip, pchOnionSeq, sizeof(pchOnionSeq)); + for (unsigned int i=0; i<16-sizeof(pchOnionSeq); i++) { + ip[i + sizeof(pchOnionSeq)] = cp.c_str()[flag+i]; + } + fqdn = cp.substr(flag,10); + } + if (flag == 255) { // backward comp + std::string name = EncodeBase32(&ip[6], 10) + ".onion"; + fqdn = name; + } + if (flag == 256) { + for (unsigned int i=0; i<16-sizeof(pchOnionSeq); i++) { + fqdn[i] = char(ip[i + sizeof(pchOnionSeq)]); + } + } + return true; +} + +CNetAddr::CNetAddr(const std::string &strName) +{ + SetSpecial(strName); + LogPrint(BCLog::NET, "CNetAddr internal setspecail called from addr by name\n"); +} + CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) { SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr); @@ -224,7 +265,15 @@ bool CNetAddr::IsHeNet() const */ bool CNetAddr::IsTor() const { - return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0); + return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0) || IsTorSequence(0x0); +} + +/** + * [@see](/bitcoin-bitcoin/contributor/see/) CNetAddr::SetSpecial(const std::string &) + */ +bool CNetAddr::IsTorSequence(char seq) const +{ + return memcmp(ip, pchOnionSeq, sizeof(pchOnionSeq)) == 0; } bool CNetAddr::IsLocal() const @@ -333,8 +382,9 @@ enum Network CNetAddr::GetNetwork() const std::string CNetAddr::ToStringIP() const { - if (IsTor()) - return EncodeBase32(&ip[6], 10) + ".onion"; + if (IsTor()) { + return fqdn; + } if (IsInternal()) return EncodeBase32(ip + sizeof(g_internal_prefix), sizeof(ip) - sizeof(g_internal_prefix)) + ".internal"; CService serv(*this, 0); @@ -640,6 +690,10 @@ CService::CService(const struct in6_addr& ipv6Addr, uint16_t portIn) : CNetAddr( { } +CService::CService(const std::string fqdn, uint16_t portIn) : CNetAddr(fqdn), port(portIn) +{ +} + CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port)) { assert(addr.sin_family == AF_INET); diff --git a/src/netaddress.h b/src/netaddress.h index c20101215..e18cc31a1 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -38,16 +38,18 @@ class CNetAddr CNetAddr(); explicit CNetAddr(const struct in_addr& ipv4Addr); void SetIP(const CNetAddr& ip); + std::string fqdn = {}; /** * Set raw IPv4 or IPv6 address (in network byte order) - * [@note](/bitcoin-bitcoin/contributor/note/) Only NET_IPV4 and NET_IPV6 are allowed for network. + * [@note](/bitcoin-bitcoin/contributor/note/) void SetRawBytes(const uint8_t *ip_in);Only NET_IPV4 and NET_IPV6 are allowed for network. */ void SetRaw(Network network, const uint8_t *data); - + void SetRawByte(char b, int pos); bool SetInternal(const std::string& name); - bool SetSpecial(const std::string &strName); // for Tor addresses + bool SetSpecial_v3(CNetAddr ref , int flag); // for Tor addresses + bool SetSpecial(const std::string &strName, int flag = 0); bool IsBindAny() const; // INADDR_ANY equivalent 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) @@ -67,6 +69,7 @@ class CNetAddr bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765) bool IsHeNet() const; // IPv6 Hurricane Electric - https://he.net (2001:0470::/36) bool IsTor() const; + bool IsTorSequence(char pseq) const; bool IsLocal() const; bool IsRoutable() const; bool IsInternal() const; @@ -94,13 +97,14 @@ class CNetAddr int GetReachabilityFrom(const CNetAddr *paddrPartner = nullptr) const; explicit CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0); + CNetAddr(const std::string &strName); bool GetIn6Addr(struct in6_addr* pipv6Addr) const; friend bool operator==(const CNetAddr& a, const CNetAddr& b); friend bool operator!=(const CNetAddr& a, const CNetAddr& b) { return !(a == b); } friend bool operator<(const CNetAddr& a, const CNetAddr& b); - SERIALIZE_METHODS(CNetAddr, obj) { READWRITE(obj.ip); } + SERIALIZE_METHODS(CNetAddr, obj) { READWRITE(obj.ip, obj.fqdn); } friend class CSubNet; }; @@ -144,7 +148,8 @@ class CService : public CNetAddr public: CService(); CService(const CNetAddr& ip, uint16_t port); - CService(const struct in_addr& ipv4Addr, uint16_t port); + CService(const struct in_addr& ipv4Addr, uint16_t port);; + CService(const std::string, uint16_t port); explicit CService(const struct sockaddr_in& addr); uint16_t GetPort() const; bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const; diff --git a/src/netbase.cpp b/src/netbase.cpp index 3a3b5f3e6..816d66228 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -4,6 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <netbase.h> +#include <net.h> #include <sync.h> #include <tinyformat.h> @@ -69,17 +70,18 @@ bool static LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, un return false; } - { - CNetAddr addr; - // From our perspective, onion addresses are not hostnames but rather - // direct encodings of CNetAddr much like IPv4 dotted-decimal notation - // or IPv6 colon-separated hextet notation. Since we can't use - // getaddrinfo to decode them and it wouldn't make sense to resolve - // them, we return a network address representing it instead. See - // CNetAddr::SetSpecial(const std::string&) for more details. - if (addr.SetSpecial(name)) { + CNetAddr addr; + // From our perspective, onion addresses are not hostnames but rather + // direct encodings of CNetAddr much like IPv4 dotted-decimal notation + // or IPv6 colon-separated hextet notation. Since we can't use + // getaddrinfo to decode them and it wouldn't make sense to resolve + // them, we return a network address representing it instead. See + // CNetAddr::SetSpecial(const std::string&) for more details. + + if (name.find(".onion")) { + if (addr.SetSpecial(name,0)) { vIP.push_back(addr); - return true; + return false; } } @@ -97,12 +99,19 @@ bool static LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, un // If we don't allow lookups, then use the AI_NUMERICHOST flag for // getaddrinfo to only decode numerical network addresses and suppress // hostname lookups. - aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST; + aiHint.ai_flags = fAllowLookup && !HaveNameProxy() ? AI_ADDRCONFIG : AI_NUMERICHOST; struct addrinfo *aiRes = nullptr; int nErr = getaddrinfo(name.c_str(), nullptr, &aiHint, &aiRes); - if (nErr) - return false; + LogPrintf("Resolver :%s error = %d local resolve allowed %s %s\n", name.c_str() ,nErr,fAllowLookup, nErr?"fail":"local resolved"); + if (nErr ) { + CNetAddr resolved; + resolved.SetInternal(name); + if (resolved.IsInternal()) { + vIP.push_back(resolved); + } + return false; + } // Traverse the linked list starting with aiTrav, add all non-internal // IPv4,v6 addresses to vIP while respecting nMaxSolutions. struct addrinfo *aiTrav = aiRes; @@ -182,7 +191,7 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup) addr = vIP.front(); return true; } - +; /** * Resolve a service string to its corresponding service. * @@ -214,8 +223,17 @@ bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefau std::vector<CNetAddr> vIP; bool fRet = LookupIntern(hostname, vIP, nMaxSolutions, fAllowLookup); - if (!fRet) - return false; + if (vIP[0].IsTor()) { + vAddr.resize(hostname.size()); + vAddr[0] = CService(hostname, port); + return true; + } + if (!fRet) // mayby just a name and only onion we do not resovel so use tor + { + vAddr.resize(hostname.size()); + vAddr[0] = CService(hostname, port); + return true; + } vAddr.resize(vIP.size()); for (unsigned int i = 0; i < vIP.size(); i++) vAddr[i] = CService(vIP[i], port);</details> does the QD job of tunnel v3 onion in ipv6 standard bitcoin ADDR format packets as we do with v2. This is a working Proof Of Concept . And can sure be optimized in many ways, And used on top of this PR to easy test on the fly v3 tor onions.
i.e On a cruft with a running open tor browser you can generate v3 onions on the fly. Use ` bitcoin-qt -proxy=127.0.0.1:9150 -torcontrol=127.0.0.1:9151 -listen -onion=127.0.0.1:9150
Btw the tor browser like Orbot sits at 9150/9151 not 9050/9051 Note, if the bugfix #19358 gets merged bitcoin-qt -proxy=127.0.0.1:9150 -torcontrol=127.0.0.1:9151 -listen is sufficient and more intuitive. since you want to do a proxy onion outbound and hidden inbound edit: with adding -onlynet=onion -dns=0 and -dnsseed=0 your onion v3 test will stay in tor and not touch the tor ipv4 exitnodes to ping hello to the seeders.
- Saibato force-pushed on Jul 12, 2020
- Saibato renamed this:
torcontrol: Add V3 ED25519-V3 onions.
torcontrol: Create also a V3 ed25519-V3 onion address.
on Jul 13, 2020 -
laanwj commented at 12:12 PM on July 15, 2020: member
Concept ACK. I thought about advertising both kinds of addresses for a bit and I think it does make sense. Tor that is unable to connect to v3 addresses is sufficiently old that running it is a security risk in itself, so that's not a valid reason to keep suporting v2 addresses, However with regard to advertising on the bitcoin P2P network it makes sense during the transition period to
addrv2, becuase older node versions won't be able to receive (and thus use) the new Tor addresses.At some point in the future when everyone supports bitcoin addrv2 mesages, we could stop creating and advertising a Tor v2 address.
-
jonatack commented at 4:30 AM on July 20, 2020: member
Concept ACK. Would you mind adding test coverage (and perhaps clang-format the changes)?
- Saibato force-pushed on Jul 23, 2020
-
Saibato commented at 10:52 AM on July 23, 2020: contributor
fixup-update: clang-format source
- luke-jr changes_requested
-
luke-jr commented at 8:17 PM on July 29, 2020: member
I find this code hard to follow.
I think you should abstract the hidden service out of TorController, and have one for each of v2/v3.
- DrahtBot added the label Needs rebase on Jul 30, 2020
- Saibato force-pushed on Jul 30, 2020
- Saibato force-pushed on Jul 30, 2020
- DrahtBot removed the label Needs rebase on Jul 30, 2020
-
Rspigler commented at 5:21 PM on July 31, 2020: contributor
Tor is planning to deprecate v2 onion addresses by September 15th, no longer support by July 15th 2021 (0.4.6), and disable by October 15th 2021.
- Saibato force-pushed on Jul 31, 2020
-
Saibato commented at 6:55 PM on July 31, 2020: contributor
Tor is planning to deprecate v2 onion addresses by September 15th, no longer support by July @Rspigler yes we have some work here, the plan was to have from now on v3 and v2 in parallel and by that allow easy testing the transition. And then fade out v2 by change v3 to default. And then way later refactor.
- DrahtBot added the label Needs rebase on Aug 9, 2020
-
cb8f28a8f8
torcontrol: Create also a v3 ed25519-V3 service address.
If the Tor version supports this, from now on we also create also ED25519-V3 in torcontrol.
- Saibato force-pushed on Aug 15, 2020
-
Saibato commented at 12:38 PM on August 15, 2020: contributor
- DrahtBot removed the label Needs rebase on Aug 15, 2020
- laanwj closed this on Sep 30, 2020
-
Saibato commented at 11:00 AM on October 1, 2020: contributor
I'm closing this in favor of #19954, which seems to include the same behvavior.
It does not, when 19954 get merged as is, some old Tor only nodes will startup if updated without v2 and will not be reachable for some time inbound, before there new v3 is widely known AFAICS u and @Sjors where in favor of a dual stack i.e. with option to select for some time, but what is partly acked now is a plain v3 and has the potential as i was wary all the time to let old not updated nodes behind and unable to connect to there used known nodes and force thereby a kind of softfork, when we merge this as is and not provide the same functionality as before at least optional for some time.
Btw. At least i know now that mastodon Avatar is not a bot, ;-)
-
Sjors commented at 12:32 PM on October 1, 2020: member
I'm not opposed to dual stack. It might be worth discussing in a separate issue / PR. But it generally takes a while for people to upgrade their Bitcoin node, so I suspect there'll be plenty of v2 nodes left when that's shut down.
-
Saibato commented at 2:10 PM on October 1, 2020: contributor
I'm not opposed to dual stack. It might be worth discussing in a separate issue / PR
But, this PR here is a dual stack and provides Tor v2 and v3 in parallel and @vasild what is so complicated to just grab from here and do this from day one? So that i can close this here. I could live with this better if u could also add an option -useonlyv3service, that we then deprecate later to default, for those who know the dire implications, if they have a solely v3 node created on startup by the service call now, :woman_shrugging: @laanwj This whole thing might not be hanging that high, when we would not have the long awaited TAPROOT in the pipeline and then, in my view, we will have a lot of nodes that seek or hope for privacy might want to update fast.
So before -onlynet=onion is also respected outbound and seeders add also there v3 addresses to chainparsms.cpp instead of using outbound there FQDN over Tor exit nodes to bootstrap onion nodes, i will not consent.
I hoped since i addressed that and other Tor related problems now in multiple PR's that one of the core team silent picks this up and does the right thing, but if nothing happens over month that;s also a message.
If u ask users ( and also some core members ) if there onion bootstrap is in Tor, i guess most will say sure because seeding is just over DNS UDP and that is not possible over Tor, so they believe that, but in fact what Bitcoin does is making outbound plain ipv4 calls to the seeders real nodes over the exit nodes to bootstrap pure onion nodes. So a. some doxing here and b. how many honest exit nodes are out there, that give u correct ADDR/ADDVv2 response messages?
Not even talking here about v3 Edwards and what that means for onions created over the service api, AFAICS we have here some profound misconceptions how Tor has changed from v2 to v3 and is about to change. imho.
We have socks5 name services and not socks4 and so one could have had just add .onion or FQDN as long domain names and relay them in simple messages to other nodes they then can or can not over socks5 proxy's call the nodes outbound like any ip. btw that will be funny with i2p, good luck to create an "outbound" socks5 proxy relay for i2p ( maybe in java?) to even compare i2p with Tor is btw a joke imo.
To use only ip in ADDR messages in the original design, was to make sure there is no DNS like or address translation that can be tampered, since Satoshis probably knew that u can not stop the INTERNET (TCP/IP) but u can hijack DNS,Tor,i2p etc.?
The way the architecture seams to want to progress forward and is now in parts moved from the first design. is to treat other forms of transports also like IP addresses, but that is utterly wrong since those "addresses names" do not even exist without outbound/inbound proxy's or programs and "address name" to IP directory's, they are more like DNS names and can easy be hooked or hijacked and worse the ones that seek privacy might be the ones that easy end up on a premined alternative chain that verify;s "correctly" and reports there hooked balances correct on the screen and RPC but has nothing to do with the original chain.
BTW: In no way, when i do "not" comment on other PR's, that does mean approve or that i even have red a PR. Since i am independent of anyone on this planet, an ACK is an ACK and if there is no ACK do not assume there is and or that i had interest in silent review bcs an PR tangent my assumed interests and just forgot to ACK or comment. DYOR verify not trust ;-)
-
Saibato commented at 2:03 PM on January 10, 2021: contributor
Probably no one ever reads that, but I still can only urge to have a dual stack as long as possible and all issues in Tor V3 are fixed and proven mature stable. The effect on the consensus is a know issue but who knows what else is there not disclosed yet. Don't be reckless.
First 2021 full V3 Tor address outage. -
Rspigler commented at 10:35 PM on January 10, 2021: contributor
I agree that having
peers.datbackwards incompatible seems less of a conservative approach than is usually taken. A dual stack (advertising both addresses) seems supported by @laanwj (https://github.com/bitcoin/bitcoin/pull/19485#issuecomment-658731686) as well. -
vasild commented at 10:32 AM on January 11, 2021: member
With current
master, one can have his node behind the old, Tor v2 address by:- Configure the onion service in
torrcand run bitcoind with-listenonion=0 -bind=127.0.0.1:8334=onion,torrc:
HiddenServiceDir /var/db/tor/bitcoind-torv2/ HiddenServiceVersion 2 HiddenServicePort 8333 127.0.0.1:8334or
- Copy the old (v2)
onion_private_keyoveronion_v3_private_key
- Configure the onion service in
-
jonatack commented at 12:58 PM on January 11, 2021: member
FWIW, the 0.21 release notes draft is at https://github.com/bitcoin-core/bitcoin-devwiki/wiki/0.21.0-Release-Notes-Draft and currently states:
"The Tor onion service that is automatically created by setting the -listenonion configuration parameter will now be created as a Tor v3 service instead of Tor v2. The private key that was used for Tor v2 (if any) will be left untouched in the onion_private_key file in the data directory (see -datadir) and can be removed if not needed. Bitcoin Core will no longer attempt to read it. The private key for the Tor v3 service will be saved in a file named onion_v3_private_key. To use the deprecated Tor v2 service (not recommended), the onion_private_key can be copied over onion_v3_private_key, e.g. cp -f onion_private_key onion_v3_private_key. (#19954)"
The wiki is publicly editable if anyone feels it could be more clear or complete.
-
Saibato commented at 2:48 PM on January 11, 2021: contributor
With current master, one can have his node behind the old, Tor v2 address by:
sure, most experienced user will have Tor anyway defined pure in torrc.and use multiple externalip= and addnode in conf and not expose the Tor service api anyway.
But if the mantra is that average Joe must not get screwed and not run into i..e. eclipse like things, we should keep v2 also in torcontrol as long as possible, 64 bit brute is cheap in reach and v2 address have also other problems but at least they work for ppl / nodes who just need to tunnel easy behind NAT's and serve from there i.e. phones and termuxe's or VM's and do not care much about privacy. They often use things out of the box with standard settings.
btw for instance in c-LNs Tor implementation we have an option to let at least the user decide what kind of auto onion he wants to have and we can use v3 whiteout clamping the key that generates the address by user defined blobs.or derive them from the node key and also on softreboots we can easy create new addresses while keeping the old ones what is anyway a good idea for v3 until it is mature
-
sipa commented at 9:15 PM on January 11, 2021: member
I don't think there is anything to do here. By the time current master is released, TorV2 will be dead and gone.
-
Saibato commented at 9:48 AM on January 12, 2021: contributor
I don't think there is anything to do here. By the time current master is released, TorV2 will be dead and gone.
I know they say i am hard to understand and often vage.but let me repharse with no intend of if a than b I don't and will not.
But, if u don;t Ithink there is anything to do here. By the time v0.21.0 is released, TorV3 will be dead and gone.
-
sipa commented at 3:32 PM on January 12, 2021: member
Current master will become 22.0. 0.21.0 will be out imminently.
-
Saibato commented at 5:02 PM on January 12, 2021: contributor
0.21.0 will be out imminently.
rc6 anyway...?
btw we should skip 22 and 23 to obvious or misleading how about 24,0?
- deadalnix referenced this in commit 4adf771f68 on Feb 9, 2021
- DrahtBot locked this on Aug 16, 2022