diff --git a/include/libtorrent/kademlia/dos_blocker.hpp b/include/libtorrent/kademlia/dos_blocker.hpp index 84449b5be..c54aa6501 100644 --- a/include/libtorrent/kademlia/dos_blocker.hpp +++ b/include/libtorrent/kademlia/dos_blocker.hpp @@ -36,12 +36,13 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include "libtorrent/time.hpp" #include "libtorrent/address.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { namespace dht { -// this is a class that maintains a list of abusive DHT nodes, -// blocking their access to our DHT node. + // this is a class that maintains a list of abusive DHT nodes, + // blocking their access to our DHT node. struct TORRENT_EXTRA_EXPORT dos_blocker { dos_blocker(); @@ -51,6 +52,18 @@ namespace libtorrent { namespace dht // it's blocked bool incoming(address addr, ptime now); + void set_rate_limit(int l) + { + TORRENT_ASSERT(l > 0); + m_message_rate_limit = l; + } + + void set_block_timer(int t) + { + TORRENT_ASSERT(t > 0); + m_block_timeout = t; + } + private: // used to ignore abusive dht nodes @@ -64,12 +77,17 @@ namespace libtorrent { namespace dht enum { num_ban_nodes = 20 }; + // the max number of packets we can receive per second from a node before + // we block it. + int m_message_rate_limit; + + // the number of seconds a node gets blocked for when it exceeds the rate + // limit + int m_block_timeout; + node_ban_entry m_ban_nodes[num_ban_nodes]; - }; - -} -} +}} #endif diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 212f3a5ba..855218c08 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -1495,6 +1495,8 @@ namespace libtorrent , privacy_lookups(false) , enforce_node_id(false) , ignore_dark_internet(true) + , block_timeout(5 * 60) + , block_ratelimit(5) {} // the maximum number of peers to send in a reply to ``get_peers`` @@ -1571,6 +1573,15 @@ namespace libtorrent // ignore DHT messages from parts of the internet we wouldn't expect to // see any traffic from bool ignore_dark_internet; + + // the number of seconds a DHT node is banned if it exceeds the rate + // limit. The rate limit is averaged over 10 seconds to allow for bursts + // above the limit. + int block_timeout; + + // the max number of packets per second a DHT node is allowed to send + // without getting banned. + int block_ratelimit; }; diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 0710f6171..fb3aff553 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -287,6 +287,11 @@ namespace libtorrent { namespace dht if (e || m_abort) return; m_dht.tick(); + + // periodically update the DOS blocker's settings from the dht_settings + m_blocker.set_block_timer(m_settings.block_timeout); + m_blocker.set_rate_limit(m_settings.block_ratelimit); + error_code ec; m_refresh_timer.expires_from_now(seconds(5), ec); m_refresh_timer.async_wait( diff --git a/src/kademlia/dos_blocker.cpp b/src/kademlia/dos_blocker.cpp index 843892018..6fa047fca 100644 --- a/src/kademlia/dos_blocker.cpp +++ b/src/kademlia/dos_blocker.cpp @@ -44,6 +44,8 @@ namespace libtorrent { namespace dht #endif dos_blocker::dos_blocker() + : m_message_rate_limit(5) + , m_block_timeout(5 * 60) { for (int i = 0; i < num_ban_nodes; ++i) { @@ -72,28 +74,27 @@ namespace libtorrent { namespace dht { ++match->count; - // TODO: 2 make these limits configurable - if (match->count >= 50) + if (match->count >= m_message_rate_limit * 10) { if (now < match->limit) { - if (match->count == 50) + if (match->count == m_message_rate_limit * 10) { #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(dht_tracker) << " BANNING PEER [ ip: " << addr << " time: " << total_milliseconds((now - match->limit) + seconds(10)) / 1000.f << " count: " << match->count << " ]"; #endif - // we've received 50 messages in less than 10 seconds from - // this node. Ignore it until it's silent for 5 minutes - match->limit = now + minutes(5); + // we've received too many messages in less than 10 seconds + // from this node. Ignore it until it's silent for 5 minutes + match->limit = now + seconds(m_block_timeout); } return false; } - // we got 50 messages from this peer, but it was in - // more than 10 seconds. Reset the counter and the timer + // the messages we received from this peer took more than 10 + // seconds. Reset the counter and the timer match->count = 0; match->limit = now + seconds(10); } @@ -106,6 +107,5 @@ namespace libtorrent { namespace dht } return true; } -} -} +}}