diff --git a/src/init.cpp b/src/init.cpp index 8fe3fa9828e7..87e55a47b212 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -596,7 +596,7 @@ void SetupServerArgs(NodeContext& node) argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-peertimeout=", strprintf("Specify p2p connection timeout in seconds. This option determines the amount of time a peer may be inactive before the connection to it is dropped. (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-port=", strprintf("Listen for connections on (default: %u, testnet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); + argsman.AddArg("-port=", strprintf("Listen for connections on . Nodes not using the default ports (default: %u, testnet: %u, regtest: %u) are unlikely to get incoming connections. Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); argsman.AddArg("-proxy=", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-seednode=", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); diff --git a/src/net.cpp b/src/net.cpp index 71843e8ded01..e3e0e8c15f9b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2385,7 +2385,11 @@ void CConnman::ThreadOpenConnections(const std::vector connect) continue; } - // do not allow non-default ports, unless after 50 invalid addresses selected already + // Do not allow non-default ports, unless after 50 invalid + // addresses selected already. This is to prevent malicious peers + // from advertising themselves as a service on another host and + // port, causing a DoS attack as nodes around the network attempt + // to connect to it fruitlessly. if ((!isMasternode || !Params().AllowMultiplePorts()) && addr.GetPort() != Params().GetDefaultPort(addr.GetNetwork()) && addr.GetPort() != GetListenPort() && nTries < 50) { continue; } diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 1a26996d9073..7f2918bea092 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -670,11 +670,8 @@ struct CNodeState { //! Whether this peer is an inbound connection bool m_is_inbound; - //! Whether this peer is a manual connection - bool m_is_manual_connection; - - CNodeState(CAddress addrIn, bool is_inbound, bool is_manual) : - address(addrIn), m_is_inbound(is_inbound), m_is_manual_connection(is_manual) + CNodeState(CAddress addrIn, bool is_inbound) : + address(addrIn), m_is_inbound(is_inbound) { pindexBestKnownBlock = nullptr; hashLastUnknownBlock.SetNull(); @@ -1159,7 +1156,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode) { NodeId nodeid = pnode->GetId(); { LOCK(cs_main); - mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, pnode->fInbound, pnode->m_manual_connection)); + mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, pnode->fInbound)); } { PeerRef peer = std::make_shared(nodeid); @@ -1475,8 +1472,8 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati } // Discourage outbound (but not inbound) peers if on an invalid chain. - // Exempt HB compact block peers and manual connections. - if (!via_compact_block && !node_state->m_is_inbound && !node_state->m_is_manual_connection) { + // Exempt HB compact block peers. Manual connections are always protected from discouragement. + if (!via_compact_block && !node_state->m_is_inbound) { Misbehaving(nodeid, 100, message); return true; } diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index 56ecab8d5159..285f68a913f2 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -29,27 +29,7 @@ FUZZ_TARGET_INIT(net, initialize_net) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - const std::optional address = ConsumeDeserializable(fuzzed_data_provider); - if (!address) { - return; - } - const std::optional address_bind = ConsumeDeserializable(fuzzed_data_provider); - if (!address_bind) { - return; - } - - CNode node{fuzzed_data_provider.ConsumeIntegral(), - static_cast(fuzzed_data_provider.ConsumeIntegral()), - INVALID_SOCKET, - *address, - fuzzed_data_provider.ConsumeIntegral(), - fuzzed_data_provider.ConsumeIntegral(), - *address_bind, - fuzzed_data_provider.ConsumeRandomLengthString(32), - fuzzed_data_provider.ConsumeBool(), - fuzzed_data_provider.ConsumeBool(), - fuzzed_data_provider.ConsumeBool() - }; + CNode node{ConsumeNode(fuzzed_data_provider)}; while (fuzzed_data_provider.ConsumeBool()) { CallOneOf( fuzzed_data_provider, diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 1f7123e4469c..26cc2a2bb1cc 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -490,11 +490,8 @@ def assert_start_raises_init_error(self, extra_args=None, expected_msg=None, mat tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False) as log_stdout: try: self.start(extra_args, stdout=log_stdout, stderr=log_stderr, *args, **kwargs) - self.wait_for_rpc_connection() - self.stop_node() - self.wait_until_stopped() - except FailedToStartError as e: - self.log.debug('dashd failed to start: %s', e) + ret = self.process.wait(timeout=self.rpc_timeout) + self.log.debug(self._node_msg(f'dashd exited with status {ret} during initialization')) self.running = False self.process = None # Check stderr for expected message @@ -513,11 +510,15 @@ def assert_start_raises_init_error(self, extra_args=None, expected_msg=None, mat if expected_msg != stderr: self._raise_assertion_error( 'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr)) - else: + except subprocess.TimeoutExpired: + self.process.kill() + self.running = False + self.process = None + assert_msg = f'dashd should have exited within {self.rpc_timeout}s ' if expected_msg is None: - assert_msg = "dashd should have exited with an error" + assert_msg += "with an error" else: - assert_msg = "dashd should have exited with expected error " + expected_msg + assert_msg += "with expected error " + expected_msg self._raise_assertion_error(assert_msg) def add_p2p_connection(self, p2p_conn, *, wait_for_verack=True, **kwargs): diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index f9c98caba5de..ca06d07f8cfb 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -25,9 +25,10 @@ got_loading_error = False + def test_load_unload(node, name): global got_loading_error - for i in range(10): + while True: if got_loading_error: return try: @@ -67,7 +68,7 @@ def wallet_file(name): return wallet_dir(name, self.wallet_data_filename) return wallet_dir(name) - assert_equal(self.nodes[0].listwalletdir(), { 'wallets': [{ 'name': self.default_wallet_name }] }) + assert_equal(self.nodes[0].listwalletdir(), {'wallets': [{'name': self.default_wallet_name}]}) # check wallet.dat is created self.stop_nodes() @@ -261,7 +262,7 @@ def wallet_file(name): threads = [] for _ in range(3): n = node.cli if self.options.usecli else get_rpc_proxy(node.url, 1, timeout=600, coveragedir=node.coverage_dir) - t = Thread(target=test_load_unload, args=(n, wallet_names[2], )) + t = Thread(target=test_load_unload, args=(n, wallet_names[2])) t.start() threads.append(t) for t in threads: