diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptonote_config.h | 2 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.h | 2 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.inl | 7 | ||||
-rw-r--r-- | src/daemon/command_parser_executor.cpp | 42 | ||||
-rw-r--r-- | src/daemon/command_server.cpp | 4 | ||||
-rw-r--r-- | src/p2p/net_node.cpp | 1 | ||||
-rw-r--r-- | src/p2p/net_node.h | 7 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 64 | ||||
-rw-r--r-- | src/p2p/net_node_common.h | 4 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 1 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 4 |
11 files changed, 127 insertions, 11 deletions
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 21f2bf81e..97706f745 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -197,6 +197,8 @@ #define RPC_CREDITS_PER_HASH_SCALE ((float)(1<<24)) +#define DNS_BLOCKLIST_LIFETIME (86400 * 8) + // New constants are intended to go here namespace config { diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index b416b86c8..0599c69f9 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -116,6 +116,8 @@ namespace cryptonote std::string get_peers_overview() const; std::pair<uint32_t, uint32_t> get_next_needed_pruning_stripe() const; bool needs_new_sync_connections() const; + bool is_busy_syncing(); + private: //----------------- commands handlers ---------------------------------------------- int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& context); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index c36cdeb82..15734cf29 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -2770,6 +2770,13 @@ skip: } //------------------------------------------------------------------------------------------------------------------------ template<class t_core> + bool t_cryptonote_protocol_handler<t_core>::is_busy_syncing() + { + const boost::unique_lock<boost::mutex> sync{m_sync_lock, boost::try_to_lock}; + return !sync.owns_lock(); + } + //------------------------------------------------------------------------------------------------------------------------ + template<class t_core> 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 " << diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 504b104b0..6695c3ecd 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -28,6 +28,7 @@ #include "common/dns_utils.h" #include "common/command_line.h" +#include "net/parse.h" #include "daemon/command_parser_executor.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -585,7 +586,6 @@ bool t_command_parser_executor::show_bans(const std::vector<std::string>& args) bool t_command_parser_executor::ban(const std::vector<std::string>& args) { if (args.size() != 1 && args.size() != 2) return false; - std::string ip = args[0]; time_t seconds = P2P_IP_BLOCKTIME; if (args.size() > 1) { @@ -602,7 +602,45 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args) return false; } } - return m_executor.ban(ip, seconds); + if (boost::starts_with(args[0], "@")) + { + const std::string ban_list = args[0].substr(1); + + try + { + const boost::filesystem::path ban_list_path(ban_list); + boost::system::error_code ec; + if (!boost::filesystem::exists(ban_list_path, ec)) + { + std::cout << "Can't find ban list file " + ban_list + " - " + ec.message() << std::endl; + return true; + } + + bool ret = true; + std::ifstream ifs(ban_list_path.string()); + for (std::string line; std::getline(ifs, line); ) + { + const expect<epee::net_utils::network_address> parsed_addr = net::get_network_address(line, 0); + if (!parsed_addr) + { + std::cout << "Invalid IP address: " << line << " - " << parsed_addr.error() << std::endl; + continue; + } + ret &= m_executor.ban(parsed_addr->host_str(), seconds); + } + return ret; + } + catch (const std::exception &e) + { + std::cout << "Error loading ban list: " << e.what() << std::endl; + return false; + } + } + else + { + const std::string ip = args[0]; + return m_executor.ban(ip, seconds); + } } bool t_command_parser_executor::unban(const std::vector<std::string>& args) diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index ac4c30726..46d96bda4 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -233,8 +233,8 @@ t_command_server::t_command_server( m_command_lookup.set_handler( "ban" , std::bind(&t_command_parser_executor::ban, &m_parser, p::_1) - , "ban <IP> [<seconds>]" - , "Ban a given <IP> for a given amount of <seconds>." + , "ban [<IP>|@<filename>] [<seconds>]" + , "Ban a given <IP> or list of IPs from a file for a given amount of <seconds>." ); m_command_lookup.set_handler( "unban" diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index aee1fa593..8dd551d1e 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -149,6 +149,7 @@ namespace nodetool const command_line::arg_descriptor<std::string> arg_ban_list = {"ban-list", "Specify ban list file, one IP address per line"}; const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true}; const command_line::arg_descriptor<bool> arg_no_sync = {"no-sync", "Don't synchronize the blockchain with other peers", false}; + const command_line::arg_descriptor<bool> arg_enable_dns_blocklist = {"enable-dns-blocklist", "Apply realtime blocklist from DNS", false}; const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"}; const command_line::arg_descriptor<std::string> arg_igd = {"igd", "UPnP port mapping (disabled, enabled, delayed)", "delayed"}; diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index f13b36a82..9fba5d636 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -287,7 +287,7 @@ namespace nodetool uint32_t get_max_out_public_peers() const; void change_max_in_public_peers(size_t count); uint32_t get_max_in_public_peers() const; - virtual bool block_host(epee::net_utils::network_address address, time_t seconds = P2P_IP_BLOCKTIME); + virtual bool block_host(epee::net_utils::network_address address, time_t seconds = P2P_IP_BLOCKTIME, bool add_only = false); virtual bool unblock_host(const epee::net_utils::network_address &address); virtual bool block_subnet(const epee::net_utils::ipv4_network_subnet &subnet, time_t seconds = P2P_IP_BLOCKTIME); virtual bool unblock_subnet(const epee::net_utils::ipv4_network_subnet &subnet); @@ -369,6 +369,7 @@ namespace nodetool bool peer_sync_idle_maker(); bool do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context, bool just_take_peerlist = false); bool do_peer_timed_sync(const epee::net_utils::connection_context_base& context, peerid_type peer_id); + bool update_dns_blocklist(); bool make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist); bool make_new_connection_from_peerlist(network_zone& zone, bool use_white_list); @@ -474,6 +475,7 @@ namespace nodetool epee::math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval; epee::math_helper::once_a_time_seconds<60> m_gray_peerlist_housekeeping_interval; epee::math_helper::once_a_time_seconds<3600, false> m_incoming_connections_interval; + epee::math_helper::once_a_time_seconds<7000> m_dns_blocklist_interval; std::list<epee::net_utils::network_address> m_priority_peers; std::vector<epee::net_utils::network_address> m_exclusive_peers; @@ -512,6 +514,8 @@ namespace nodetool cryptonote::network_type m_nettype; epee::net_utils::ssl_support_t m_ssl_support; + + bool m_enable_dns_blocklist; }; const int64_t default_limit_up = P2P_DEFAULT_LIMIT_RATE_UP; // kB/s @@ -533,6 +537,7 @@ namespace nodetool extern const command_line::arg_descriptor<std::string> arg_ban_list; extern const command_line::arg_descriptor<bool> arg_p2p_hide_my_port; extern const command_line::arg_descriptor<bool> arg_no_sync; + extern const command_line::arg_descriptor<bool> arg_enable_dns_blocklist; extern const command_line::arg_descriptor<bool> arg_no_igd; extern const command_line::arg_descriptor<std::string> arg_igd; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 65db2615c..03ab04b21 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -37,6 +37,7 @@ #include <boost/optional/optional.hpp> #include <boost/thread/thread.hpp> #include <boost/uuid/uuid_io.hpp> +#include <boost/algorithm/string.hpp> #include <atomic> #include <functional> #include <limits> @@ -120,6 +121,7 @@ namespace nodetool command_line::add_arg(desc, arg_ban_list); command_line::add_arg(desc, arg_p2p_hide_my_port); command_line::add_arg(desc, arg_no_sync); + command_line::add_arg(desc, arg_enable_dns_blocklist); command_line::add_arg(desc, arg_no_igd); command_line::add_arg(desc, arg_igd); command_line::add_arg(desc, arg_out_peers); @@ -226,7 +228,7 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::block_host(epee::net_utils::network_address addr, time_t seconds) + bool node_server<t_payload_net_handler>::block_host(epee::net_utils::network_address addr, time_t seconds, bool add_only) { if(!addr.is_blockable()) return false; @@ -240,7 +242,11 @@ namespace nodetool else limit = now + seconds; const std::string host_str = addr.host_str(); - m_blocked_hosts[host_str] = limit; + auto it = m_blocked_hosts.find(host_str); + if (it == m_blocked_hosts.end()) + m_blocked_hosts[host_str] = limit; + else if (it->second < limit || !add_only) + it->second = limit; // drop any connection to that address. This should only have to look into // the zone related to the connection, but really make sure everything is @@ -260,6 +266,8 @@ namespace nodetool peerlist_entry pe{}; pe.adr = addr; zone.second.m_peerlist.remove_from_peer_white(pe); + zone.second.m_peerlist.remove_from_peer_gray(pe); + zone.second.m_peerlist.remove_from_peer_anchor(addr); for (const auto &c: conns) zone.second.m_net_server.get_config_object().close(c); @@ -497,6 +505,8 @@ namespace nodetool if (command_line::has_arg(vm, arg_no_sync)) m_payload_handler.set_no_sync(true); + m_enable_dns_blocklist = command_line::get_arg(vm, arg_enable_dns_blocklist); + if ( !set_max_out_peers(public_zone, command_line::get_arg(vm, arg_out_peers) ) ) return false; else @@ -1971,6 +1981,52 @@ namespace nodetool m_gray_peerlist_housekeeping_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::gray_peerlist_housekeeping, this)); m_peerlist_store_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::store_config, this)); m_incoming_connections_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::check_incoming_connections, this)); + m_dns_blocklist_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::update_dns_blocklist, this)); + return true; + } + //----------------------------------------------------------------------------------- + template<class t_payload_net_handler> + bool node_server<t_payload_net_handler>::update_dns_blocklist() + { + if (!m_enable_dns_blocklist) + return true; + if (m_nettype != cryptonote::MAINNET) + return true; + + static const std::vector<std::string> dns_urls = { + "blocklist.moneropulse.se" + , "blocklist.moneropulse.org" + , "blocklist.moneropulse.net" + , "blocklist.moneropulse.no" + , "blocklist.moneropulse.fr" + , "blocklist.moneropulse.de" + , "blocklist.moneropulse.ch" + }; + + std::vector<std::string> records; + if (!tools::dns_utils::load_txt_records_from_dns(records, dns_urls)) + return true; + + unsigned good = 0, bad = 0; + for (const auto& record : records) + { + std::vector<std::string> ips; + boost::split(ips, record, boost::is_any_of(";")); + for (const auto &ip: ips) + { + const expect<epee::net_utils::network_address> parsed_addr = net::get_network_address(ip, 0); + if (!parsed_addr) + { + MWARNING("Invalid IP address from DNS blocklist: " << ip << " - " << parsed_addr.error()); + ++bad; + continue; + } + block_host(*parsed_addr, DNS_BLOCKLIST_LIFETIME, true); + ++good; + } + } + if (good > 0) + MINFO(good << " addresses added to the blocklist"); return true; } //----------------------------------------------------------------------------------- @@ -2093,7 +2149,9 @@ namespace nodetool LOG_DEBUG_CC(context, "REMOTE PEERLIST: remote peerlist size=" << peerlist_.size()); LOG_TRACE_CC(context, "REMOTE PEERLIST: " << ENDL << print_peerlist_to_string(peerlist_)); - return m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.merge_peerlist(peerlist_, [this](const peerlist_entry &pe) { return !is_addr_recently_failed(pe.adr); }); + return m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.merge_peerlist(peerlist_, [this](const peerlist_entry &pe) { + return !is_addr_recently_failed(pe.adr) && is_remote_host_allowed(pe.adr); + }); } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h index f1490a0db..0da758ad4 100644 --- a/src/p2p/net_node_common.h +++ b/src/p2p/net_node_common.h @@ -58,7 +58,7 @@ namespace nodetool virtual uint64_t get_public_connections_count()=0; virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0; virtual bool for_connection(const boost::uuids::uuid&, std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0; - virtual bool block_host(epee::net_utils::network_address address, time_t seconds = 0)=0; + virtual bool block_host(epee::net_utils::network_address address, time_t seconds = 0, bool add_only = false)=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<epee::net_utils::ipv4_network_subnet, time_t> get_blocked_subnets()=0; @@ -108,7 +108,7 @@ namespace nodetool { return false; } - virtual bool block_host(epee::net_utils::network_address address, time_t seconds) + virtual bool block_host(epee::net_utils::network_address address, time_t seconds, bool add_only) { return true; } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index f7d5bf03c..e6ad93312 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -498,6 +498,7 @@ namespace cryptonote res.database_size = round_up(res.database_size, 5ull* 1024 * 1024 * 1024); res.update_available = restricted ? false : m_core.is_update_available(); res.version = restricted ? "" : MONERO_VERSION_FULL; + res.busy_syncing = m_p2p.get_payload_object().is_busy_syncing(); res.status = CORE_RPC_STATUS_OK; return true; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 8748b0540..21e981eae 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -88,7 +88,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 3 -#define CORE_RPC_VERSION_MINOR 2 +#define CORE_RPC_VERSION_MINOR 4 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -684,6 +684,7 @@ namespace cryptonote bool was_bootstrap_ever_used; uint64_t database_size; bool update_available; + bool busy_syncing; std::string version; BEGIN_KV_SERIALIZE_MAP() @@ -723,6 +724,7 @@ namespace cryptonote KV_SERIALIZE(was_bootstrap_ever_used) KV_SERIALIZE(database_size) KV_SERIALIZE(update_available) + KV_SERIALIZE(busy_syncing) KV_SERIALIZE(version) END_KV_SERIALIZE_MAP() }; |