Skip to content

Commit

Permalink
Moved ip blocking to tcp listener
Browse files Browse the repository at this point in the history
  • Loading branch information
RickiNano committed Feb 1, 2024
1 parent 0897961 commit 0db8f91
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 45 deletions.
2 changes: 1 addition & 1 deletion nano/core_test/toml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +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"]
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
Expand Down
41 changes: 0 additions & 41 deletions nano/node/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ nano::network::~network ()

void nano::network::start ()
{
Configure_blocked_peers ();

if (!node.flags.disable_connection_cleanup)
{
ongoing_cleanup ();
Expand Down Expand Up @@ -349,39 +347,6 @@ void nano::network::broadcast_confirm_req_many (std::deque<std::pair<std::shared
}
}

void nano::network::Configure_blocked_peers ()
{
for (const std::string & ip_string : node.config.blocked_peers)
{
boost::system::error_code ec;
auto ip_address = boost::asio::ip::address::from_string (ip_string, ec);

if (!ec)
{
if (ip_address.is_v4 ())
{
// Convert IPv4 address to IPv4-mapped IPv6 address
blocked_ips.insert (boost::asio::ip::address_v6::v4_mapped (ip_address.to_v4 ()));
}
else
{
blocked_ips.insert (ip_address);
}

node.logger.info (nano::log::type::network, "Added blocking rule for ip {}", ip_address.to_string ());
}
else
{
node.logger.error (nano::log::type::network, "Invalid IP address: {}", ip_string);
}
}
}

bool nano::network::is_ip_blocked (const boost::asio::ip::address & ip_address) const
{
return blocked_ips.find (ip_address) != blocked_ips.end ();
}

namespace
{
class network_message_visitor : public nano::message_visitor
Expand Down Expand Up @@ -503,12 +468,6 @@ class network_message_visitor : public nano::message_visitor

void nano::network::process_message (nano::message const & message, std::shared_ptr<nano::transport::channel> const & channel)
{
if (is_ip_blocked (channel->get_tcp_endpoint ().address ()))
{
node.logger.debug (nano::log::type::network, "Ignoring message from IP {}", channel->get_tcp_endpoint ().address ().to_string ());
return;
}

node.stats.inc (nano::stat::type::message, to_stat_detail (message.header.type), nano::stat::dir::in);

network_message_visitor visitor{ node, channel };
Expand Down
3 changes: 0 additions & 3 deletions nano/node/network.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ class network final
void broadcast_confirm_req_base (std::shared_ptr<nano::block> const &, std::shared_ptr<std::vector<std::shared_ptr<nano::transport::channel>>> const &, unsigned, bool = false);
void broadcast_confirm_req_batched_many (std::unordered_map<std::shared_ptr<nano::transport::channel>, std::deque<std::pair<nano::block_hash, nano::root>>>, std::function<void ()> = nullptr, unsigned = broadcast_interval_ms, bool = false);
void broadcast_confirm_req_many (std::deque<std::pair<std::shared_ptr<nano::block>, std::shared_ptr<std::vector<std::shared_ptr<nano::transport::channel>>>>>, std::function<void ()> = nullptr, unsigned = broadcast_interval_ms);
void Configure_blocked_peers ();
bool is_ip_blocked (const boost::asio::ip::address & ip_address) const;
std::shared_ptr<nano::transport::channel> find_node_id (nano::account const &);
std::shared_ptr<nano::transport::channel> find_channel (nano::endpoint const &);
bool not_a_peer (nano::endpoint const &, bool);
Expand Down Expand Up @@ -135,7 +133,6 @@ class network final
bool verify_handshake_response (nano::node_id_handshake::response_payload const & response, nano::endpoint const & remote_endpoint);
std::optional<nano::node_id_handshake::query_payload> prepare_handshake_query (nano::endpoint const & remote_endpoint);
nano::node_id_handshake::response_payload prepare_handshake_response (nano::node_id_handshake::query_payload const & query, bool v2) const;
std::unordered_set<boost::asio::ip::address> blocked_ips;

private:
void process_message (nano::message const &, std::shared_ptr<nano::transport::channel> const &);
Expand Down
46 changes: 46 additions & 0 deletions nano/node/transport/tcp_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool (std::shared_ptr<nano::transport::socket> const &, boost::system::error_code const &)> callback_a)
{
configure_blocked_peers ();
nano::lock_guard<nano::mutex> lock{ mutex };
on = true;
acceptor.open (local.protocol ());
Expand Down Expand Up @@ -136,6 +137,13 @@ void nano::transport::tcp_listener::on_connection (std::function<bool (std::shar
[this_l, new_connection, cbk = std::move (callback)] (boost::system::error_code const & ec_a) mutable {
this_l->evict_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);
Expand Down Expand Up @@ -217,6 +225,44 @@ void nano::transport::tcp_listener::on_connection (std::function<bool (std::shar
}));
}

void nano::transport::tcp_listener::configure_blocked_peers ()
{
blocked_ips.clear ();
if (!node.config.blocked_peers.empty ())
{
node.logger.info (nano::log::type::tcp_listener, "Setting up network blocking rules");
for (const std::string & ip_string : node.config.blocked_peers)
{
boost::system::error_code ec;
auto ip_address = boost::asio::ip::address::from_string (ip_string, ec);

if (!ec)
{
if (ip_address.is_v4 ())
{
// Convert IPv4 address to IPv4-mapped IPv6 address
blocked_ips.insert (boost::asio::ip::address_v6::v4_mapped (ip_address.to_v4 ()));
}
else
{
blocked_ips.insert (ip_address);
}

node.logger.info (nano::log::type::tcp_listener, "Added blocking rule for ip {}", ip_address.to_string ());
}
else
{
node.logger.error (nano::log::type::tcp_listener, "Invalid IP address: {}", ip_string);
}
}
}
}

bool nano::transport::tcp_listener::is_ip_blocked (const boost::asio::ip::address & ip_address) const
{
return blocked_ips.find (ip_address) != blocked_ips.end ();
}

// If we are unable to accept a socket, for any reason, we wait just a little (1ms) before rescheduling the next connection accept.
// The intention is to throttle back the connection requests and break up any busy loops that could possibly form and
// give the rest of the system a chance to recover.
Expand Down
4 changes: 4 additions & 0 deletions nano/node/transport/tcp_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <nano/node/transport/socket.hpp>

#include <atomic>
#include <unordered_set>

namespace nano
{
Expand Down Expand Up @@ -35,6 +36,7 @@ class tcp_listener final : public std::enable_shared_from_this<nano::transport::
bool on{ false };
std::atomic<std::size_t> bootstrap_count{ 0 };
std::atomic<std::size_t> realtime_count{ 0 };
std::unordered_set<boost::asio::ip::address> blocked_ips;

private:
boost::asio::strand<boost::asio::io_context::executor_type> strand;
Expand All @@ -48,6 +50,8 @@ class tcp_listener final : public std::enable_shared_from_this<nano::transport::
/** Checks whether the maximum number of connections per IP was reached. If so, it returns true. */
bool limit_reached_for_incoming_ip_connections (std::shared_ptr<nano::transport::socket> const & new_connection);
bool limit_reached_for_incoming_subnetwork_connections (std::shared_ptr<nano::transport::socket> const & new_connection);
void configure_blocked_peers ();
bool is_ip_blocked (const boost::asio::ip::address & ip_address) const;
};

std::unique_ptr<container_info_component> collect_container_info (tcp_listener & bootstrap_listener, std::string const & name);
Expand Down

0 comments on commit 0db8f91

Please sign in to comment.