mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
merge bitcoin#19991: Use alternative port for incoming Tor connections
This commit is contained in:
parent
95d462d01d
commit
c89cac5783
@ -53,11 +53,12 @@ config file): *Needed for Tor version 0.2.7.0 and older versions of Tor only. Fo
|
|||||||
versions of Tor see [Section 4](#4-automatically-listen-on-tor).*
|
versions of Tor see [Section 4](#4-automatically-listen-on-tor).*
|
||||||
|
|
||||||
HiddenServiceDir /var/lib/tor/dashcore-service/
|
HiddenServiceDir /var/lib/tor/dashcore-service/
|
||||||
HiddenServicePort 9999 127.0.0.1:9999
|
HiddenServicePort 9999 127.0.0.1:9996
|
||||||
HiddenServicePort 19999 127.0.0.1:19999
|
HiddenServicePort 19999 127.0.0.1:19996
|
||||||
|
|
||||||
The directory can be different of course, but (both) port numbers should be equal to
|
The directory can be different of course, but virtual port numbers should be equal to
|
||||||
your dashd's P2P listen port (9999 by default).
|
your dashd's P2P listen port (9999 by default), and target addresses and ports
|
||||||
|
should be equal to binding address and port for inbound Tor connections (127.0.0.1:9996 by default).
|
||||||
|
|
||||||
-externalip=X You can tell Dash Core about its publicly reachable address using
|
-externalip=X You can tell Dash Core about its publicly reachable address using
|
||||||
this option, and this can be a .onion address. Given the above
|
this option, and this can be a .onion address. Given the above
|
||||||
|
@ -49,16 +49,20 @@ const CBaseChainParams& BaseParams()
|
|||||||
return *globalChainBaseParams;
|
return *globalChainBaseParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Port numbers for incoming Tor connections (9996, 19996, 19796, 19896) have
|
||||||
|
* been chosen arbitrarily to keep ranges of used ports tight.
|
||||||
|
*/
|
||||||
std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
|
std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
|
||||||
{
|
{
|
||||||
if (chain == CBaseChainParams::MAIN)
|
if (chain == CBaseChainParams::MAIN)
|
||||||
return std::make_unique<CBaseChainParams>("", 9998);
|
return std::make_unique<CBaseChainParams>("", 9998, 9996);
|
||||||
else if (chain == CBaseChainParams::TESTNET)
|
else if (chain == CBaseChainParams::TESTNET)
|
||||||
return std::make_unique<CBaseChainParams>("testnet3", 19998);
|
return std::make_unique<CBaseChainParams>("testnet3", 19998, 19996);
|
||||||
else if (chain == CBaseChainParams::DEVNET)
|
else if (chain == CBaseChainParams::DEVNET)
|
||||||
return std::make_unique<CBaseChainParams>(gArgs.GetDevNetName(), 19798);
|
return std::make_unique<CBaseChainParams>(gArgs.GetDevNetName(), 19798, 19796);
|
||||||
else if (chain == CBaseChainParams::REGTEST)
|
else if (chain == CBaseChainParams::REGTEST)
|
||||||
return std::make_unique<CBaseChainParams>("regtest", 19898);
|
return std::make_unique<CBaseChainParams>("regtest", 19898, 19896);
|
||||||
else
|
else
|
||||||
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
|
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
|
||||||
}
|
}
|
||||||
|
@ -26,13 +26,16 @@ public:
|
|||||||
///@}
|
///@}
|
||||||
|
|
||||||
const std::string& DataDir() const { return strDataDir; }
|
const std::string& DataDir() const { return strDataDir; }
|
||||||
uint16_t RPCPort() const { return nRPCPort; }
|
uint16_t RPCPort() const { return m_rpc_port; }
|
||||||
|
uint16_t OnionServiceTargetPort() const { return m_onion_service_target_port; }
|
||||||
|
|
||||||
CBaseChainParams() = delete;
|
CBaseChainParams() = delete;
|
||||||
CBaseChainParams(const std::string& data_dir, int rpc_port) : nRPCPort(rpc_port), strDataDir(data_dir) {}
|
CBaseChainParams(const std::string& data_dir, uint16_t rpc_port, uint16_t onion_service_target_port)
|
||||||
|
: m_rpc_port(rpc_port), m_onion_service_target_port(onion_service_target_port), strDataDir(data_dir) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t nRPCPort;
|
const uint16_t m_rpc_port;
|
||||||
|
const uint16_t m_onion_service_target_port;
|
||||||
std::string strDataDir;
|
std::string strDataDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
40
src/init.cpp
40
src/init.cpp
@ -552,7 +552,7 @@ void SetupServerArgs(NodeContext& node)
|
|||||||
argsman.AddArg("-allowprivatenet", strprintf("Allow RFC1918 addresses to be relayed and connected to (default: %u)", DEFAULT_ALLOWPRIVATENET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-allowprivatenet", strprintf("Allow RFC1918 addresses to be relayed and connected to (default: %u)", DEFAULT_ALLOWPRIVATENET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting and discouraging misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting and discouraging misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||||
@ -2480,8 +2480,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogPrintf("::ChainActive().Height() = %d\n", chain_active_height);
|
LogPrintf("::ChainActive().Height() = %d\n", chain_active_height);
|
||||||
if (args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
|
|
||||||
StartTorControl();
|
|
||||||
|
|
||||||
Discover();
|
Discover();
|
||||||
|
|
||||||
@ -2506,13 +2504,39 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
|||||||
connOptions.nMaxOutboundLimit = 1024 * 1024 * args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET);
|
connOptions.nMaxOutboundLimit = 1024 * 1024 * args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET);
|
||||||
connOptions.m_peer_connect_timeout = peer_connect_timeout;
|
connOptions.m_peer_connect_timeout = peer_connect_timeout;
|
||||||
|
|
||||||
for (const std::string& strBind : args.GetArgs("-bind")) {
|
for (const std::string& bind_arg : args.GetArgs("-bind")) {
|
||||||
CService addrBind;
|
CService bind_addr;
|
||||||
if (!Lookup(strBind, addrBind, GetListenPort(), false)) {
|
const size_t index = bind_arg.rfind('=');
|
||||||
return InitError(ResolveErrMsg("bind", strBind));
|
if (index == std::string::npos) {
|
||||||
|
if (Lookup(bind_arg, bind_addr, GetListenPort(), false)) {
|
||||||
|
connOptions.vBinds.push_back(bind_addr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const std::string network_type = bind_arg.substr(index + 1);
|
||||||
|
if (network_type == "onion") {
|
||||||
|
const std::string truncated_bind_arg = bind_arg.substr(0, index);
|
||||||
|
if (Lookup(truncated_bind_arg, bind_addr, BaseParams().OnionServiceTargetPort(), false)) {
|
||||||
|
connOptions.onion_binds.push_back(bind_addr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
connOptions.vBinds.push_back(addrBind);
|
return InitError(ResolveErrMsg("bind", bind_arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connOptions.onion_binds.empty()) {
|
||||||
|
connOptions.onion_binds.push_back(DefaultOnionServiceTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {
|
||||||
|
const auto bind_addr = connOptions.onion_binds.front();
|
||||||
|
if (connOptions.onion_binds.size() > 1) {
|
||||||
|
InitWarning(strprintf(_("More than one onion bind address is provided. Using %s for the automatically created Tor onion service."), bind_addr.ToStringIPPort()));
|
||||||
|
}
|
||||||
|
StartTorControl(bind_addr);
|
||||||
|
}
|
||||||
|
|
||||||
for (const std::string& strBind : args.GetArgs("-whitebind")) {
|
for (const std::string& strBind : args.GetArgs("-whitebind")) {
|
||||||
NetWhitebindPermissions whitebind;
|
NetWhitebindPermissions whitebind;
|
||||||
bilingual_str error;
|
bilingual_str error;
|
||||||
|
27
src/net.cpp
27
src/net.cpp
@ -99,6 +99,11 @@ enum BindFlags {
|
|||||||
BF_NONE = 0,
|
BF_NONE = 0,
|
||||||
BF_EXPLICIT = (1U << 0),
|
BF_EXPLICIT = (1U << 0),
|
||||||
BF_REPORT_ERROR = (1U << 1),
|
BF_REPORT_ERROR = (1U << 1),
|
||||||
|
/**
|
||||||
|
* Do not call AddLocal() for our special addresses, e.g., for incoming
|
||||||
|
* Tor connections, to prevent gossiping them over the network.
|
||||||
|
*/
|
||||||
|
BF_DONT_ADVERTISE = (1U << 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef USE_WAKEUP_PIPE
|
#ifndef USE_WAKEUP_PIPE
|
||||||
@ -2875,9 +2880,6 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
|
|||||||
|
|
||||||
vhListenSocket.push_back(ListenSocket(sock->Release(), permissions));
|
vhListenSocket.push_back(ListenSocket(sock->Release(), permissions));
|
||||||
|
|
||||||
if (addrBind.IsRoutable() && fDiscover && (permissions & PF_NOBAN) == 0)
|
|
||||||
AddLocal(addrBind, LOCAL_BIND);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2974,10 +2976,18 @@ bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !(permissions & PF_NOBAN)) {
|
||||||
|
AddLocal(addr, LOCAL_BIND);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<NetWhitebindPermissions>& whiteBinds)
|
bool CConnman::InitBinds(
|
||||||
|
const std::vector<CService>& binds,
|
||||||
|
const std::vector<NetWhitebindPermissions>& whiteBinds,
|
||||||
|
const std::vector<CService>& onion_binds)
|
||||||
{
|
{
|
||||||
bool fBound = false;
|
bool fBound = false;
|
||||||
for (const auto& addrBind : binds) {
|
for (const auto& addrBind : binds) {
|
||||||
@ -2988,11 +2998,16 @@ bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<N
|
|||||||
}
|
}
|
||||||
if (binds.empty() && whiteBinds.empty()) {
|
if (binds.empty() && whiteBinds.empty()) {
|
||||||
struct in_addr inaddr_any;
|
struct in_addr inaddr_any;
|
||||||
inaddr_any.s_addr = INADDR_ANY;
|
inaddr_any.s_addr = htonl(INADDR_ANY);
|
||||||
struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
|
struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
|
||||||
fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE, NetPermissionFlags::PF_NONE);
|
fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE, NetPermissionFlags::PF_NONE);
|
||||||
fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE, NetPermissionFlags::PF_NONE);
|
fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE, NetPermissionFlags::PF_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto& addr_bind : onion_binds) {
|
||||||
|
fBound |= Bind(addr_bind, BF_EXPLICIT | BF_DONT_ADVERTISE, NetPermissionFlags::PF_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
return fBound;
|
return fBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3031,7 +3046,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) {
|
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds, connOptions.onion_binds)) {
|
||||||
if (clientInterface) {
|
if (clientInterface) {
|
||||||
clientInterface->ThreadSafeMessageBox(
|
clientInterface->ThreadSafeMessageBox(
|
||||||
_("Failed to listen on any port. Use -listen=0 if you want this."),
|
_("Failed to listen on any port. Use -listen=0 if you want this."),
|
||||||
|
@ -178,6 +178,7 @@ public:
|
|||||||
std::vector<NetWhitelistPermissions> vWhitelistedRange;
|
std::vector<NetWhitelistPermissions> vWhitelistedRange;
|
||||||
std::vector<NetWhitebindPermissions> vWhiteBinds;
|
std::vector<NetWhitebindPermissions> vWhiteBinds;
|
||||||
std::vector<CService> vBinds;
|
std::vector<CService> vBinds;
|
||||||
|
std::vector<CService> onion_binds;
|
||||||
bool m_use_addrman_outgoing = true;
|
bool m_use_addrman_outgoing = true;
|
||||||
std::vector<std::string> m_specified_outgoing;
|
std::vector<std::string> m_specified_outgoing;
|
||||||
std::vector<std::string> m_added_nodes;
|
std::vector<std::string> m_added_nodes;
|
||||||
@ -496,7 +497,11 @@ private:
|
|||||||
|
|
||||||
bool BindListenPort(const CService& bindAddr, bilingual_str& strError, NetPermissionFlags permissions);
|
bool BindListenPort(const CService& bindAddr, bilingual_str& strError, NetPermissionFlags permissions);
|
||||||
bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions);
|
bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions);
|
||||||
bool InitBinds(const std::vector<CService>& binds, const std::vector<NetWhitebindPermissions>& whiteBinds);
|
bool InitBinds(
|
||||||
|
const std::vector<CService>& binds,
|
||||||
|
const std::vector<NetWhitebindPermissions>& whiteBinds,
|
||||||
|
const std::vector<CService>& onion_binds);
|
||||||
|
|
||||||
void ThreadOpenAddedConnections();
|
void ThreadOpenAddedConnections();
|
||||||
void AddOneShot(const std::string& strDest);
|
void AddOneShot(const std::string& strDest);
|
||||||
void ProcessOneShot();
|
void ProcessOneShot();
|
||||||
|
@ -3,14 +3,17 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <chainparams.h>
|
|
||||||
#include <torcontrol.h>
|
#include <torcontrol.h>
|
||||||
#include <util/strencodings.h>
|
|
||||||
#include <netbase.h>
|
#include <chainparams.h>
|
||||||
|
#include <chainparamsbase.h>
|
||||||
|
#include <crypto/hmac_sha256.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
|
#include <netaddress.h>
|
||||||
|
#include <netbase.h>
|
||||||
|
#include <util/strencodings.h>
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
#include <util/time.h>
|
#include <util/time.h>
|
||||||
#include <crypto/hmac_sha256.h>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
@ -79,12 +82,12 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a Tor control port.
|
* Connect to a Tor control port.
|
||||||
* target is address of the form host:port.
|
* tor_control_center is address of the form host:port.
|
||||||
* connected is the handler that is called when connection is successfully established.
|
* connected is the handler that is called when connection is successfully established.
|
||||||
* disconnected is a handler that is called when the connection is broken.
|
* disconnected is a handler that is called when the connection is broken.
|
||||||
* Return true on success.
|
* Return true on success.
|
||||||
*/
|
*/
|
||||||
bool Connect(const std::string &target, const ConnectionCB& connected, const ConnectionCB& disconnected);
|
bool Connect(const std::string& tor_control_center, const ConnectionCB& connected, const ConnectionCB& disconnected);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnect from Tor control port.
|
* Disconnect from Tor control port.
|
||||||
@ -191,16 +194,16 @@ void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorControlConnection::Connect(const std::string &target, const ConnectionCB& _connected, const ConnectionCB& _disconnected)
|
bool TorControlConnection::Connect(const std::string& tor_control_center, const ConnectionCB& _connected, const ConnectionCB& _disconnected)
|
||||||
{
|
{
|
||||||
if (b_conn)
|
if (b_conn)
|
||||||
Disconnect();
|
Disconnect();
|
||||||
// Parse target address:port
|
// Parse tor_control_center address:port
|
||||||
struct sockaddr_storage connect_to_addr;
|
struct sockaddr_storage connect_to_addr;
|
||||||
int connect_to_addrlen = sizeof(connect_to_addr);
|
int connect_to_addrlen = sizeof(connect_to_addr);
|
||||||
if (evutil_parse_sockaddr_port(target.c_str(),
|
if (evutil_parse_sockaddr_port(tor_control_center.c_str(),
|
||||||
(struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0) {
|
(struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0) {
|
||||||
LogPrintf("tor: Error parsing socket address %s\n", target);
|
LogPrintf("tor: Error parsing socket address %s\n", tor_control_center);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,9 +216,9 @@ bool TorControlConnection::Connect(const std::string &target, const ConnectionCB
|
|||||||
this->connected = _connected;
|
this->connected = _connected;
|
||||||
this->disconnected = _disconnected;
|
this->disconnected = _disconnected;
|
||||||
|
|
||||||
// Finally, connect to target
|
// Finally, connect to tor_control_center
|
||||||
if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) {
|
if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) {
|
||||||
LogPrintf("tor: Error connecting to address %s\n", target);
|
LogPrintf("tor: Error connecting to address %s\n", tor_control_center);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -408,7 +411,7 @@ static bool WriteBinaryFile(const fs::path &filename, const std::string &data)
|
|||||||
class TorController
|
class TorController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TorController(struct event_base* base, const std::string& target);
|
TorController(struct event_base* base, const std::string& tor_control_center, const CService& target);
|
||||||
~TorController();
|
~TorController();
|
||||||
|
|
||||||
/** Get name of file to store private key in */
|
/** Get name of file to store private key in */
|
||||||
@ -418,7 +421,7 @@ public:
|
|||||||
void Reconnect();
|
void Reconnect();
|
||||||
private:
|
private:
|
||||||
struct event_base* base;
|
struct event_base* base;
|
||||||
std::string target;
|
const std::string m_tor_control_center;
|
||||||
TorControlConnection conn;
|
TorControlConnection conn;
|
||||||
std::string private_key;
|
std::string private_key;
|
||||||
std::string service_id;
|
std::string service_id;
|
||||||
@ -426,6 +429,7 @@ private:
|
|||||||
struct event *reconnect_ev;
|
struct event *reconnect_ev;
|
||||||
float reconnect_timeout;
|
float reconnect_timeout;
|
||||||
CService service;
|
CService service;
|
||||||
|
const CService m_target;
|
||||||
/** Cookie for SAFECOOKIE auth */
|
/** Cookie for SAFECOOKIE auth */
|
||||||
std::vector<uint8_t> cookie;
|
std::vector<uint8_t> cookie;
|
||||||
/** ClientNonce for SAFECOOKIE auth */
|
/** ClientNonce for SAFECOOKIE auth */
|
||||||
@ -448,18 +452,19 @@ private:
|
|||||||
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
|
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
TorController::TorController(struct event_base* _base, const std::string& _target):
|
TorController::TorController(struct event_base* _base, const std::string& tor_control_center, const CService& target):
|
||||||
base(_base),
|
base(_base),
|
||||||
target(_target), conn(base), reconnect(true), reconnect_ev(0),
|
m_tor_control_center(tor_control_center), conn(base), reconnect(true), reconnect_ev(0),
|
||||||
reconnect_timeout(RECONNECT_TIMEOUT_START)
|
reconnect_timeout(RECONNECT_TIMEOUT_START),
|
||||||
|
m_target(target)
|
||||||
{
|
{
|
||||||
reconnect_ev = event_new(base, -1, 0, reconnect_cb, this);
|
reconnect_ev = event_new(base, -1, 0, reconnect_cb, this);
|
||||||
if (!reconnect_ev)
|
if (!reconnect_ev)
|
||||||
LogPrintf("tor: Failed to create event for reconnection: out of memory?\n");
|
LogPrintf("tor: Failed to create event for reconnection: out of memory?\n");
|
||||||
// Start connection attempts immediately
|
// Start connection attempts immediately
|
||||||
if (!conn.Connect(_target, std::bind(&TorController::connected_cb, this, std::placeholders::_1),
|
if (!conn.Connect(m_tor_control_center, std::bind(&TorController::connected_cb, this, std::placeholders::_1),
|
||||||
std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) {
|
std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) {
|
||||||
LogPrintf("tor: Initiating connection to Tor control port %s failed\n", _target);
|
LogPrintf("tor: Initiating connection to Tor control port %s failed\n", m_tor_control_center);
|
||||||
}
|
}
|
||||||
// Read service private key if cached
|
// Read service private key if cached
|
||||||
std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
|
std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
|
||||||
@ -535,7 +540,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
|
|||||||
}
|
}
|
||||||
// Request hidden service, redirect port.
|
// Request hidden service, redirect port.
|
||||||
// Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports.
|
// Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports.
|
||||||
_conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, Params().GetDefaultPort(), GetListenPort()),
|
_conn.Command(strprintf("ADD_ONION %s Port=%i,%s", private_key, Params().GetDefaultPort(), m_target.ToStringIPPort()),
|
||||||
std::bind(&TorController::add_onion_cb, this, std::placeholders::_1, std::placeholders::_2));
|
std::bind(&TorController::add_onion_cb, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("tor: Authentication failed\n");
|
LogPrintf("tor: Authentication failed\n");
|
||||||
@ -697,7 +702,7 @@ void TorController::disconnected_cb(TorControlConnection& _conn)
|
|||||||
if (!reconnect)
|
if (!reconnect)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LogPrint(BCLog::TOR, "tor: Not connected to Tor control port %s, trying to reconnect\n", target);
|
LogPrint(BCLog::TOR, "tor: Not connected to Tor control port %s, trying to reconnect\n", m_tor_control_center);
|
||||||
|
|
||||||
// Single-shot timer for reconnect. Use exponential backoff.
|
// Single-shot timer for reconnect. Use exponential backoff.
|
||||||
struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0));
|
struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0));
|
||||||
@ -711,9 +716,9 @@ void TorController::Reconnect()
|
|||||||
/* Try to reconnect and reestablish if we get booted - for example, Tor
|
/* Try to reconnect and reestablish if we get booted - for example, Tor
|
||||||
* may be restarting.
|
* may be restarting.
|
||||||
*/
|
*/
|
||||||
if (!conn.Connect(target, std::bind(&TorController::connected_cb, this, std::placeholders::_1),
|
if (!conn.Connect(m_tor_control_center, std::bind(&TorController::connected_cb, this, std::placeholders::_1),
|
||||||
std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) {
|
std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) {
|
||||||
LogPrintf("tor: Re-initiating connection to Tor control port %s failed\n", target);
|
LogPrintf("tor: Re-initiating connection to Tor control port %s failed\n", m_tor_control_center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,14 +737,14 @@ void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg)
|
|||||||
static struct event_base *gBase;
|
static struct event_base *gBase;
|
||||||
static std::thread torControlThread;
|
static std::thread torControlThread;
|
||||||
|
|
||||||
static void TorControlThread()
|
static void TorControlThread(CService onion_service_target)
|
||||||
{
|
{
|
||||||
TorController ctrl(gBase, gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL));
|
TorController ctrl(gBase, gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL), onion_service_target);
|
||||||
|
|
||||||
event_base_dispatch(gBase);
|
event_base_dispatch(gBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartTorControl()
|
void StartTorControl(CService onion_service_target)
|
||||||
{
|
{
|
||||||
assert(!gBase);
|
assert(!gBase);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@ -753,7 +758,9 @@ void StartTorControl()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
torControlThread = std::thread(std::bind(&TraceThread<void (*)()>, "torcontrol", &TorControlThread));
|
torControlThread = std::thread(&TraceThread<std::function<void()>>, "torcontrol", [onion_service_target] {
|
||||||
|
TorControlThread(onion_service_target);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptTorControl()
|
void InterruptTorControl()
|
||||||
@ -774,3 +781,10 @@ void StopTorControl()
|
|||||||
gBase = nullptr;
|
gBase = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CService DefaultOnionServiceTarget()
|
||||||
|
{
|
||||||
|
struct in_addr onion_service_target;
|
||||||
|
onion_service_target.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
return {onion_service_target, BaseParams().OnionServiceTargetPort()};
|
||||||
|
}
|
||||||
|
@ -8,12 +8,17 @@
|
|||||||
#ifndef BITCOIN_TORCONTROL_H
|
#ifndef BITCOIN_TORCONTROL_H
|
||||||
#define BITCOIN_TORCONTROL_H
|
#define BITCOIN_TORCONTROL_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class CService;
|
||||||
|
|
||||||
extern const std::string DEFAULT_TOR_CONTROL;
|
extern const std::string DEFAULT_TOR_CONTROL;
|
||||||
static const bool DEFAULT_LISTEN_ONION = true;
|
static const bool DEFAULT_LISTEN_ONION = true;
|
||||||
|
|
||||||
void StartTorControl();
|
void StartTorControl(CService onion_service_target);
|
||||||
void InterruptTorControl();
|
void InterruptTorControl();
|
||||||
void StopTorControl();
|
void StopTorControl();
|
||||||
|
|
||||||
|
CService DefaultOnionServiceTarget();
|
||||||
|
|
||||||
#endif /* BITCOIN_TORCONTROL_H */
|
#endif /* BITCOIN_TORCONTROL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user