diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index b973b99..74943fa 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -591,7 +591,7 @@ void P2PServer::load_peer_list() p.m_numFailedConnections = 0; p.m_lastSeen = seconds_since_epoch(); - if (!already_added && !is_banned(p.m_addr)) { + if (!already_added && !is_banned(p.m_isV6, p.m_addr)) { m_peerList.push_back(p); } }); @@ -661,7 +661,7 @@ void P2PServer::load_monerod_peer_list() p.m_port = port; p.m_numFailedConnections = 0; - if (!is_banned(p.m_addr)) { + if (!is_banned(p.m_isV6, p.m_addr)) { m_peerListMonero.push_back(p); } } @@ -694,7 +694,7 @@ void P2PServer::update_peer_in_list(bool is_v6, const raw_ip& ip, int port) } } - if (!is_banned(ip)) { + if (!is_banned(is_v6, ip)) { m_peerList.emplace_back(Peer{ is_v6, ip, port, 0, cur_time }); } } @@ -2237,7 +2237,7 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf) } } - if (!already_added && !server->is_banned(ip)) { + if (!already_added && !server->is_banned(is_v6, ip)) { server->m_peerList.emplace_back(Peer{ is_v6, ip, port, 0, cur_time }); } } @@ -2306,11 +2306,12 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u P2PClient* client; P2PServer* server; uint32_t client_reset_counter; + bool client_isV6; raw_ip client_ip; std::vector missing_blocks; }; - Work* work = new Work{ {}, *block, this, server, m_resetCounter.load(), m_addr, {} }; + Work* work = new Work{ {}, *block, this, server, m_resetCounter.load(), m_isV6, m_addr, {} }; work->req.data = work; const int err = uv_queue_work(&server->m_loop, &work->req, @@ -2318,7 +2319,7 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u { BACKGROUND_JOB_START(P2PServer::handle_incoming_block_async); Work* work = reinterpret_cast(req->data); - work->client->handle_incoming_block(work->server->m_pool, work->block, work->client_reset_counter, work->client_ip, work->missing_blocks); + work->client->handle_incoming_block(work->server->m_pool, work->block, work->client_reset_counter, work->client_isV6, work->client_ip, work->missing_blocks); }, [](uv_work_t* req, int /*status*/) { @@ -2337,7 +2338,7 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u return true; } -void P2PServer::P2PClient::handle_incoming_block(p2pool* pool, PoolBlock& block, const uint32_t reset_counter, const raw_ip& addr, std::vector& missing_blocks) +void P2PServer::P2PClient::handle_incoming_block(p2pool* pool, PoolBlock& block, const uint32_t reset_counter, bool is_v6, const raw_ip& addr, std::vector& missing_blocks) { if (!pool->side_chain().add_external_block(block, missing_blocks)) { // Client sent bad data, disconnect and ban it @@ -2351,7 +2352,7 @@ void P2PServer::P2PClient::handle_incoming_block(p2pool* pool, PoolBlock& block, } P2PServer* server = pool->p2p_server(); - server->ban(addr, DEFAULT_BAN_TIME); + server->ban(is_v6, addr, DEFAULT_BAN_TIME); server->remove_peer_from_list(addr); } } diff --git a/src/p2p_server.h b/src/p2p_server.h index a773567..01155bf 100644 --- a/src/p2p_server.h +++ b/src/p2p_server.h @@ -111,7 +111,7 @@ public: void on_peer_list_response(const uint8_t* buf); bool handle_incoming_block_async(const PoolBlock* block, uint64_t max_time_delta = 0); - void handle_incoming_block(p2pool* pool, PoolBlock& block, const uint32_t reset_counter, const raw_ip& addr, std::vector& missing_blocks); + void handle_incoming_block(p2pool* pool, PoolBlock& block, const uint32_t reset_counter, bool is_v6, const raw_ip& addr, std::vector& missing_blocks); void post_handle_incoming_block(const uint32_t reset_counter, std::vector& missing_blocks); bool is_good() const { return m_handshakeComplete && !m_handshakeInvalid && (m_listenPort >= 0); } diff --git a/src/stratum_server.cpp b/src/stratum_server.cpp index 1942151..9c02319 100644 --- a/src/stratum_server.cpp +++ b/src/stratum_server.cpp @@ -410,6 +410,7 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo share->m_req.data = share; share->m_server = this; share->m_client = client; + share->m_clientIPv6 = client->m_isV6; share->m_clientAddr = client->m_addr; share->m_clientResetCounter = client->m_resetCounter.load(); share->m_rpcId = client->m_rpcId; @@ -843,7 +844,7 @@ void StratumServer::on_share_found(uv_work_t* req) SubmittedShare* share = reinterpret_cast(req->data); StratumServer* server = share->m_server; - if (server->is_banned(share->m_clientAddr)) { + if (server->is_banned(share->m_clientIPv6, share->m_clientAddr)) { share->m_highEnoughDifficulty = false; share->m_result = SubmittedShare::Result::BANNED; return; @@ -1019,7 +1020,7 @@ void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/) } } else if (bad_share) { - server->ban(share->m_clientAddr, DEFAULT_BAN_TIME); + server->ban(share->m_clientIPv6, share->m_clientAddr, DEFAULT_BAN_TIME); } } diff --git a/src/stratum_server.h b/src/stratum_server.h index 98f6872..bf60611 100644 --- a/src/stratum_server.h +++ b/src/stratum_server.h @@ -142,6 +142,7 @@ private: uv_work_t m_req; StratumServer* m_server; StratumClient* m_client; + bool m_clientIPv6; raw_ip m_clientAddr; uint32_t m_clientResetCounter; uint32_t m_rpcId; diff --git a/src/tcp_server.cpp b/src/tcp_server.cpp index 495bb74..477d981 100644 --- a/src/tcp_server.cpp +++ b/src/tcp_server.cpp @@ -300,12 +300,17 @@ bool TCPServer::connect_to_peer(bool is_v6, const raw_ip& ip, int port) return connect_to_peer(client); } -bool TCPServer::is_banned(const raw_ip& ip) +bool TCPServer::is_banned(bool is_v6, raw_ip ip) { if (ip.is_localhost()) { return false; } + // If it's IPv6, check the whole /64 prefix + if (is_v6 && !ip.is_ipv4_prefix()) { + memset(ip.data + 8, 0, sizeof(ip.data) - 8); + } + const auto cur_time = std::chrono::steady_clock::now(); MutexLock lock(m_bansLock); @@ -324,7 +329,7 @@ bool TCPServer::is_banned(const raw_ip& ip) bool TCPServer::connect_to_peer(Client* client) { - if (is_banned(client->m_addr)) { + if (is_banned(client->m_isV6, client->m_addr)) { LOGINFO(5, "peer " << log::Gray() << static_cast(client->m_addrString) << log::NoColor() << " is banned, not connecting to it"); return_client(client); return false; @@ -482,12 +487,17 @@ void TCPServer::print_status() ); } -void TCPServer::ban(const raw_ip& ip, uint64_t seconds) +void TCPServer::ban(bool is_v6, raw_ip ip, uint64_t seconds) { if (ip.is_localhost()) { return; } + // If it's IPv6, ban the whole /64 prefix + if (is_v6 && !ip.is_ipv4_prefix()) { + memset(ip.data + 8, 0, sizeof(ip.data) - 8); + } + const auto ban_time = std::chrono::steady_clock::now() + std::chrono::seconds(seconds); MutexLock lock(m_bansLock); @@ -772,7 +782,7 @@ void TCPServer::on_new_client(uv_stream_t* server, Client* client) LOGINFO(5, "new connection " << (client->m_isIncoming ? "from " : "to ") << log::Gray() << static_cast(client->m_addrString)); - if (is_banned(client->m_addr)) { + if (is_banned(client->m_isV6, client->m_addr)) { LOGINFO(5, "peer " << log::Gray() << static_cast(client->m_addrString) << log::NoColor() << " is banned, disconnecting"); client->close(); return; @@ -1209,7 +1219,7 @@ void TCPServer::Client::ban(uint64_t seconds) if (m_owner) { LOGWARN(3, "peer " << static_cast(m_addrString) << " banned for " << seconds << " seconds"); - m_owner->ban(m_addr, seconds); + m_owner->ban(m_isV6, m_addr, seconds); } } diff --git a/src/tcp_server.h b/src/tcp_server.h index 081cf60..fe43b12 100644 --- a/src/tcp_server.h +++ b/src/tcp_server.h @@ -44,7 +44,7 @@ public: bool connect_to_peer(bool is_v6, const raw_ip& ip, int port); virtual void on_connect_failed(bool /*is_v6*/, const raw_ip& /*ip*/, int /*port*/) {} - void ban(const raw_ip& ip, uint64_t seconds); + void ban(bool is_v6, raw_ip ip, uint64_t seconds); virtual void print_bans(); struct Client @@ -188,7 +188,7 @@ protected: uv_mutex_t m_bansLock; unordered_map m_bans; - bool is_banned(const raw_ip& ip); + bool is_banned(bool is_v6, raw_ip ip); unordered_set m_pendingConnections;