Skip to content

Commit df2129a

Browse files
committed
Merge #19991: net: Use alternative port for incoming Tor connections
96571b3 doc: Update onion service target port numbers in tor.md (Hennadii Stepanov) bb145c9 net: Extend -bind config option with optional network type (Hennadii Stepanov) 92bd3c1 net, refactor: Move AddLocal call one level up (Hennadii Stepanov) 57f17e5 net: Pass onion service target to Tor controller (Hennadii Stepanov) e3f0785 refactor: Rename TorController::target to m_tor_control_center (Hennadii Stepanov) fdd3ae4 net, refactor: Refactor CBaseChainParams::RPCPort function (Hennadii Stepanov) a5266d4 net: Add alternative port for onion service (Hennadii Stepanov) b3273cf net: Use network byte order for in_addr.s_addr (Hennadii Stepanov) Pull request description: This PR adds ability to label incoming Tor connections as different from normal localhost connections. Closes #8973. Closes #16693. Default onion service target ports are: - 8334 on mainnnet - 18334 on testnet - 38334 on signet - 18445 on regtest To set the onion service target socket manually the extended `-bind` config option could be used: ``` $ src/bitcoind -help | grep -A 6 -e '-bind' -bind=<addr>[:<port>][=onion] 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:8334=onion, testnet: 127.0.0.1:18334=onion, signet: 127.0.0.1:38334=onion, regtest: 127.0.0.1:18445=onion) ``` Since [pr19991.02 update](bitcoin/bitcoin#19991 (comment)) this PR is an alternative to #19043. ACKs for top commit: Sjors: re-utACK 96571b3 vasild: ACK 96571b3 laanwj: Re-ACK 96571b3 Tree-SHA512: cb0eade80f4b3395f405f775e1b89c086a1f09d5a4464df6cb4faf808d9c2245474e1720b2b538f203f6c1996507f69b09f5a6e35ea42633c10e22bd733d4438
2 parents 60ec57b + 96571b3 commit df2129a

File tree

8 files changed

+125
-56
lines changed

8 files changed

+125
-56
lines changed

doc/tor.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ config file): *Needed for Tor version 0.2.7.0 and older versions of Tor only. Fo
4545
versions of Tor see [Section 3](#3-automatically-listen-on-tor).*
4646

4747
HiddenServiceDir /var/lib/tor/bitcoin-service/
48-
HiddenServicePort 8333 127.0.0.1:8333
49-
HiddenServicePort 18333 127.0.0.1:18333
48+
HiddenServicePort 8333 127.0.0.1:8334
49+
HiddenServicePort 18333 127.0.0.1:18334
5050

51-
The directory can be different of course, but (both) port numbers should be equal to
52-
your bitcoind's P2P listen port (8333 by default).
51+
The directory can be different of course, but virtual port numbers should be equal to
52+
your bitcoind's P2P listen port (8333 by default), and target addresses and ports
53+
should be equal to binding address and port for inbound Tor connections (127.0.0.1:8334 by default).
5354

5455
-externalip=X You can tell bitcoin about its publicly reachable address using
5556
this option, and this can be a .onion address. Given the above

src/chainparamsbase.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,20 @@ const CBaseChainParams& BaseParams()
3737
return *globalChainBaseParams;
3838
}
3939

40+
/**
41+
* Port numbers for incoming Tor connections (8334, 18334, 38334, 18445) have
42+
* been chosen arbitrarily to keep ranges of used ports tight.
43+
*/
4044
std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
4145
{
4246
if (chain == CBaseChainParams::MAIN) {
43-
return MakeUnique<CBaseChainParams>("", 8332);
47+
return MakeUnique<CBaseChainParams>("", 8332, 8334);
4448
} else if (chain == CBaseChainParams::TESTNET) {
45-
return MakeUnique<CBaseChainParams>("testnet3", 18332);
49+
return MakeUnique<CBaseChainParams>("testnet3", 18332, 18334);
4650
} else if (chain == CBaseChainParams::SIGNET) {
47-
return MakeUnique<CBaseChainParams>("signet", 38332);
51+
return MakeUnique<CBaseChainParams>("signet", 38332, 38334);
4852
} else if (chain == CBaseChainParams::REGTEST) {
49-
return MakeUnique<CBaseChainParams>("regtest", 18443);
53+
return MakeUnique<CBaseChainParams>("regtest", 18443, 18445);
5054
}
5155
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
5256
}

src/chainparamsbase.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,16 @@ class CBaseChainParams
2626
///@}
2727

2828
const std::string& DataDir() const { return strDataDir; }
29-
int RPCPort() const { return nRPCPort; }
29+
uint16_t RPCPort() const { return m_rpc_port; }
30+
uint16_t OnionServiceTargetPort() const { return m_onion_service_target_port; }
3031

3132
CBaseChainParams() = delete;
32-
CBaseChainParams(const std::string& data_dir, int rpc_port) : nRPCPort(rpc_port), strDataDir(data_dir) {}
33+
CBaseChainParams(const std::string& data_dir, uint16_t rpc_port, uint16_t onion_service_target_port)
34+
: m_rpc_port(rpc_port), m_onion_service_target_port(onion_service_target_port), strDataDir(data_dir) {}
3335

3436
private:
35-
int nRPCPort;
37+
const uint16_t m_rpc_port;
38+
const uint16_t m_onion_service_target_port;
3639
std::string strDataDir;
3740
};
3841

src/init.cpp

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ void SetupServerArgs(NodeContext& node)
442442
argsman.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
443443
argsman.AddArg("-asmap=<file>", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
444444
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
445-
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);
445+
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, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), signetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
446446
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);
447447
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
448448
argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -1918,9 +1918,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
19181918
}
19191919
LogPrintf("nBestHeight = %d\n", chain_active_height);
19201920

1921-
if (args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
1922-
StartTorControl();
1923-
19241921
Discover();
19251922

19261923
// Map ports with UPnP
@@ -1947,13 +1944,39 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
19471944
connOptions.nMaxOutboundLimit = nMaxOutboundLimit;
19481945
connOptions.m_peer_connect_timeout = peer_connect_timeout;
19491946

1950-
for (const std::string& strBind : args.GetArgs("-bind")) {
1951-
CService addrBind;
1952-
if (!Lookup(strBind, addrBind, GetListenPort(), false)) {
1953-
return InitError(ResolveErrMsg("bind", strBind));
1947+
for (const std::string& bind_arg : args.GetArgs("-bind")) {
1948+
CService bind_addr;
1949+
const size_t index = bind_arg.rfind('=');
1950+
if (index == std::string::npos) {
1951+
if (Lookup(bind_arg, bind_addr, GetListenPort(), false)) {
1952+
connOptions.vBinds.push_back(bind_addr);
1953+
continue;
1954+
}
1955+
} else {
1956+
const std::string network_type = bind_arg.substr(index + 1);
1957+
if (network_type == "onion") {
1958+
const std::string truncated_bind_arg = bind_arg.substr(0, index);
1959+
if (Lookup(truncated_bind_arg, bind_addr, BaseParams().OnionServiceTargetPort(), false)) {
1960+
connOptions.onion_binds.push_back(bind_addr);
1961+
continue;
1962+
}
1963+
}
19541964
}
1955-
connOptions.vBinds.push_back(addrBind);
1965+
return InitError(ResolveErrMsg("bind", bind_arg));
19561966
}
1967+
1968+
if (connOptions.onion_binds.empty()) {
1969+
connOptions.onion_binds.push_back(DefaultOnionServiceTarget());
1970+
}
1971+
1972+
if (args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {
1973+
const auto bind_addr = connOptions.onion_binds.front();
1974+
if (connOptions.onion_binds.size() > 1) {
1975+
InitWarning(strprintf(_("More than one onion bind address is provided. Using %s for the automatically created Tor onion service."), bind_addr.ToStringIPPort()));
1976+
}
1977+
StartTorControl(bind_addr);
1978+
}
1979+
19571980
for (const std::string& strBind : args.GetArgs("-whitebind")) {
19581981
NetWhitebindPermissions whitebind;
19591982
bilingual_str error;

src/net.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ enum BindFlags {
8383
BF_NONE = 0,
8484
BF_EXPLICIT = (1U << 0),
8585
BF_REPORT_ERROR = (1U << 1),
86+
/**
87+
* Do not call AddLocal() for our special addresses, e.g., for incoming
88+
* Tor connections, to prevent gossiping them over the network.
89+
*/
90+
BF_DONT_ADVERTISE = (1U << 2),
8691
};
8792

8893
// The set of sockets cannot be modified while waiting
@@ -2241,10 +2246,6 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
22412246
}
22422247

22432248
vhListenSocket.push_back(ListenSocket(hListenSocket, permissions));
2244-
2245-
if (addrBind.IsRoutable() && fDiscover && (permissions & PF_NOBAN) == 0)
2246-
AddLocal(addrBind, LOCAL_BIND);
2247-
22482249
return true;
22492250
}
22502251

@@ -2338,10 +2339,18 @@ bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags
23382339
}
23392340
return false;
23402341
}
2342+
2343+
if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !(permissions & PF_NOBAN)) {
2344+
AddLocal(addr, LOCAL_BIND);
2345+
}
2346+
23412347
return true;
23422348
}
23432349

