ban peers sending bad pow outright

PoW is expensive to verify, so be strict
This commit is contained in:
moneromooo-monero 2019-09-24 13:08:25 +00:00
parent faf5805fc0
commit 3455efafa8
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
9 changed files with 25 additions and 15 deletions

View file

@ -58,5 +58,6 @@ namespace cryptonote
bool m_marked_as_orphaned; bool m_marked_as_orphaned;
bool m_already_exists; bool m_already_exists;
bool m_partial_block_reward; bool m_partial_block_reward;
bool m_bad_pow; // if bad pow, bad peer outright for DoS protection
}; };
} }

View file

@ -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); 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_verifivation_failed = true;
bvc.m_bad_pow = true;
return false; 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); 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_verifivation_failed = true;
bvc.m_bad_pow = true;
goto leave; goto leave;
} }
} }

View file

@ -138,6 +138,7 @@ namespace cryptonote
bool on_connection_synchronized(); bool on_connection_synchronized();
bool should_download_next_span(cryptonote_connection_context& context, bool standby); 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(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 kick_idle_peers();
bool check_standby_peers(); bool check_standby_peers();
bool update_sync_search(); bool update_sync_search();

View file

@ -475,7 +475,7 @@ namespace cryptonote
if(bvc.m_verifivation_failed) if(bvc.m_verifivation_failed)
{ {
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection"); 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; return 1;
} }
if(bvc.m_added_to_main_chain) if(bvc.m_added_to_main_chain)
@ -748,7 +748,7 @@ namespace cryptonote
if( bvc.m_verifivation_failed ) if( bvc.m_verifivation_failed )
{ {
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection"); 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; return 1;
} }
if( bvc.m_added_to_main_chain ) 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{ 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"); 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; return 1;
})) }))
LOG_ERROR_CCONTEXT("span connection id not found"); LOG_ERROR_CCONTEXT("span connection id not found");
@ -2305,14 +2305,14 @@ skip:
} }
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
template<class t_core> template<class t_core>
void t_cryptonote_protocol_handler<t_core>::drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans) void t_cryptonote_protocol_handler<t_core>::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 " << LOG_DEBUG_CC(context, "dropping connection id " << context.m_connection_id << " (pruning seed " <<
epee::string_tools::to_string_hex(context.m_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) if (score > 0)
m_p2p->add_host_fail(context.m_remote_address); m_p2p->add_host_fail(context.m_remote_address, score);
m_block_queue.flush_spans(context.m_connection_id, flush_all_spans); m_block_queue.flush_spans(context.m_connection_id, flush_all_spans);
@ -2320,6 +2320,12 @@ skip:
} }
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
template<class t_core> template<class t_core>
void t_cryptonote_protocol_handler<t_core>::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<class t_core>
void t_cryptonote_protocol_handler<t_core>::on_connection_close(cryptonote_connection_context &context) void t_cryptonote_protocol_handler<t_core>::on_connection_close(cryptonote_connection_context &context)
{ {
uint64_t target = 0; uint64_t target = 0;

View file

@ -342,7 +342,7 @@ namespace nodetool
virtual void request_callback(const epee::net_utils::connection_context_base& context); virtual void request_callback(const epee::net_utils::connection_context_base& context);
virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f); virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f);
virtual bool for_connection(const boost::uuids::uuid&, std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f); virtual bool for_connection(const boost::uuids::uuid&, std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> 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 -------------------------------------------------------- //----------------- i_connection_filter --------------------------------------------------------
virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address, time_t *t = NULL); virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address, time_t *t = NULL);
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------

View file

@ -315,13 +315,13 @@ namespace nodetool
} }
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
template<class t_payload_net_handler> template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::add_host_fail(const epee::net_utils::network_address &address) bool node_server<t_payload_net_handler>::add_host_fail(const epee::net_utils::network_address &address, unsigned int score)
{ {
if(!address.is_blockable()) if(!address.is_blockable())
return false; return false;
CRITICAL_REGION_LOCAL(m_host_fails_score_lock); 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); MDEBUG("Host " << address.host_str() << " fail score=" << fails);
if(fails > P2P_IP_FAILS_BEFORE_BLOCK) if(fails > P2P_IP_FAILS_BEFORE_BLOCK)
{ {

View file

@ -60,7 +60,7 @@ namespace nodetool
virtual bool unblock_host(const epee::net_utils::network_address &address)=0; virtual bool unblock_host(const epee::net_utils::network_address &address)=0;
virtual std::map<std::string, time_t> get_blocked_hosts()=0; virtual std::map<std::string, time_t> get_blocked_hosts()=0;
virtual std::map<epee::net_utils::ipv4_network_subnet, time_t> get_blocked_subnets()=0; virtual std::map<epee::net_utils::ipv4_network_subnet, time_t> 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 add_used_stripe_peer(const t_connection_context &context)=0;
virtual void remove_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; virtual void clear_used_stripe_peers()=0;
@ -122,7 +122,7 @@ namespace nodetool
{ {
return std::map<epee::net_utils::ipv4_network_subnet, time_t>(); return std::map<epee::net_utils::ipv4_network_subnet, time_t>();
} }
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; return true;
} }

View file

@ -217,13 +217,13 @@ namespace cryptonote
return true; 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()) if(!ctx || !ctx->m_remote_address.is_blockable())
return false; return false;
CRITICAL_REGION_LOCAL(m_host_fails_score_lock); 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); MDEBUG("Host " << ctx->m_remote_address.host_str() << " fail score=" << fails);
if(fails > RPC_IP_FAILS_BEFORE_BLOCK) if(fails > RPC_IP_FAILS_BEFORE_BLOCK)
{ {

View file

@ -241,7 +241,7 @@ namespace cryptonote
private: private:
bool check_core_busy(); bool check_core_busy();
bool check_core_ready(); 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 //utils
uint64_t get_block_reward(const block& blk); uint64_t get_block_reward(const block& blk);