Skip to content
Bitcoin Roots

v29.4-roots.3 · Commit 3: [PATCH 03/30] policy: restore conservative relay and network controls

src/netbase.cpp

Before: src/netbase.cpp · After: src/netbase.cpp

File metadata
index d3d54048272415bb349f73acb0db8b1a59d901d4..775e459cca189a47a90112e26c8d36ab93079110 100644

Download original patch · Release notes

Diff rows 1–110 of 110. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.

src/netbase.cpp CHANGED
@@ -103,7 +103,7 @@ enum Network ParseNetwork(const std::string& net_in) {
103
103
  if (net == "ipv6") return NET_IPV6;
104
104
  if (net == "onion") return NET_ONION;
105
105
  if (net == "tor") {
106
- LogPrintf("Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
106
+ LogWarning("Net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.");
107
107
  return NET_ONION;
108
108
  }
109
109
  if (net == "i2p") {
@@ -277,6 +277,14 @@ enum SOCKS5Reply: uint8_t {
277
277
  TTLEXPIRED = 0x06, //!< TTL expired
278
278
  CMDUNSUPPORTED = 0x07, //!< Command not supported
279
279
  ATYPEUNSUPPORTED = 0x08, //!< Address type not supported
280
+ TOR_HS_DESC_NOT_FOUND = 0xf0, //!< Tor: Onion service descriptor can not be found
281
+ TOR_HS_DESC_INVALID = 0xf1, //!< Tor: Onion service descriptor is invalid
282
+ TOR_HS_INTRO_FAILED = 0xf2, //!< Tor: Onion service introduction failed
283
+ TOR_HS_REND_FAILED = 0xf3, //!< Tor: Onion service rendezvous failed
284
+ TOR_HS_MISSING_CLIENT_AUTH = 0xf4, //!< Tor: Onion service missing client authorization
285
+ TOR_HS_WRONG_CLIENT_AUTH = 0xf5, //!< Tor: Onion service wrong client authorization
286
+ TOR_HS_BAD_ADDRESS = 0xf6, //!< Tor: Onion service invalid address
287
+ TOR_HS_INTRO_TIMEOUT = 0xf7, //!< Tor: Onion service introduction timed out
280
288
  };
281
289
 
282
290
  /** Values defined for ATYPE in RFC1928 */
@@ -364,8 +372,24 @@ static std::string Socks5ErrorString(uint8_t err)
364
372
  return "protocol error";
365
373
  case SOCKS5Reply::ATYPEUNSUPPORTED:
366
374
  return "address type not supported";
375
+ case SOCKS5Reply::TOR_HS_DESC_NOT_FOUND:
376
+ return "onion service descriptor can not be found";
377
+ case SOCKS5Reply::TOR_HS_DESC_INVALID:
378
+ return "onion service descriptor is invalid";
379
+ case SOCKS5Reply::TOR_HS_INTRO_FAILED:
380
+ return "onion service introduction failed";
381
+ case SOCKS5Reply::TOR_HS_REND_FAILED:
382
+ return "onion service rendezvous failed";
383
+ case SOCKS5Reply::TOR_HS_MISSING_CLIENT_AUTH:
384
+ return "onion service missing client authorization";
385
+ case SOCKS5Reply::TOR_HS_WRONG_CLIENT_AUTH:
386
+ return "onion service wrong client authorization";
387
+ case SOCKS5Reply::TOR_HS_BAD_ADDRESS:
388
+ return "onion service invalid address";
389
+ case SOCKS5Reply::TOR_HS_INTRO_TIMEOUT:
390
+ return "onion service introduction timed out";
367
391
  default:
368
- return "unknown";
392
+ return strprintf("unknown (0x%02x)", err);
369
393
  }
370
394
  }
371
395
 
@@ -411,8 +435,8 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
411
435
  vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
412
436
  vAuth.push_back(auth->password.size());
413
437
  vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
438
+ LogDebug(BCLog::PROXY, "SOCKS5 sending username/password authentication\n");
414
439
  sock.SendComplete(vAuth, g_socks5_recv_timeout, g_socks5_interrupt);
415
- LogDebug(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
416
440
  uint8_t pchRetA[2];
417
441
  if (InterruptibleRecv(pchRetA, 2, g_socks5_recv_timeout, sock) != IntrRecvError::OK) {
418
442
  LogError("Error reading proxy authentication response\n");
@@ -725,6 +749,43 @@ bool IsProxy(const CNetAddr &addr) {
725
749
  return false;
726
750
  }
727
751
 
752
+ /**
753
+ * Generate unique credentials for Tor stream isolation. Tor will create
754
+ * separate circuits for SOCKS5 proxy connections with different credentials, which
755
+ * makes it harder to correlate the connections.
756
+ */
757
+ class TorStreamIsolationCredentialsGenerator
758
+ {
759
+ public:
760
+ TorStreamIsolationCredentialsGenerator():
761
+ m_prefix(GenerateUniquePrefix()) {
762
+ }
763
+
764
+ /** Return the next unique proxy credentials. */
765
+ ProxyCredentials Generate() {
766
+ ProxyCredentials auth;
767
+ auth.username = auth.password = strprintf("%s%i", m_prefix, m_counter);
768
+ ++m_counter;
769
+ return auth;
770
+ }
771
+
772
+ /** Size of session prefix in bytes. */
773
+ static constexpr size_t PREFIX_BYTE_LENGTH = 8;
774
+ private:
775
+ const std::string m_prefix;
776
+ std::atomic<uint64_t> m_counter;
777
+
778
+ /** Generate a random prefix for each of the credentials returned by this generator.
779
+ * This makes sure that different launches of the application (either successively or in parallel)
780
+ * will not share the same circuits, as would be the case with a bare counter.
781
+ */
782
+ static std::string GenerateUniquePrefix() {
783
+ std::array<uint8_t, PREFIX_BYTE_LENGTH> prefix_bytes;
784
+ GetRandBytes(prefix_bytes);
785
+ return HexStr(prefix_bytes) + "-";
786
+ }
787
+ };
788
+
728
789
  std::unique_ptr<Sock> ConnectThroughProxy(const Proxy& proxy,
729
790
  const std::string& dest,
730
791
  uint16_t port,
@@ -739,9 +800,8 @@ std::unique_ptr<Sock> ConnectThroughProxy(const Proxy& proxy,
739
800
 
740
801
  // do socks negotiation
741
802
  if (proxy.m_randomize_credentials) {
742
- ProxyCredentials random_auth;
743
- static std::atomic_int counter(0);
744
- random_auth.username = random_auth.password = strprintf("%i", counter++);
803
+ static TorStreamIsolationCredentialsGenerator generator;
804
+ ProxyCredentials random_auth{generator.Generate()};
745
805
  if (!Socks5(dest, port, &random_auth, *sock)) {
746
806
  return {};
747
807
  }