Added SOCKS5 proxy type command line parameter

- Auto-detect by default, based on the port number
- Don't run TOR-specific code if it's not the TOR proxy
This commit is contained in:
SChernykh
2026-02-10 21:15:30 +01:00
parent cf1c88b907
commit 6d6c12c1e8
13 changed files with 99 additions and 21 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ static constexpr int DEFAULT_BACKLOG = 1;
namespace p2pool {
ConsoleCommands::ConsoleCommands(p2pool* pool)
: TCPServer(DEFAULT_BACKLOG, ConsoleClient::allocate, std::string())
: TCPServer(DEFAULT_BACKLOG, ConsoleClient::allocate, std::string(), Params::ProxyType::INVALID)
, m_pool(pool)
, m_tty{}
, m_stdin_pipe{}
+1
View File
@@ -89,6 +89,7 @@ void p2pool_usage()
"--no-autodiff Disable automatic difficulty adjustment for miners connected to stratum (WARNING: incompatible with Nicehash and MRR)\n"
"--rpc-login Specify username[:password] required for Monero RPC server\n"
"--socks5 Specify IP:port of a SOCKS5 proxy to use for outgoing connections\n"
"--socks5-proxy-type The type of SOCKS5 proxy. Can be one of the following values: auto, plain, tor. Default is auto (auto-detect by the port number)\n"
"--no-dns Disable DNS queries, use only IP addresses to connect to peers (seed node DNS will be unavailable too)\n"
"--p2p-external-port Port number that your router uses for mapping to your local p2p port. Use it if you are behind a NAT and still want to accept incoming connections\n"
#ifdef WITH_UPNP
+3 -3
View File
@@ -42,7 +42,7 @@ MergeMiningClientTari::MergeMiningClientTari(p2pool* pool, std::string host, con
, m_auxWallet(wallet)
, m_pool(pool)
, m_tariJobParams{}
, m_server(new TariServer(pool->params().m_socks5Proxy))
, m_server(new TariServer(pool->params().m_socks5Proxy, pool->params().m_socks5ProxyType))
, m_hostStr(host)
, m_workerStop(0)
, m_pushBlockStop(0)
@@ -863,8 +863,8 @@ void MergeMiningClientTari::run()
// TariServer and TariClient are simply a proxy from a localhost TCP port to the external Tari node
// This is needed for SOCKS5 proxy support (gRPC library doesn't support it natively)
MergeMiningClientTari::TariServer::TariServer(const std::string& socks5Proxy)
: TCPServer(1, MergeMiningClientTari::TariClient::allocate, socks5Proxy)
MergeMiningClientTari::TariServer::TariServer(const std::string& socks5Proxy, Params::ProxyType socks5ProxyType)
: TCPServer(1, MergeMiningClientTari::TariClient::allocate, socks5Proxy, socks5ProxyType)
, m_TariNodeIsV6(false)
, m_TariNodeHost()
, m_TariNodePort(0)
+1 -1
View File
@@ -83,7 +83,7 @@ private:
struct TariServer : public TCPServer
{
explicit TariServer(const std::string& socks5Proxy);
TariServer(const std::string& socks5Proxy, Params::ProxyType socks5ProxyType);
~TariServer() {}
[[nodiscard]] bool start();
+23 -8
View File
@@ -64,7 +64,7 @@ static constexpr hash seed_onion_nodes[] = {
};
P2PServer::P2PServer(p2pool* pool)
: TCPServer(DEFAULT_BACKLOG, P2PClient::allocate, pool->params().m_socks5Proxy)
: TCPServer(DEFAULT_BACKLOG, P2PClient::allocate, pool->params().m_socks5Proxy, pool->params().m_socks5ProxyType)
, m_pool(pool)
, m_cache(pool->params().m_blockCache ? new BlockCache(pool->params()) : nullptr)
, m_cacheLoaded(false)
@@ -426,14 +426,16 @@ void P2PServer::update_peer_connections()
uint32_t num_outgoing = m_numConnections - m_numIncomingConnections;
// Try to have at least N/2 outgoing onion connections
if (!m_socks5Proxy.empty()) {
// Try to have at least N/2 (or N if clearnet P2P is disabled) outgoing onion connections
if (!m_socks5Proxy.empty() && (m_socks5ProxyType == Params::ProxyType::TOR)) {
std::vector<hash> pubkeys = m_pool->side_chain().seen_onion_pubkeys();
// Add seed nodes
pubkeys.insert(pubkeys.end(), seed_onion_nodes, seed_onion_nodes + array_size(seed_onion_nodes));
for (uint32_t i = m_numOnionConnections, n = N / 2; (i < n) && !pubkeys.empty();) {
const uint32_t n = m_pool->params().m_noClearnetP2P ? N : (N / 2);
for (uint32_t i = m_numOnionConnections; (i < n) && !pubkeys.empty();) {
const uint64_t k = get_random64() % pubkeys.size();
const std::string addr = to_onion_v3(pubkeys[k]);
@@ -727,8 +729,21 @@ void P2PServer::load_peer_list()
}
// Finally load peers from p2pool_peers.txt and p2pool_onion_peers.txt
for (size_t i = 0, n = (m_socks5Proxy.empty() ? 1 : 2); i < n; ++i) {
const std::string path = m_pool->params().m_dataDir + (i ? saved_onion_peer_list_file_name : saved_peer_list_file_name);
std::vector<std::string> paths;
paths.resize(Params::ProxyType::MAX);
paths[Params::ProxyType::PLAIN] = saved_peer_list_file_name;
if (!m_socks5Proxy.empty() && (m_socks5ProxyType == Params::ProxyType::TOR)) {
paths[Params::ProxyType::TOR] = saved_onion_peer_list_file_name;
}
for (int i = Params::ProxyType::PLAIN; i < Params::ProxyType::MAX; ++i) {
const std::string& path = paths[i];
if (path.empty()) {
continue;
}
std::ifstream f(path);
@@ -740,7 +755,7 @@ void P2PServer::load_peer_list()
std::getline(f, address);
if (!address.empty()) {
if (i > 0) {
if (i == Params::ProxyType::TOR) {
const hash h = from_onion_v3(address);
if (!h.empty()) {
pubkeys.emplace_back(h);
@@ -756,7 +771,7 @@ void P2PServer::load_peer_list()
}
f.close();
if (i > 0) {
if (i == Params::ProxyType::TOR) {
s.add_onion_pubkeys(pubkeys);
}
}
+40
View File
@@ -238,6 +238,18 @@ Params::Params(const std::vector<std::vector<std::string>>& args)
ok = true;
}
if ((arg[0] == "socks5-proxy-type") && has1(arg)) {
const std::string s = tolower(arg[1]);
m_socks5ProxyType = ProxyType::INVALID;
if (s == "auto") m_socks5ProxyType = ProxyType::AUTO;
if (s == "plain") m_socks5ProxyType = ProxyType::PLAIN;
if (s == "tor") m_socks5ProxyType = ProxyType::TOR;
ok = m_socks5ProxyType != ProxyType::INVALID;
}
if (arg[0] == "no-dns") {
m_dns = false;
disable_resolve_host = true;
@@ -426,6 +438,29 @@ Params::Params(const std::vector<std::vector<std::string>>& args)
else {
fixup_path(m_dataDir);
}
// Detect the proxy type
if (!m_socks5Proxy.empty() && (m_socks5ProxyType == ProxyType::AUTO)) {
m_socks5ProxyType = ProxyType::INVALID;
const size_t k = m_socks5Proxy.find_last_of(':');
if ((k != std::string::npos) && (k < m_socks5Proxy.length() - 1)) {
const uint32_t port = std::stoul(m_socks5Proxy.substr(k + 1), nullptr, 10);
if ((port > 0) && (port < 65536)) {
switch (port) {
case 9050:
m_socks5ProxyType = ProxyType::TOR;
break;
default:
m_socks5ProxyType = ProxyType::PLAIN;
break;
}
}
}
}
}
bool Params::valid() const
@@ -478,6 +513,11 @@ bool Params::valid() const
return false;
}
if (m_socks5ProxyType == ProxyType::INVALID) {
LOGERR(1, "Invalid SOCKS5 proxy type. Check the --socks5 parameter.");
return false;
}
return true;
}
+10
View File
@@ -108,7 +108,17 @@ struct Params
bool m_mini = false;
bool m_nano = false;
bool m_autoDiff = true;
std::string m_socks5Proxy;
enum ProxyType {
INVALID = -1,
AUTO = 0,
PLAIN = 1,
TOR = 2,
MAX = 3,
} m_socks5ProxyType = ProxyType::AUTO;
bool m_dns = true;
int32_t m_p2pExternalPort = 0;
#ifdef WITH_UPNP
+1 -1
View File
@@ -44,7 +44,7 @@ static constexpr int32_t BAN_THRESHOLD_POINTS = -15;
namespace p2pool {
StratumServer::StratumServer(p2pool* pool)
: TCPServer(DEFAULT_BACKLOG, StratumClient::allocate, std::string())
: TCPServer(DEFAULT_BACKLOG, StratumClient::allocate, std::string(), Params::ProxyType::INVALID)
, m_pool(pool)
, m_autoDiff(pool->params().m_autoDiff)
, m_enableFullValidation(pool->params().m_enableFullValidation)
+2 -1
View File
@@ -23,7 +23,7 @@ static thread_local const char* log_category_prefix = "TCPServer ";
namespace p2pool {
TCPServer::TCPServer(int default_backlog, allocate_client_callback allocate_new_client, const std::string& socks5Proxy)
TCPServer::TCPServer(int default_backlog, allocate_client_callback allocate_new_client, const std::string& socks5Proxy, Params::ProxyType socks5ProxyType)
: m_allocateNewClient(allocate_new_client)
, m_defaultBacklog(default_backlog)
, m_loopThread{}
@@ -32,6 +32,7 @@ TCPServer::TCPServer(int default_backlog, allocate_client_callback allocate_new_
, m_portMapping(0)
#endif
, m_socks5Proxy(socks5Proxy)
, m_socks5ProxyType(socks5ProxyType)
, m_socks5ProxyV6(false)
, m_socks5ProxyIP{}
, m_socks5ProxyPort(-1)
+3 -1
View File
@@ -18,6 +18,7 @@
#pragma once
#include "uv_util.h"
#include "params.h"
#ifdef WITH_TLS
#include "tls.h"
@@ -33,7 +34,7 @@ public:
struct Client;
typedef Client* (*allocate_client_callback)();
TCPServer(int default_backlog, allocate_client_callback allocate_new_client, const std::string& socks5Proxy);
TCPServer(int default_backlog, allocate_client_callback allocate_new_client, const std::string& socks5Proxy, Params::ProxyType socks5ProxyType);
virtual ~TCPServer();
[[nodiscard]] bool connect_to_peer(bool is_v6, const char* ip, int port);
@@ -191,6 +192,7 @@ protected:
#endif
std::string m_socks5Proxy;
Params::ProxyType m_socks5ProxyType;
bool m_socks5ProxyV6;
raw_ip m_socks5ProxyIP;
int m_socks5ProxyPort;
+1 -5
View File
@@ -1014,12 +1014,8 @@ hash from_onion_v3(const std::string& address)
return {};
}
// Convert address to lowercase
std::string s = address;
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
// Checksum validation
if (to_onion_v3(result) != s) {
if (to_onion_v3(result) != tolower(address)) {
LOGWARN(3, "Invalid onion address \"" << address << "\": checksum failed");
return {};
}
+12
View File
@@ -395,6 +395,18 @@ FORCEINLINE void secure_zero_memory(T& value)
secure_zero_memory(&value, sizeof(T));
}
FORCEINLINE std::string tolower(const std::string& s)
{
std::string result;
result.reserve(s.size() + 1);
for (char c : s) {
result.push_back(static_cast<char>(std::tolower(c)));
}
return result;
}
std::string to_onion_v3(const hash& pubkey);
hash from_onion_v3(const std::string& address);