diff --git a/nano/core_test/toml.cpp b/nano/core_test/toml.cpp index b28c875750..5b9c7f5896 100644 --- a/nano/core_test/toml.cpp +++ b/nano/core_test/toml.cpp @@ -180,6 +180,7 @@ TEST (toml, daemon_config_deserialize_defaults) ASSERT_EQ (conf.node.peering_port, defaults.node.peering_port); ASSERT_EQ (conf.node.pow_sleep_interval, defaults.node.pow_sleep_interval); ASSERT_EQ (conf.node.preconfigured_peers, defaults.node.preconfigured_peers); + ASSERT_EQ (conf.node.blocked_peers, defaults.node.blocked_peers); ASSERT_EQ (conf.node.preconfigured_representatives, defaults.node.preconfigured_representatives); ASSERT_EQ (conf.node.receive_minimum, defaults.node.receive_minimum); ASSERT_EQ (conf.node.signature_checker_threads, defaults.node.signature_checker_threads); @@ -407,6 +408,7 @@ TEST (toml, daemon_config_deserialize_no_defaults) peering_port = 999 pow_sleep_interval= 999 preconfigured_peers = ["dev.org"] + blocked_peers = ["192.168.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"] preconfigured_representatives = ["nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4"] receive_minimum = "999" signature_checker_threads = 999 @@ -597,6 +599,7 @@ TEST (toml, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.peering_port, defaults.node.peering_port); ASSERT_NE (conf.node.pow_sleep_interval, defaults.node.pow_sleep_interval); ASSERT_NE (conf.node.preconfigured_peers, defaults.node.preconfigured_peers); + ASSERT_NE (conf.node.blocked_peers, defaults.node.blocked_peers); ASSERT_NE (conf.node.preconfigured_representatives, defaults.node.preconfigured_representatives); ASSERT_NE (conf.node.receive_minimum, defaults.node.receive_minimum); ASSERT_NE (conf.node.signature_checker_threads, defaults.node.signature_checker_threads); diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index 61179c685c..3b357578bd 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -144,6 +144,8 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const preconfigured_peers_l->push_back (*i); } + auto blocked_peers_l (toml.create_array ("blocked_peers", "A list of \"address\" (ipv4 or ipv6 notation ip address) that you want to ignore all requests from. \nExample: [\"192.168.0.1\",\"::ffff:10.0.0.1\"]")); + auto preconfigured_representatives_l (toml.create_array ("preconfigured_representatives", "A list of representative account addresses used when creating new accounts in internal wallets.")); for (auto i (preconfigured_representatives.begin ()), n (preconfigured_representatives.end ()); i != n; ++i) { @@ -288,6 +290,14 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) }); } + if (toml.has_key ("blocked_peers")) + { + blocked_peers.clear (); + toml.array_entries_required ("blocked_peers", [this, &toml] (std::string entry) { + blocked_peers.push_back (entry); + }); + } + if (toml.has_key ("preconfigured_representatives")) { preconfigured_representatives.clear (); diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index d1a42fa370..5f4ff3fc24 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -54,6 +54,7 @@ class node_config std::vector> work_peers; std::vector> secondary_work_peers{ { "127.0.0.1", 8076 } }; /* Default of nano-pow-server */ std::vector preconfigured_peers; + std::vector blocked_peers{}; std::vector preconfigured_representatives; unsigned bootstrap_fraction_numerator{ 1 }; nano::amount receive_minimum{ nano::xrb_ratio }; diff --git a/nano/node/transport/tcp_server.cpp b/nano/node/transport/tcp_server.cpp index af163701a5..f2b9f1733a 100644 --- a/nano/node/transport/tcp_server.cpp +++ b/nano/node/transport/tcp_server.cpp @@ -44,6 +44,7 @@ nano::transport::tcp_listener::tcp_listener (uint16_t port_a, nano::node & node_ void nano::transport::tcp_listener::start (std::function const &, boost::system::error_code const &)> callback_a) { + configure_blocked_peers (); nano::lock_guard lock{ mutex }; on = true; acceptor.open (local.protocol ()); @@ -136,6 +137,13 @@ void nano::transport::tcp_listener::on_connection (std::functionevict_dead_connections (); + if (this_l->is_ip_blocked (new_connection->remote.address ())) + { + this_l->node.logger.info (nano::log::type::tcp_listener, "Connection refused from blocked IP: {}", new_connection->remote_endpoint ().address ().to_string ()); + this_l->on_connection (std::move (cbk)); + return; + } + if (this_l->connections_per_address.size () >= this_l->max_inbound_connections) { this_l->node.stats.inc (nano::stat::type::tcp, nano::stat::detail::tcp_accept_failure, nano::stat::dir::in); @@ -217,6 +225,44 @@ void nano::transport::tcp_listener::on_connection (std::function #include +#include namespace nano { @@ -35,6 +36,7 @@ class tcp_listener final : public std::enable_shared_from_this bootstrap_count{ 0 }; std::atomic realtime_count{ 0 }; + std::unordered_set blocked_ips; private: boost::asio::strand strand; @@ -48,6 +50,8 @@ class tcp_listener final : public std::enable_shared_from_this const & new_connection); bool limit_reached_for_incoming_subnetwork_connections (std::shared_ptr const & new_connection); + void configure_blocked_peers (); + bool is_ip_blocked (const boost::asio::ip::address & ip_address) const; }; std::unique_ptr collect_container_info (tcp_listener & bootstrap_listener, std::string const & name);