2344-
bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<NetWhitebindPermissions>& whiteBinds)
2350+
bool CConnman::InitBinds(
2351+
const std::vector<CService>& binds,
2352+
const std::vector<NetWhitebindPermissions>& whiteBinds,
2353+
const std::vector<CService>& onion_binds)
23452354
{
23462355
bool fBound = false;
23472356
for (const auto& addrBind : binds) {
@@ -2352,11 +2361,16 @@ bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<N
23522361
}
23532362
if (binds.empty() && whiteBinds.empty()) {
23542363
struct in_addr inaddr_any;
2355-
inaddr_any.s_addr = INADDR_ANY;
2364+
inaddr_any.s_addr = htonl(INADDR_ANY);
23562365
struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
23572366
fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE, NetPermissionFlags::PF_NONE);
23582367
fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE, NetPermissionFlags::PF_NONE);
23592368
}
2369+
2370+
for (const auto& addr_bind : onion_binds) {
2371+
fBound |= Bind(addr_bind, BF_EXPLICIT | BF_DONT_ADVERTISE, NetPermissionFlags::PF_NONE);
2372+
}
2373+
23602374
return fBound;
23612375
}
23622376

@@ -2375,7 +2389,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
23752389
nMaxOutboundCycleStartTime = 0;
23762390
}
23772391

2378-
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) {
2392+
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds, connOptions.onion_binds)) {
23792393
if (clientInterface) {
23802394
clientInterface->ThreadSafeMessageBox(
23812395
_("Failed to listen on any port. Use -listen=0 if you want this."),

src/net.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ class CConnman
220220
std::vector<NetWhitelistPermissions> vWhitelistedRange;
221221
std::vector<NetWhitebindPermissions> vWhiteBinds;
222222
std::vector<CService> vBinds;
223+
std::vector<CService> onion_binds;
223224
bool m_use_addrman_outgoing = true;
224225
std::vector<std::string> m_specified_outgoing;
225226
std::vector<std::string> m_added_nodes;
@@ -417,7 +418,11 @@ class CConnman
417418

418419
bool BindListenPort(const CService& bindAddr, bilingual_str& strError, NetPermissionFlags permissions);
419420
bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions);
420-
bool InitBinds(const std::vector<CService>& binds, const std::vector<NetWhitebindPermissions>& whiteBinds);
421+
bool InitBinds(
422+
const std::vector<CService>& binds,
423+
const std::vector<NetWhitebindPermissions>& whiteBinds,
424+
const std::vector<CService>& onion_binds);
425+
421426
void ThreadOpenAddedConnections();
422427
void AddAddrFetch(const std::string& strDest);
423428
void ProcessAddrFetch();

0 commit comments

Comments
 (0)