diff options
| author | Bitflash <admin@bitflash.network> | 2026-08-12 10:22:23 -0300 |
|---|---|---|
| committer | Bitflash <admin@bitflash.network> | 2026-08-12 10:22:23 -0300 |
| commit | d0ebe648f333def99fababd65f6b929448616d56 (patch) | |
| tree | c7ccaa28b9f83abd077ba90c031632deda83c80a | |
| parent | c330b8e5e1c057049b5b361908c94f41344dff80 (diff) | |
| parent | a0a300c240c91fa0c1cd1dc60ff5420a89cc33f8 (diff) | |
Merge pull request 'net: add Tor mode for outbound discovery' (#28) from tor-mode into main
| -rw-r--r-- | README.md | 9 | ||||
| -rw-r--r-- | docs/tor.md | 84 | ||||
| -rw-r--r-- | src/main_gui.cpp | 30 | ||||
| -rw-r--r-- | src/proxy.cpp | 50 | ||||
| -rw-r--r-- | src/proxy.h | 3 | ||||
| -rw-r--r-- | src/readme.txt | 3 | ||||
| -rw-r--r-- | src/selftest.cpp | 25 |
7 files changed, 197 insertions, 7 deletions
| @@ -36,7 +36,8 @@ Worth being precise, because the difference matters if you are relying on it. | |||
| 36 | 36 | ||
| 37 | **The node still listens on 8433.** Nothing dials by IP any more, but the listener is still there, so anyone who already knows your address and can reach that port may connect directly. If that matters to you, firewall it. | 37 | **The node still listens on 8433.** Nothing dials by IP any more, but the listener is still there, so anyone who already knows your address and can reach that port may connect directly. If that matters to you, firewall it. |
| 38 | 38 | ||
| 39 | This is unlinkability between peers, not anonymity against a network observer. It is not Tor. | 39 | This is unlinkability between peers, not anonymity against a network observer. |
| 40 | For Tor routing, start the node with `-tor`; see [Tor mode](docs/tor.md). | ||
| 40 | 41 | ||
| 41 | --- | 42 | --- |
| 42 | 43 | ||
| @@ -319,6 +320,7 @@ Other options worth knowing: | |||
| 319 | -datadir=PATH # wallet and chain data elsewhere | 320 | -datadir=PATH # wallet and chain data elsewhere |
| 320 | -port=N # P2P listen port, default 8433 | 321 | -port=N # P2P listen port, default 8433 |
| 321 | -socks=HOST:PORT # SOCKS5 for outbound Nostr and .btf rendezvous dials | 322 | -socks=HOST:PORT # SOCKS5 for outbound Nostr and .btf rendezvous dials |
| 323 | -tor[=HOST:PORT] # Tor mode; default local Tor SOCKS5 proxy is 127.0.0.1:9050 | ||
| 322 | -debug # verbose log; without it debug.log is nearly silent | 324 | -debug # verbose log; without it debug.log is nearly silent |
| 323 | -help # full list | 325 | -help # full list |
| 324 | ``` | 326 | ``` |
| @@ -332,6 +334,11 @@ dials through a local SOCKS5 proxy such as Tor. When it is set, the node skips | |||
| 332 | plain HTTP external-IP probes instead of leaking a direct request outside the | 334 | plain HTTP external-IP probes instead of leaking a direct request outside the |
| 333 | proxy. IPv6 proxy endpoints use brackets, for example `-socks=[::1]:9050`. | 335 | proxy. IPv6 proxy endpoints use brackets, for example `-socks=[::1]:9050`. |
| 334 | 336 | ||
| 337 | `-tor` is a privacy shorthand for the usual local Tor SOCKS5 listener at | ||
| 338 | `127.0.0.1:9050`. It routes outbound Nostr discovery and `.btf` rendezvous | ||
| 339 | dials through Tor, refuses direct `.onion` resolution, and keeps external-IP | ||
| 340 | probes disabled. Use `-tor=HOST:PORT` when Tor listens somewhere else. | ||
| 341 | |||
| 335 | ### When something looks wrong | 342 | ### When something looks wrong |
| 336 | 343 | ||
| 337 | **Menu > Diagnostics**, and the same report in `debug.log` every ten minutes: | 344 | **Menu > Diagnostics**, and the same report in `debug.log` every ten minutes: |
diff --git a/docs/tor.md b/docs/tor.md new file mode 100644 index 0000000..087c822 --- /dev/null +++ b/docs/tor.md | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | # Tor mode | ||
| 2 | |||
| 3 | Bitflash can route outbound discovery traffic through a local Tor SOCKS5 proxy. | ||
| 4 | This is transport plumbing only: it does not change consensus, wallet keys, | ||
| 5 | mining, `.btf` addresses, or the encrypted rendezvous protocol. | ||
| 6 | |||
| 7 | ## Client mode | ||
| 8 | |||
| 9 | Start Tor locally, then start Bitflash with: | ||
| 10 | |||
| 11 | ```bash | ||
| 12 | bitflash -tor | ||
| 13 | ``` | ||
| 14 | |||
| 15 | `-tor` is shorthand for: | ||
| 16 | |||
| 17 | ```bash | ||
| 18 | bitflash -socks=127.0.0.1:9050 | ||
| 19 | ``` | ||
| 20 | |||
| 21 | If Tor listens somewhere else: | ||
| 22 | |||
| 23 | ```bash | ||
| 24 | bitflash -tor=127.0.0.1:9150 | ||
| 25 | bitflash -tor=[::1]:9050 | ||
| 26 | ``` | ||
| 27 | |||
| 28 | When Tor mode is enabled: | ||
| 29 | |||
| 30 | - outbound Nostr relay dials use Tor; | ||
| 31 | - outbound `.btf` rendezvous relay dials use Tor; | ||
| 32 | - destination names are sent to Tor as SOCKS5 domain-name CONNECT requests, so | ||
| 33 | the local DNS resolver does not see them; | ||
| 34 | - direct `.onion` dials are refused unless a SOCKS5/Tor proxy is enabled; | ||
| 35 | - plain HTTP external-IP probes are skipped. | ||
| 36 | |||
| 37 | ## Onion rendezvous relay | ||
| 38 | |||
| 39 | An operator can expose a Bitflash rendezvous relay as a Tor hidden service. The | ||
| 40 | node does not create hidden services itself; Tor owns that configuration. | ||
| 41 | |||
| 42 | Example `torrc`: | ||
| 43 | |||
| 44 | ```text | ||
| 45 | HiddenServiceDir /var/lib/tor/bitflash-rendezvous/ | ||
| 46 | HiddenServicePort 8434 127.0.0.1:8434 | ||
| 47 | ``` | ||
| 48 | |||
| 49 | After restarting Tor, read the generated onion name: | ||
| 50 | |||
| 51 | ```bash | ||
| 52 | sudo cat /var/lib/tor/bitflash-rendezvous/hostname | ||
| 53 | ``` | ||
| 54 | |||
| 55 | Then run the relay on localhost/VPS as usual and announce the onion endpoint from | ||
| 56 | nodes that use Tor: | ||
| 57 | |||
| 58 | ```bash | ||
| 59 | bitflash -tor -rvrelay=exampleexampleexampleexampleexampleexampleexampleexample.onion:8434 | ||
| 60 | bitflash -tor -announcerelay=exampleexampleexampleexampleexampleexampleexampleexample.onion:8434 | ||
| 61 | ``` | ||
| 62 | |||
| 63 | For a pool operator that wants the pool descriptor to point at an onion | ||
| 64 | rendezvous relay, use both: | ||
| 65 | |||
| 66 | ```bash | ||
| 67 | bitflash -operator -tor \ | ||
| 68 | -rvrelay=exampleexampleexampleexampleexampleexampleexampleexample.onion:8434 \ | ||
| 69 | -announcerelay=exampleexampleexampleexampleexampleexampleexampleexample.onion:8434 | ||
| 70 | ``` | ||
| 71 | |||
| 72 | ## Full-node hidden service | ||
| 73 | |||
| 74 | The legacy P2P listener still binds to port `8433`. You can expose it through | ||
| 75 | Tor manually: | ||
| 76 | |||
| 77 | ```text | ||
| 78 | HiddenServiceDir /var/lib/tor/bitflash-node/ | ||
| 79 | HiddenServicePort 8433 127.0.0.1:8433 | ||
| 80 | ``` | ||
| 81 | |||
| 82 | Current automatic peer discovery is `.btf`/rendezvous based, not onion-address | ||
| 83 | gossip. Treat direct full-node onion access as an operator/admin tool unless a | ||
| 84 | future release adds first-class onion peer advertisements. | ||
diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 90a6050..bef8503 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp | |||
| @@ -138,6 +138,7 @@ static void PrintUsage() | |||
| 138 | printf("Network:\n"); | 138 | printf("Network:\n"); |
| 139 | printf(" /port=N (P2P listen port, default 8433)\n"); | 139 | printf(" /port=N (P2P listen port, default 8433)\n"); |
| 140 | printf(" /socks=HOST:PORT (SOCKS5 proxy for outbound Nostr and .btf relay dials)\n"); | 140 | printf(" /socks=HOST:PORT (SOCKS5 proxy for outbound Nostr and .btf relay dials)\n"); |
| 141 | printf(" /tor[=HOST:PORT] (Tor mode; default SOCKS5 proxy is 127.0.0.1:9050)\n"); | ||
| 141 | printf(" /btfseed=ADDRESS:ENCHEX (extra bootstrap peer, repeatable)\n"); | 142 | printf(" /btfseed=ADDRESS:ENCHEX (extra bootstrap peer, repeatable)\n"); |
| 142 | printf("\n"); | 143 | printf("\n"); |
| 143 | printf("Wallet:\n"); | 144 | printf("Wallet:\n"); |
| @@ -285,16 +286,35 @@ static void ParseStartupArguments(int argc, char* argv[]) | |||
| 285 | if (!announceRelay.empty()) | 286 | if (!announceRelay.empty()) |
| 286 | strBtfAnnounceRelay = announceRelay; | 287 | strBtfAnnounceRelay = announceRelay; |
| 287 | 288 | ||
| 288 | string socksProxy = argval2(argc, argv, "/socks", "-socks"); | 289 | bool fTorMode = arg(argc, argv, "/tor") || arg(argc, argv, "-tor"); |
| 289 | if (!socksProxy.empty()) | 290 | if (fTorMode) |
| 290 | { | 291 | { |
| 292 | string socksProxy = argval2(argc, argv, "/socks", "-socks"); | ||
| 293 | if (!socksProxy.empty()) | ||
| 294 | fprintf(stderr, "Warning: /tor takes precedence over /socks=%s\n", | ||
| 295 | socksProxy.c_str()); | ||
| 296 | |||
| 297 | string torProxy = argval2(argc, argv, "/tor", "-tor"); | ||
| 291 | string err; | 298 | string err; |
| 292 | if (!BtfSetSocks5Proxy(socksProxy, err)) | 299 | if (!BtfEnableTorProxy(torProxy, err)) |
| 293 | fprintf(stderr, "Ignoring /socks=%s: %s\n", socksProxy.c_str(), err.c_str()); | 300 | fprintf(stderr, "Ignoring /tor=%s: %s\n", torProxy.c_str(), err.c_str()); |
| 294 | else | 301 | else |
| 295 | fprintf(stderr, "SOCKS5 proxy enabled for outbound discovery/relay dials: %s\n", | 302 | fprintf(stderr, "Tor mode enabled through SOCKS5 proxy %s\n", |
| 296 | BtfSocks5ProxyName().c_str()); | 303 | BtfSocks5ProxyName().c_str()); |
| 297 | } | 304 | } |
| 305 | else | ||
| 306 | { | ||
| 307 | string socksProxy = argval2(argc, argv, "/socks", "-socks"); | ||
| 308 | if (!socksProxy.empty()) | ||
| 309 | { | ||
| 310 | string err; | ||
| 311 | if (!BtfSetSocks5Proxy(socksProxy, err)) | ||
| 312 | fprintf(stderr, "Ignoring /socks=%s: %s\n", socksProxy.c_str(), err.c_str()); | ||
| 313 | else | ||
| 314 | fprintf(stderr, "SOCKS5 proxy enabled for outbound discovery/relay dials: %s\n", | ||
| 315 | BtfSocks5ProxyName().c_str()); | ||
| 316 | } | ||
| 317 | } | ||
| 298 | 318 | ||
| 299 | // /btfseed=ADDRESS:ENCHEX -- extra bootstrap peers, repeatable. Useful for | 319 | // /btfseed=ADDRESS:ENCHEX -- extra bootstrap peers, repeatable. Useful for |
| 300 | // testing the seed path and for private networks that ship no compiled list. | 320 | // testing the seed path and for private networks that ship no compiled list. |
diff --git a/src/proxy.cpp b/src/proxy.cpp index d7dc324..7d30911 100644 --- a/src/proxy.cpp +++ b/src/proxy.cpp | |||
| @@ -9,8 +9,10 @@ | |||
| 9 | 9 | ||
| 10 | static CCriticalSection cs_socks5; | 10 | static CCriticalSection cs_socks5; |
| 11 | static bool g_fSocks5Proxy = false; | 11 | static bool g_fSocks5Proxy = false; |
| 12 | static bool g_fTorProxy = false; | ||
| 12 | static std::string g_socks5Host; | 13 | static std::string g_socks5Host; |
| 13 | static unsigned short g_socks5Port = 0; | 14 | static unsigned short g_socks5Port = 0; |
| 15 | static const char* DEFAULT_TOR_SOCKS5_PROXY = "127.0.0.1:9050"; | ||
| 14 | 16 | ||
| 15 | static void SetSocketTimeout(SOCKET s, int nTimeoutSecs) | 17 | static void SetSocketTimeout(SOCKET s, int nTimeoutSecs) |
| 16 | { | 18 | { |
| @@ -67,6 +69,24 @@ static bool ValidProxyIpv6HostChar(char c) | |||
| 67 | return isxdigit((unsigned char)c) || c == ':' || c == '.'; | 69 | return isxdigit((unsigned char)c) || c == ':' || c == '.'; |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 72 | static std::string LowerProxyHost(std::string host) | ||
| 73 | { | ||
| 74 | if (!host.empty() && host[host.size() - 1] == '.') | ||
| 75 | host.erase(host.size() - 1); | ||
| 76 | for (size_t i = 0; i < host.size(); i++) | ||
| 77 | host[i] = (char)tolower((unsigned char)host[i]); | ||
| 78 | return host; | ||
| 79 | } | ||
| 80 | |||
| 81 | bool BtfIsTorOnionHost(const std::string& host) | ||
| 82 | { | ||
| 83 | std::string lower = LowerProxyHost(host); | ||
| 84 | static const char* suffix = ".onion"; | ||
| 85 | size_t suffixLen = strlen(suffix); | ||
| 86 | return lower.size() > suffixLen && | ||
| 87 | lower.compare(lower.size() - suffixLen, suffixLen, suffix) == 0; | ||
| 88 | } | ||
| 89 | |||
| 70 | static bool ParsePort(const std::string& port, unsigned short& portOut, | 90 | static bool ParsePort(const std::string& port, unsigned short& portOut, |
| 71 | std::string& errOut) | 91 | std::string& errOut) |
| 72 | { | 92 | { |
| @@ -176,7 +196,8 @@ bool BtfParseSocks5Proxy(const std::string& spec, std::string& hostOut, | |||
| 176 | return true; | 196 | return true; |
| 177 | } | 197 | } |
| 178 | 198 | ||
| 179 | bool BtfSetSocks5Proxy(const std::string& spec, std::string& errOut) | 199 | static bool SetSocks5Proxy(const std::string& spec, bool fTorMode, |
| 200 | std::string& errOut) | ||
| 180 | { | 201 | { |
| 181 | std::string host; | 202 | std::string host; |
| 182 | unsigned short port = 0; | 203 | unsigned short port = 0; |
| @@ -187,15 +208,27 @@ bool BtfSetSocks5Proxy(const std::string& spec, std::string& errOut) | |||
| 187 | g_socks5Host = host; | 208 | g_socks5Host = host; |
| 188 | g_socks5Port = port; | 209 | g_socks5Port = port; |
| 189 | g_fSocks5Proxy = true; | 210 | g_fSocks5Proxy = true; |
| 211 | g_fTorProxy = fTorMode; | ||
| 190 | } | 212 | } |
| 191 | return true; | 213 | return true; |
| 192 | } | 214 | } |
| 193 | 215 | ||
| 216 | bool BtfSetSocks5Proxy(const std::string& spec, std::string& errOut) | ||
| 217 | { | ||
| 218 | return SetSocks5Proxy(spec, false, errOut); | ||
| 219 | } | ||
| 220 | |||
| 221 | bool BtfEnableTorProxy(const std::string& spec, std::string& errOut) | ||
| 222 | { | ||
| 223 | return SetSocks5Proxy(spec.empty() ? DEFAULT_TOR_SOCKS5_PROXY : spec, true, errOut); | ||
| 224 | } | ||
| 225 | |||
| 194 | void BtfClearSocks5Proxy() | 226 | void BtfClearSocks5Proxy() |
| 195 | { | 227 | { |
| 196 | CRITICAL_BLOCK(cs_socks5) | 228 | CRITICAL_BLOCK(cs_socks5) |
| 197 | { | 229 | { |
| 198 | g_fSocks5Proxy = false; | 230 | g_fSocks5Proxy = false; |
| 231 | g_fTorProxy = false; | ||
| 199 | g_socks5Host.clear(); | 232 | g_socks5Host.clear(); |
| 200 | g_socks5Port = 0; | 233 | g_socks5Port = 0; |
| 201 | } | 234 | } |
| @@ -208,6 +241,13 @@ bool BtfSocks5ProxyEnabled() | |||
| 208 | return false; | 241 | return false; |
| 209 | } | 242 | } |
| 210 | 243 | ||
| 244 | bool BtfTorProxyEnabled() | ||
| 245 | { | ||
| 246 | CRITICAL_BLOCK(cs_socks5) | ||
| 247 | return g_fSocks5Proxy && g_fTorProxy; | ||
| 248 | return false; | ||
| 249 | } | ||
| 250 | |||
| 211 | std::string BtfSocks5ProxyName() | 251 | std::string BtfSocks5ProxyName() |
| 212 | { | 252 | { |
| 213 | CRITICAL_BLOCK(cs_socks5) | 253 | CRITICAL_BLOCK(cs_socks5) |
| @@ -315,7 +355,15 @@ SOCKET BtfConnectSocket(const std::string& destHost, unsigned short destPort, | |||
| 315 | } | 355 | } |
| 316 | 356 | ||
| 317 | if (!fProxy) | 357 | if (!fProxy) |
| 358 | { | ||
| 359 | if (BtfIsTorOnionHost(destHost)) | ||
| 360 | { | ||
| 361 | error("Refusing direct .onion connection to %s:%u; use /tor or /socks\n", | ||
| 362 | destHost.c_str(), (unsigned)destPort); | ||
| 363 | return INVALID_SOCKET; | ||
| 364 | } | ||
| 318 | return ConnectDirect(destHost, destPort, nSockSite, nTimeoutSecs); | 365 | return ConnectDirect(destHost, destPort, nSockSite, nTimeoutSecs); |
| 366 | } | ||
| 319 | 367 | ||
| 320 | SOCKET s = ConnectDirect(proxyHost, proxyPort, nSockSite, nTimeoutSecs); | 368 | SOCKET s = ConnectDirect(proxyHost, proxyPort, nSockSite, nTimeoutSecs); |
| 321 | if (s == INVALID_SOCKET) | 369 | if (s == INVALID_SOCKET) |
diff --git a/src/proxy.h b/src/proxy.h index b5e69c8..6429cf2 100644 --- a/src/proxy.h +++ b/src/proxy.h | |||
| @@ -21,8 +21,11 @@ | |||
| 21 | bool BtfParseSocks5Proxy(const std::string& spec, std::string& hostOut, | 21 | bool BtfParseSocks5Proxy(const std::string& spec, std::string& hostOut, |
| 22 | unsigned short& portOut, std::string& errOut); | 22 | unsigned short& portOut, std::string& errOut); |
| 23 | bool BtfSetSocks5Proxy(const std::string& spec, std::string& errOut); | 23 | bool BtfSetSocks5Proxy(const std::string& spec, std::string& errOut); |
| 24 | bool BtfEnableTorProxy(const std::string& spec, std::string& errOut); | ||
| 24 | void BtfClearSocks5Proxy(); | 25 | void BtfClearSocks5Proxy(); |
| 25 | bool BtfSocks5ProxyEnabled(); | 26 | bool BtfSocks5ProxyEnabled(); |
| 27 | bool BtfTorProxyEnabled(); | ||
| 28 | bool BtfIsTorOnionHost(const std::string& host); | ||
| 26 | std::string BtfSocks5ProxyName(); | 29 | std::string BtfSocks5ProxyName(); |
| 27 | 30 | ||
| 28 | SOCKET BtfConnectSocket(const std::string& destHost, unsigned short destPort, | 31 | SOCKET BtfConnectSocket(const std::string& destHost, unsigned short destPort, |
diff --git a/src/readme.txt b/src/readme.txt index 1fa77df..794fe20 100644 --- a/src/readme.txt +++ b/src/readme.txt | |||
| @@ -46,6 +46,9 @@ Command-line options (in addition to the original ones) | |||
| 46 | route outbound Nostr and .btf rendezvous dials through a | 46 | route outbound Nostr and .btf rendezvous dials through a |
| 47 | SOCKS5 proxy, e.g. /socks=127.0.0.1:9050 for local Tor | 47 | SOCKS5 proxy, e.g. /socks=127.0.0.1:9050 for local Tor |
| 48 | or /socks=[::1]:9050 for an IPv6 loopback proxy | 48 | or /socks=[::1]:9050 for an IPv6 loopback proxy |
| 49 | /tor[=HOST:PORT] | ||
| 50 | Tor mode for outbound Nostr and .btf rendezvous dials; | ||
| 51 | defaults to the local Tor SOCKS5 proxy at 127.0.0.1:9050 | ||
| 49 | /solomine mine without requiring a connected peer (local testing) | 52 | /solomine mine without requiring a connected peer (local testing) |
| 50 | /operator operator mode (run pool server) | 53 | /operator operator mode (run pool server) |
| 51 | /participant=ADDR | 54 | /participant=ADDR |
diff --git a/src/selftest.cpp b/src/selftest.cpp index aa4e528..cca5335 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp | |||
| @@ -1474,6 +1474,11 @@ static int RunSocks5ProxySelfTest() | |||
| 1474 | "rejects overflowing port") ? 0 : 1; | 1474 | "rejects overflowing port") ? 0 : 1; |
| 1475 | nFail += Check(!BtfParseSocks5Proxy("user:pass@localhost:9050", host, port, err), | 1475 | nFail += Check(!BtfParseSocks5Proxy("user:pass@localhost:9050", host, port, err), |
| 1476 | "rejects unsupported authenticated proxy syntax") ? 0 : 1; | 1476 | "rejects unsupported authenticated proxy syntax") ? 0 : 1; |
| 1477 | nFail += Check(BtfIsTorOnionHost("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd.onion") && | ||
| 1478 | BtfIsTorOnionHost("Relay.Example.ONION.") && | ||
| 1479 | !BtfIsTorOnionHost("relay.example") && | ||
| 1480 | !BtfIsTorOnionHost(".onion"), | ||
| 1481 | "detects .onion hosts without accepting lookalikes") ? 0 : 1; | ||
| 1477 | 1482 | ||
| 1478 | BtfClearSocks5Proxy(); | 1483 | BtfClearSocks5Proxy(); |
| 1479 | nFail += Check(!BtfSocks5ProxyEnabled(), "starts disabled after clear") ? 0 : 1; | 1484 | nFail += Check(!BtfSocks5ProxyEnabled(), "starts disabled after clear") ? 0 : 1; |
| @@ -1490,6 +1495,26 @@ static int RunSocks5ProxySelfTest() | |||
| 1490 | "enables bracketed IPv6 proxy endpoint") ? 0 : 1; | 1495 | "enables bracketed IPv6 proxy endpoint") ? 0 : 1; |
| 1491 | BtfClearSocks5Proxy(); | 1496 | BtfClearSocks5Proxy(); |
| 1492 | 1497 | ||
| 1498 | nFail += Check(BtfEnableTorProxy("", err) && | ||
| 1499 | BtfSocks5ProxyEnabled() && | ||
| 1500 | BtfTorProxyEnabled() && | ||
| 1501 | BtfSocks5ProxyName() == "127.0.0.1:9050", | ||
| 1502 | "enables Tor mode on the default local SOCKS5 endpoint") ? 0 : 1; | ||
| 1503 | BtfClearSocks5Proxy(); | ||
| 1504 | |||
| 1505 | nFail += Check(BtfEnableTorProxy("[::1]:9050", err) && | ||
| 1506 | BtfSocks5ProxyEnabled() && | ||
| 1507 | BtfTorProxyEnabled() && | ||
| 1508 | BtfSocks5ProxyName() == "[::1]:9050", | ||
| 1509 | "enables Tor mode on a custom IPv6 endpoint") ? 0 : 1; | ||
| 1510 | BtfClearSocks5Proxy(); | ||
| 1511 | |||
| 1512 | nFail += Check(BtfSetSocks5Proxy("127.0.0.1:9051", err) && | ||
| 1513 | BtfSocks5ProxyEnabled() && | ||
| 1514 | !BtfTorProxyEnabled(), | ||
| 1515 | "plain SOCKS5 mode is distinct from Tor mode") ? 0 : 1; | ||
| 1516 | BtfClearSocks5Proxy(); | ||
| 1517 | |||
| 1493 | std::string handshakeErr; | 1518 | std::string handshakeErr; |
| 1494 | bool fHandshakeOk = RunSocks5HandshakeProbe(handshakeErr); | 1519 | bool fHandshakeOk = RunSocks5HandshakeProbe(handshakeErr); |
| 1495 | nFail += Check(fHandshakeOk, handshakeErr.empty() ? | 1520 | nFail += Check(fHandshakeOk, handshakeErr.empty() ? |