Merge pull request #14 from iamsmooth/master

IP banning
This commit is contained in:
aeonix
2015-08-06 21:11:34 -07:00
7 changed files with 126 additions and 7 deletions
@@ -633,9 +633,7 @@ POP_WARNINGS
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept, this,
boost::asio::placeholders::error));
bool r = conn->start(true, 1 < m_threads_count);
if (!r)
LOG_ERROR("[sock " << conn->socket().native_handle() << "] Failed to start connection, connections_count = " << m_sockets_count);
conn->start(true, 1 < m_threads_count);
}else
{
LOG_ERROR("Some problems at accept: " << e.message() << ", connections_count = " << m_sockets_count);
+5
View File
@@ -106,6 +106,11 @@
#define P2P_STAT_TRUSTED_PUB_KEY ""
#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70
#define P2P_FAILED_ADDR_FORGET_SECONDS (60*60) //1 hour
#define P2P_IP_BLOCKTIME (60*60*24) //24 hour
#define P2P_IP_FAILS_BEFOR_BLOCK 10
#define P2P_IDLE_CONNECTION_KILL_INTERVAL (5*60) //5 minutes
#define ALLOW_DEBUG_COMMANDS
#define CRYPTONOTE_NAME "aeon"
@@ -332,6 +332,7 @@ namespace cryptonote
LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n"
<< epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection");
m_p2p->drop_connection(context);
m_p2p->add_ip_fail(context.m_remote_ip);
return 1;
}
//to avoid concurrency in core between connections, suspend connections which delivered block later then first one
@@ -407,12 +408,14 @@ namespace cryptonote
{
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection");
m_p2p->drop_connection(context);
m_p2p->add_ip_fail(context.m_remote_ip);
return 1;
}
if(bvc.m_marked_as_orphaned)
{
LOG_PRINT_CCONTEXT_L0("Block received at sync phase was marked as orphaned, dropping connection");
m_p2p->drop_connection(context);
m_p2p->add_ip_fail(context.m_remote_ip);
return 1;
}
@@ -534,6 +537,7 @@ namespace cryptonote
{
LOG_ERROR_CCONTEXT("sent empty m_block_ids, dropping connection");
m_p2p->drop_connection(context);
m_p2p->add_ip_fail(context.m_remote_ip);
return 1;
}
@@ -542,6 +546,7 @@ namespace cryptonote
LOG_ERROR_CCONTEXT("sent m_block_ids starting from unknown id: "
<< epee::string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection");
m_p2p->drop_connection(context);
m_p2p->add_ip_fail(context.m_remote_ip);
return 1;
}
+34 -1
View File
@@ -41,6 +41,7 @@
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/map.hpp>
#include "warnings.h"
#include "net/levin_server_cp2.h"
@@ -55,6 +56,7 @@
PUSH_WARNINGS
DISABLE_VS_WARNINGS(4355)
namespace nodetool
{
template<class base_type>
@@ -65,7 +67,8 @@ namespace nodetool
template<class t_payload_net_handler>
class node_server: public epee::levin::levin_commands_handler<p2p_connection_context_t<typename t_payload_net_handler::connection_context> >,
public i_p2p_endpoint<typename t_payload_net_handler::connection_context>
public i_p2p_endpoint<typename t_payload_net_handler::connection_context>,
public epee::net_utils::i_connection_filter
{
struct by_conn_id{};
struct by_peer_id{};
@@ -94,8 +97,23 @@ namespace nodetool
template <class Archive, class t_version_type>
void serialize(Archive &a, const t_version_type ver)
{
#if 0
{
time_t current_time = time(nullptr);
time_t archive_time = current_time;
a & archive_time;
if(archive_time > current_time)
{
LOG_PRINT_L0("p2p network state file has future time, skipped");
return;
}
}
#endif
a & m_peerlist;
a & m_config.m_peer_id;
#if 0
a & m_blocked_ips;
#endif
}
// debug functions
bool log_peerlist();
@@ -147,6 +165,10 @@ namespace nodetool
virtual bool drop_connection(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)> f);
virtual bool block_ip(uint32_t adress);
virtual bool add_ip_fail(uint32_t address);
//----------------- i_connection_filter --------------------------------------------------------
virtual bool is_remote_ip_allowed(uint32_t adress);
//-----------------------------------------------------------------------------------------------
bool parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr);
bool handle_command_line(const boost::program_options::variables_map& vm);
@@ -171,6 +193,8 @@ namespace nodetool
template<class t_callback>
bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb);
bool make_expected_connections_count(bool white_list, size_t expected_connections);
void cache_connect_fail_info(const net_address& addr);
bool is_addr_recently_failed(const net_address& addr);
bool is_priority_node(const net_address& na);
template <class Container>
@@ -229,6 +253,15 @@ namespace nodetool
uint64_t m_peer_livetime;
//keep connections to initiate some interactions
net_server m_net_server;
std::map<net_address, time_t> m_conn_fails_cache;
epee::critical_section m_conn_fails_cache_lock;
epee::critical_section m_blocked_ips_lock;
std::map<uint32_t, time_t> m_blocked_ips;
epee::critical_section m_ip_fails_score_lock;
std::map<uint32_t, uint64_t> m_ip_fails_score;
};
}
+69 -1
View File
@@ -28,6 +28,8 @@
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
// IP blocking adapted from Boolberry
#pragma once
#include <algorithm>
@@ -118,6 +120,22 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::is_remote_ip_allowed(uint32_t addr)
{
CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
auto it = m_blocked_ips.find(addr);
if(it == m_blocked_ips.end())
return true;
if(time(nullptr) - it->second > P2P_IP_BLOCKTIME )
{
m_blocked_ips.erase(it);
LOG_PRINT_CYAN("Ip " << epee::string_tools::get_ip_string_from_int32(addr) << "is unblocked.", LOG_LEVEL_0);
return true;
}
return false;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::make_default_config()
{
m_config.m_peer_id = crypto::rand<uint64_t>();
@@ -125,6 +143,31 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::block_ip(uint32_t addr)
{
CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
m_blocked_ips[addr] = time(nullptr);
LOG_PRINT_CYAN("Ip " << epee::string_tools::get_ip_string_from_int32(addr) << " blocked.", LOG_LEVEL_0);
return true;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::add_ip_fail(uint32_t address)
{
CRITICAL_REGION_LOCAL(m_ip_fails_score_lock);
uint64_t fails = ++m_ip_fails_score[address];
LOG_PRINT_CYAN("Ip " << epee::string_tools::get_ip_string_from_int32(address) << " fail score=" << fails, LOG_LEVEL_1);
if(fails > P2P_IP_FAILS_BEFOR_BLOCK)
{
auto it = m_ip_fails_score.find(address);
CHECK_AND_ASSERT_MES(it != m_ip_fails_score.end(), false, "internal error");
it->second = P2P_IP_FAILS_BEFOR_BLOCK/2;
block_ip(address);
}
return true;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr)
{
return epee::string_tools::parse_peer_from_string(pe.ip, pe.port, node_addr);
@@ -245,6 +288,7 @@ namespace nodetool
m_net_server.set_threads_prefix("P2P");
m_net_server.get_config_object().m_pcommands_handler = this;
m_net_server.get_config_object().m_invoke_timeout = P2P_DEFAULT_INVOKE_TIMEOUT;
m_net_server.set_connection_filter(this);
//try to bind
LOG_PRINT_L0("Binding on " << m_bind_ip << ":" << m_port);
@@ -403,6 +447,7 @@ namespace nodetool
if(!handle_remote_peerlist(rsp.local_peerlist, rsp.node_data.local_time, context))
{
LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE: failed to handle_remote_peerlist(...), closing connection.");
add_ip_fail(context.m_remote_ip);
return;
}
hsh_result = true;
@@ -464,6 +509,7 @@ namespace nodetool
{
LOG_ERROR_CCONTEXT("COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection.");
m_net_server.get_config_object().close(context.m_connection_id );
add_ip_fail(context.m_remote_ip);
}
if(!context.m_is_income)
m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_ip, context.m_remote_port);
@@ -598,6 +644,20 @@ namespace nodetool
#undef LOG_PRINT_CC_PRIORITY_NODE
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::is_addr_recently_failed(const net_address& addr)
{
CRITICAL_REGION_LOCAL(m_conn_fails_cache_lock);
auto it = m_conn_fails_cache.find(addr);
if(it == m_conn_fails_cache.end())
return false;
if(time(NULL) - it->second > P2P_FAILED_ADDR_FORGET_SECONDS)
return false;
else
return true;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::make_new_connection_from_peerlist(bool use_white_list)
@@ -631,7 +691,13 @@ namespace nodetool
if(is_peer_used(pe))
continue;
LOG_PRINT_L1("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip)
if(!is_remote_ip_allowed(pe.adr.ip))
continue;
if(is_addr_recently_failed(pe.adr))
continue;
LOG_PRINT_L2("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip)
<< ":" << boost::lexical_cast<std::string>(pe.adr.port)
<< "[white=" << use_white_list
<< "] last_seen: " << (pe.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never"));
@@ -1029,6 +1095,7 @@ namespace nodetool
LOG_PRINT_CCONTEXT_L0("WRONG NETWORK AGENT CONNECTED! id=" << epee::string_tools::get_str_from_guid_a(arg.node_data.network_id));
drop_connection(context);
add_ip_fail(context.m_remote_ip);
return 1;
}
@@ -1036,6 +1103,7 @@ namespace nodetool
{
LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE came not from incoming connection");
drop_connection(context);
add_ip_fail(context.m_remote_ip);
return 1;
}
+10
View File
@@ -50,6 +50,8 @@ namespace nodetool
virtual void request_callback(const epee::net_utils::connection_context_base& context)=0;
virtual uint64_t get_connections_count()=0;
virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type)> f)=0;
virtual bool block_ip(uint32_t adress)=0;
virtual bool add_ip_fail(uint32_t adress)=0;
};
template<class t_connection_context>
@@ -84,5 +86,13 @@ namespace nodetool
{
return false;
}
virtual bool block_ip(uint32_t adress)
{
return true;
}
virtual bool add_ip_fail(uint32_t adress)
{
return true;
}
};
}
+2 -2
View File
@@ -52,7 +52,7 @@
#include "cryptonote_config.h"
#include "net_peerlist_boost_serialization.h"
#define CURRENT_PEERLIST_STORAGE_ARCHIVE_VER 4
namespace nodetool
{
@@ -394,4 +394,4 @@ namespace nodetool
//--------------------------------------------------------------------------------------------------
}
BOOST_CLASS_VERSION(nodetool::peerlist_manager, 4)
BOOST_CLASS_VERSION(nodetool::peerlist_manager, CURRENT_PEERLIST_STORAGE_ARCHIVE_VER)