diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl index ae8e43477..790d0f3b1 100644 --- a/contrib/epee/include/net/http_protocol_handler.inl +++ b/contrib/epee/include/net/http_protocol_handler.inl @@ -577,6 +577,10 @@ namespace net_utils if (query_info.m_http_method != http::http_method_options) { res = handle_request(query_info, response); + if (response.m_response_code == 500) + { + m_want_close = true; // close on all "Internal server error"s + } } else { diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h index 4b2053091..07ed8157b 100644 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -71,7 +71,7 @@ MINFO(m_conn_context << "calling " << s_pattern); \ if(!callback_f(static_cast(req), static_cast(resp), &m_conn_context)) \ { \ - LOG_ERROR("Failed to " << #callback_f << "()"); \ + MERROR(m_conn_context << "Failed to " << #callback_f << "()"); \ response_info.m_response_code = 500; \ response_info.m_response_comment = "Internal Server Error"; \ return true; \ @@ -99,7 +99,7 @@ MINFO(m_conn_context << "calling " << s_pattern); \ if(!callback_f(static_cast(req), static_cast(resp), &m_conn_context)) \ { \ - LOG_ERROR("Failed to " << #callback_f << "()"); \ + MERROR(m_conn_context << "Failed to " << #callback_f << "()"); \ response_info.m_response_code = 500; \ response_info.m_response_comment = "Internal Server Error"; \ return true; \ diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 56b6a63b7..678148942 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -128,6 +128,8 @@ #define P2P_SUPPORT_FLAG_FLUFFY_BLOCKS 0x01 #define P2P_SUPPORT_FLAGS P2P_SUPPORT_FLAG_FLUFFY_BLOCKS +#define RPC_IP_FAILS_BEFORE_BLOCK 3 + #define ALLOW_DEBUG_COMMANDS #define CRYPTONOTE_NAME "bitmonero" diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 3db138719..3d9c58eb0 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -113,6 +113,7 @@ namespace cryptonote { m_restricted = restricted; m_net_server.set_threads_prefix("RPC"); + m_net_server.set_connection_filter(&m_p2p); auto rpc_config = cryptonote::rpc_args::process(vm, true); if (!rpc_config) @@ -161,6 +162,24 @@ namespace cryptonote } return true; } + //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::add_host_fail(const connection_context *ctx) + { + 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()]; + MDEBUG("Host " << ctx->m_remote_address.host_str() << " fail score=" << fails); + if(fails > RPC_IP_FAILS_BEFORE_BLOCK) + { + auto it = m_host_fails_score.find(ctx->m_remote_address.host_str()); + CHECK_AND_ASSERT_MES(it != m_host_fails_score.end(), false, "internal error"); + it->second = RPC_IP_FAILS_BEFORE_BLOCK/2; + m_p2p.block_host(ctx->m_remote_address); + } + return true; + } #define CHECK_CORE_READY() do { if(!check_core_ready()){res.status = CORE_RPC_STATUS_BUSY;return true;} } while(0) //------------------------------------------------------------------------------------------------------------------------------ @@ -282,6 +301,7 @@ namespace cryptonote if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, req.prune, !req.no_miner_tx, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) { res.status = "Failed"; + add_host_fail(ctx); return false; } @@ -405,6 +425,7 @@ namespace cryptonote if(!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, res.m_block_ids, res.start_height, res.current_height, false)) { res.status = "Failed"; + add_host_fail(ctx); return false; } diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index e4683bbe2..328e62dfa 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -236,6 +236,7 @@ namespace cryptonote private: bool check_core_busy(); bool check_core_ready(); + bool add_host_fail(const connection_context *ctx); //utils uint64_t get_block_reward(const block& blk); @@ -254,6 +255,8 @@ private: bool m_was_bootstrap_ever_used; network_type m_nettype; bool m_restricted; + epee::critical_section m_host_fails_score_lock; + std::map m_host_fails_score; }; }