diff --git a/include/libtorrent/kademlia/dht_tracker.hpp b/include/libtorrent/kademlia/dht_tracker.hpp index f61364707..c032c19d1 100644 --- a/include/libtorrent/kademlia/dht_tracker.hpp +++ b/include/libtorrent/kademlia/dht_tracker.hpp @@ -127,7 +127,20 @@ namespace libtorrent { namespace dht // used to resolve hostnames for nodes udp::resolver m_host_resolver; - + + // used to ignore abusive dht nodes + struct node_ban_entry + { + node_ban_entry(): count(0) {} + udp::endpoint src; + ptime limit; + int count; + }; + + enum { num_ban_nodes = 20 }; + + node_ban_entry m_ban_nodes[num_ban_nodes]; + // reference counter for intrusive_ptr mutable boost::detail::atomic_count m_refs; diff --git a/include/libtorrent/time.hpp b/include/libtorrent/time.hpp index 4ab7a3819..ec1c0bce9 100644 --- a/include/libtorrent/time.hpp +++ b/include/libtorrent/time.hpp @@ -99,6 +99,7 @@ namespace libtorrent time_duration operator/(int rhs) const { return time_duration(diff / rhs); } explicit time_duration(boost::int64_t d) : diff(d) {} time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; } + time_duration operator+(time_duration const& c) { return time_duration(diff + c.diff); } boost::int64_t diff; }; diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 3f47eb070..1a074bc20 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -405,6 +405,54 @@ namespace libtorrent { namespace dht if (error) return; + node_ban_entry* match = 0; + node_ban_entry* min = m_ban_nodes; + ptime now = time_now(); + for (node_ban_entry* i = m_ban_nodes; i < m_ban_nodes + num_ban_nodes; ++i) + { + if (i->src == m_remote_endpoint[current_buffer]) + { + match = i; + break; + } + if (i->count < min->count) min = i; + } + + if (match) + { + ++match->count; + if (match->count >= 20) + { + if (now < match->limit) + { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + if (match->count == 20) + { + TORRENT_LOG(dht_tracker) << time_now_string() << " BANNING PEER [ ip: " + << m_remote_endpoint[current_buffer] << " | " + "time: " << total_seconds((now - match->limit) + seconds(5)) + << " | count: " << match->count << " ]"; + } +#endif + // we've received 20 messages in less than 5 seconds from + // this node. Ignore it until it's silent for 5 minutes + match->limit = now + minutes(5); + return; + } + + // we got 50 messages from this peer, but it was in + // more than 5 seconds. Reset the counter and the timer + match->count = 0; + match->limit = now + seconds(5); + } + } + else + { + min->count = 1; + min->limit = now + seconds(5); + min->src = m_remote_endpoint[current_buffer]; + } + #ifdef TORRENT_DHT_VERBOSE_LOGGING ++m_total_message_input; m_total_in_bytes += bytes_transferred;