From 3455efafa812d646f2eea42db14b761f34975147 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 24 Sep 2019 13:08:25 +0000 Subject: [PATCH] ban peers sending bad pow outright PoW is expensive to verify, so be strict --- src/cryptonote_basic/verification_context.h | 1 + src/cryptonote_core/blockchain.cpp | 2 ++ .../cryptonote_protocol_handler.h | 1 + .../cryptonote_protocol_handler.inl | 20 ++++++++++++------- src/p2p/net_node.h | 2 +- src/p2p/net_node.inl | 4 ++-- src/p2p/net_node_common.h | 4 ++-- src/rpc/core_rpc_server.cpp | 4 ++-- src/rpc/core_rpc_server.h | 2 +- 9 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/cryptonote_basic/verification_context.h b/src/cryptonote_basic/verification_context.h index 3d7200fae..f5f663464 100644 --- a/src/cryptonote_basic/verification_context.h +++ b/src/cryptonote_basic/verification_context.h @@ -58,5 +58,6 @@ namespace cryptonote bool m_marked_as_orphaned; bool m_already_exists; bool m_partial_block_reward; + bool m_bad_pow; // if bad pow, bad peer outright for DoS protection }; } diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 5cf4952ae..584dfbe71 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1689,6 +1689,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id { MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff); bvc.m_verifivation_failed = true; + bvc.m_bad_pow = true; return false; } @@ -3620,6 +3621,7 @@ leave: { MERROR_VER("Block with id: " << id << std::endl << "does not have enough proof of work: " << proof_of_work << " at height " << blockchain_height << ", unexpected difficulty: " << current_diffic); bvc.m_verifivation_failed = true; + bvc.m_bad_pow = true; goto leave; } } diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index dcc5ec6ed..6501b2425 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -138,6 +138,7 @@ namespace cryptonote bool on_connection_synchronized(); bool should_download_next_span(cryptonote_connection_context& context, bool standby); void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans); + void drop_connection_with_score(cryptonote_connection_context &context, unsigned int score, bool flush_all_spans); bool kick_idle_peers(); bool check_standby_peers(); bool update_sync_search(); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 82f9f96a0..32f5c81ec 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -475,7 +475,7 @@ namespace cryptonote if(bvc.m_verifivation_failed) { LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection"); - drop_connection(context, true, false); + drop_connection_with_score(context, bvc.m_bad_pow ? P2P_IP_FAILS_BEFORE_BLOCK : 1, false); return 1; } if(bvc.m_added_to_main_chain) @@ -748,7 +748,7 @@ namespace cryptonote if( bvc.m_verifivation_failed ) { LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection"); - drop_connection(context, true, false); + drop_connection_with_score(context, bvc.m_bad_pow ? P2P_IP_FAILS_BEFORE_BLOCK : 1, false); return 1; } if( bvc.m_added_to_main_chain ) @@ -1309,7 +1309,7 @@ namespace cryptonote { if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{ LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection"); - drop_connection(context, true, true); + drop_connection_with_score(context, bvc.m_bad_pow ? P2P_IP_FAILS_BEFORE_BLOCK : 1, true); return 1; })) LOG_ERROR_CCONTEXT("span connection id not found"); @@ -2305,14 +2305,14 @@ skip: } //------------------------------------------------------------------------------------------------------------------------ template - void t_cryptonote_protocol_handler::drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans) + void t_cryptonote_protocol_handler::drop_connection_with_score(cryptonote_connection_context &context, unsigned score, bool flush_all_spans) { LOG_DEBUG_CC(context, "dropping connection id " << context.m_connection_id << " (pruning seed " << epee::string_tools::to_string_hex(context.m_pruning_seed) << - "), add_fail " << add_fail << ", flush_all_spans " << flush_all_spans); + "), score " << score << ", flush_all_spans " << flush_all_spans); - if (add_fail) - m_p2p->add_host_fail(context.m_remote_address); + if (score > 0) + m_p2p->add_host_fail(context.m_remote_address, score); m_block_queue.flush_spans(context.m_connection_id, flush_all_spans); @@ -2320,6 +2320,12 @@ skip: } //------------------------------------------------------------------------------------------------------------------------ template + void t_cryptonote_protocol_handler::drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans) + { + return drop_connection_with_score(context, add_fail ? 1 : 0, flush_all_spans); + } + //------------------------------------------------------------------------------------------------------------------------ + template void t_cryptonote_protocol_handler::on_connection_close(cryptonote_connection_context &context) { uint64_t target = 0; diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index d7e2e91f5..3a5d980ab 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -342,7 +342,7 @@ namespace nodetool virtual void request_callback(const epee::net_utils::connection_context_base& context); virtual void for_each_connection(std::function f); virtual bool for_connection(const boost::uuids::uuid&, std::function f); - virtual bool add_host_fail(const epee::net_utils::network_address &address); + virtual bool add_host_fail(const epee::net_utils::network_address &address, unsigned int score = 1); //----------------- i_connection_filter -------------------------------------------------------- virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address, time_t *t = NULL); //----------------------------------------------------------------------------------------------- diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 24c87cef8..e8e19905a 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -315,13 +315,13 @@ namespace nodetool } //----------------------------------------------------------------------------------- template - bool node_server::add_host_fail(const epee::net_utils::network_address &address) + bool node_server::add_host_fail(const epee::net_utils::network_address &address, unsigned int score) { if(!address.is_blockable()) return false; CRITICAL_REGION_LOCAL(m_host_fails_score_lock); - uint64_t fails = ++m_host_fails_score[address.host_str()]; + uint64_t fails = m_host_fails_score[address.host_str()] += score; MDEBUG("Host " << address.host_str() << " fail score=" << fails); if(fails > P2P_IP_FAILS_BEFORE_BLOCK) { diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h index e0046cd86..752873666 100644 --- a/src/p2p/net_node_common.h +++ b/src/p2p/net_node_common.h @@ -60,7 +60,7 @@ namespace nodetool virtual bool unblock_host(const epee::net_utils::network_address &address)=0; virtual std::map get_blocked_hosts()=0; virtual std::map get_blocked_subnets()=0; - virtual bool add_host_fail(const epee::net_utils::network_address &address)=0; + virtual bool add_host_fail(const epee::net_utils::network_address &address, unsigned int score = 1)=0; virtual void add_used_stripe_peer(const t_connection_context &context)=0; virtual void remove_used_stripe_peer(const t_connection_context &context)=0; virtual void clear_used_stripe_peers()=0; @@ -122,7 +122,7 @@ namespace nodetool { return std::map(); } - virtual bool add_host_fail(const epee::net_utils::network_address &address) + virtual bool add_host_fail(const epee::net_utils::network_address &address, unsigned int score) { return true; } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 3f53d59cf..ac8e0784f 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -217,13 +217,13 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::add_host_fail(const connection_context *ctx) + bool core_rpc_server::add_host_fail(const connection_context *ctx, unsigned int score) { if(!ctx || !ctx->m_remote_address.is_blockable()) return false; CRITICAL_REGION_LOCAL(m_host_fails_score_lock); - uint64_t fails = ++m_host_fails_score[ctx->m_remote_address.host_str()]; + uint64_t fails = m_host_fails_score[ctx->m_remote_address.host_str()] += score; MDEBUG("Host " << ctx->m_remote_address.host_str() << " fail score=" << fails); if(fails > RPC_IP_FAILS_BEFORE_BLOCK) { diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 379f6ed28..fe03012b7 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -241,7 +241,7 @@ namespace cryptonote private: bool check_core_busy(); bool check_core_ready(); - bool add_host_fail(const connection_context *ctx); + bool add_host_fail(const connection_context *ctx, unsigned int score = 1); //utils uint64_t get_block_reward(const block& blk);