Skip to content

Commit e53a850

Browse files
committed
net: respect -onlynet= when making outbound connections
Do not make outbound connections to hosts which belong to a network which is restricted by `-onlynet`. This applies to hosts that are automatically chosen to connect to and to anchors. This does not apply to hosts given to `-connect`, `-addnode`, `addnode` RPC, dns seeds, `-seednodes`. Fixes bitcoin/bitcoin#13378 Fixes bitcoin/bitcoin#22647 Supersedes bitcoin/bitcoin#22651
1 parent 9394964 commit e53a850

File tree

6 files changed

+45
-25
lines changed

6 files changed

+45
-25
lines changed

doc/i2p.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,7 @@ logging` for more information.
6767

6868
Make outgoing connections only to I2P addresses. Incoming connections are not
6969
affected by this option. It can be specified multiple times to allow multiple
70-
network types, e.g. onlynet=ipv4, onlynet=ipv6, onlynet=onion, onlynet=i2p.
71-
72-
Warning: if you use -onlynet with values other than onion, and the -onion or
73-
-proxy option is set, then outgoing onion connections will still be made; use
74-
-noonion or -onion=0 to disable outbound onion connections in this case.
70+
network types, e.g. onlynet=onion, onlynet=i2p.
7571

7672
I2P support was added to Bitcoin Core in version 22.0 and there may be fewer I2P
7773
peers than Tor or IP ones. Therefore, using I2P alone without other networks may

doc/release-notes.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ Updated settings
131131
E.g. `-maxuploadtarget=500g`. No whitespace, +- or fractions allowed.
132132
Default is `M` if no suffix provided. (#23249)
133133

134+
- If `-proxy=` is given together with `-noonion` then the provided proxy will
135+
not be set as a proxy for reaching the Tor network. So it will not be
136+
possible to open manual connections to the Tor network for example with the
137+
`addnode` RPC. To mimic the old behavior use `-proxy=` together with
138+
`-onlynet=` listing all relevant networks except `onion`. (#22834)
139+
134140
Tools and Utilities
135141
-------------------
136142

doc/tor.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,7 @@ outgoing connections, but more is possible.
5656
-onlynet=onion Make outgoing connections only to .onion addresses. Incoming
5757
connections are not affected by this option. This option can be
5858
specified multiple times to allow multiple network types, e.g.
59-
onlynet=ipv4, onlynet=ipv6, onlynet=onion, onlynet=i2p.
60-
Warning: if you use -onlynet with values other than onion, and
61-
the -onion or -proxy option is set, then outgoing onion
62-
connections will still be made; use -noonion or -onion=0 to
63-
disable outbound onion connections in this case.
59+
onlynet=onion, onlynet=i2p.
6460

6561
In a typical situation, this suffices to run behind a Tor proxy:
6662

src/init.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ void SetupServerArgs(ArgsManager& argsman)
441441
argsman.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
442442
argsman.AddArg("-i2psam=<ip:port>", "I2P SAM proxy to reach I2P peers and accept I2P connections (default: none)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
443443
argsman.AddArg("-i2pacceptincoming", "If set and -i2psam is also set then incoming I2P connections are accepted via the SAM proxy. If this is not set but -i2psam is set then only outgoing connections will be made to the I2P network. Ignored if -i2psam is not set. Listening for incoming I2P connections is done through the SAM proxy, not by binding to a local address and port (default: 1)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
444-
argsman.AddArg("-onlynet=<net>", "Make outgoing connections only through network <net> (" + Join(GetNetworkNames(), ", ") + "). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks. Warning: if it is used with non-onion networks and the -onion or -proxy option is set, then outbound onion connections will still be made; use -noonion or -onion=0 to disable outbound onion connections in this case.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
444+
argsman.AddArg("-onlynet=<net>", "Make automatic outgoing connections only through network <net> (" + Join(GetNetworkNames(), ", ") + "). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
445445
argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
446446
argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
447447
argsman.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -1315,11 +1315,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
13151315
// Check for host lookup allowed before parsing any network related parameters
13161316
fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
13171317

1318+
proxyType onion_proxy;
1319+
13181320
bool proxyRandomize = args.GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE);
13191321
// -proxy sets a proxy for all outgoing network traffic
13201322
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
13211323
std::string proxyArg = args.GetArg("-proxy", "");
1322-
SetReachable(NET_ONION, false);
13231324
if (proxyArg != "" && proxyArg != "0") {
13241325
CService proxyAddr;
13251326
if (!Lookup(proxyArg, proxyAddr, 9050, fNameLookup)) {
@@ -1332,10 +1333,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
13321333

13331334
SetProxy(NET_IPV4, addrProxy);
13341335
SetProxy(NET_IPV6, addrProxy);
1335-
SetProxy(NET_ONION, addrProxy);
13361336
SetProxy(NET_CJDNS, addrProxy);
13371337
SetNameProxy(addrProxy);
1338-
SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
1338+
onion_proxy = addrProxy;
13391339
}
13401340

13411341
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
@@ -1344,18 +1344,26 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
13441344
std::string onionArg = args.GetArg("-onion", "");
13451345
if (onionArg != "") {
13461346
if (onionArg == "0") { // Handle -noonion/-onion=0
1347-
SetReachable(NET_ONION, false);
1347+
onion_proxy = proxyType{};
13481348
} else {
1349-
CService onionProxy;
1350-
if (!Lookup(onionArg, onionProxy, 9050, fNameLookup)) {
1349+
CService addr;
1350+
if (!Lookup(onionArg, addr, 9050, fNameLookup) || !addr.IsValid()) {
13511351
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
13521352
}
1353-
proxyType addrOnion = proxyType(onionProxy, proxyRandomize);
1354-
if (!addrOnion.IsValid())
1355-
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
1356-
SetProxy(NET_ONION, addrOnion);
1357-
SetReachable(NET_ONION, true);
1353+
onion_proxy = proxyType{addr, proxyRandomize};
1354+
}
1355+
}
1356+
1357+
if (onion_proxy.IsValid()) {
1358+
SetProxy(NET_ONION, onion_proxy);
1359+
} else {
1360+
if (args.IsArgSet("-onlynet") && IsReachable(NET_ONION)) {
1361+
return InitError(
1362+
_("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
1363+
"reaching the Tor network is not provided (no -proxy= and no -onion= given) or "
1364+
"it is explicitly forbidden (-onion=0)"));
13581365
}
1366+
SetReachable(NET_ONION, false);
13591367
}
13601368

13611369
for (const std::string& strAddr : args.GetArgs("-externalip")) {
@@ -1843,7 +1851,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
18431851
if (!Lookup(i2psam_arg, addr, 7656, fNameLookup) || !addr.IsValid()) {
18441852
return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));
18451853
}
1846-
SetReachable(NET_I2P, true);
18471854
SetProxy(NET_I2P, proxyType{addr});
18481855
} else {
18491856
SetReachable(NET_I2P, false);

src/torcontrol.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,22 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
380380
CService resolved(LookupNumeric("127.0.0.1", 9050));
381381
proxyType addrOnion = proxyType(resolved, true);
382382
SetProxy(NET_ONION, addrOnion);
383-
SetReachable(NET_ONION, true);
383+
384+
const auto onlynets = gArgs.GetArgs("-onlynet");
385+
386+
const bool onion_allowed_by_onlynet{
387+
!gArgs.IsArgSet("-onlynet") ||
388+
std::any_of(onlynets.begin(), onlynets.end(), [](const auto& n) {
389+
return ParseNetwork(n) == NET_ONION;
390+
})};
391+
392+
if (onion_allowed_by_onlynet) {
393+
// If NET_ONION is reachable, then the below is a noop.
394+
//
395+
// If NET_ONION is not reachable, then none of -proxy or -onion was given.
396+
// Since we are here, then -torcontrol and -torpassword were given.
397+
SetReachable(NET_ONION, true);
398+
}
384399
}
385400

386401
// Finally - now create the service

test/functional/feature_proxy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ def networks_dict(d):
280280
n3 = networks_dict(self.nodes[3].getnetworkinfo())
281281
assert_equal(NETWORKS, n3.keys())
282282
for net in NETWORKS:
283-
if net == NET_I2P:
283+
if net == NET_I2P or net == NET_ONION:
284284
expected_proxy = ''
285285
else:
286286
expected_proxy = f'[{self.conf3.addr[0]}]:{self.conf3.addr[1]}'

0 commit comments

Comments
 (0)