From b8e264f4d13354e9ae2bd387dfed7ea137a83424 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Thu, 4 Dec 2014 16:45:43 -0200 Subject: [PATCH] 0.9.28: better enforcement of DHT upload rate limit for non-locally generated requests. the limit applies to: DHT replies, refreshes of stored items, checking for status/tracker and proxy server. local requests (eg. dhtgets from the UI) are excluded from this limit, so user experience is not affected. in other words: we limit only the band contributed back to twister network for maintenance tasks. this should improve resilience against some sorts of denial-of-service attacks and also prevents saturating the uplink as observed recently. --- .../include/libtorrent/aux_/session_impl.hpp | 2 +- .../include/libtorrent/kademlia/dht_get.hpp | 3 ++- .../include/libtorrent/kademlia/dht_tracker.hpp | 2 +- libtorrent/include/libtorrent/kademlia/node.hpp | 2 +- .../include/libtorrent/kademlia/observer.hpp | 2 ++ libtorrent/include/libtorrent/session.hpp | 2 +- libtorrent/src/kademlia/dht_get.cpp | 5 ++++- libtorrent/src/kademlia/dht_tracker.cpp | 4 ++-- libtorrent/src/kademlia/node.cpp | 15 +++++++++------ libtorrent/src/kademlia/rpc_manager.cpp | 2 +- libtorrent/src/session.cpp | 7 +++++-- libtorrent/src/session_impl.cpp | 5 +++-- src/clientversion.h | 2 +- src/dhtproxy.cpp | 2 +- src/twister.cpp | 15 +++++++++------ src/twister.h | 2 +- 16 files changed, 44 insertions(+), 28 deletions(-) diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index 2aa48989..6a4aa380 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -310,7 +310,7 @@ namespace libtorrent void dht_putDataSigned(std::string const &username, std::string const &resource, bool multi, entry const &p, std::string const &sig_p, std::string const &sig_user, bool local); - void dht_getData(std::string const &username, std::string const &resource, bool multi); + void dht_getData(std::string const &username, std::string const &resource, bool multi, bool local); entry dht_getLocalData() const; diff --git a/libtorrent/include/libtorrent/kademlia/dht_get.hpp b/libtorrent/include/libtorrent/kademlia/dht_get.hpp index 0be2f554..a6d3d951 100644 --- a/libtorrent/include/libtorrent/kademlia/dht_get.hpp +++ b/libtorrent/include/libtorrent/kademlia/dht_get.hpp @@ -74,7 +74,7 @@ public: , std::string const &targetUser, std::string const &targetResource, bool multi , data_callback const& dcallback , nodes_callback const& ncallback - , bool justToken); + , bool justToken, bool dontDrop ); virtual char const* name() const { return "getData"; } @@ -98,6 +98,7 @@ private: bool m_done:1; bool m_got_data:1; bool m_justToken:1; + bool m_dontDrop:1; friend class dht_get_observer; }; diff --git a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp b/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp index a60b8741..bce71496 100644 --- a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp +++ b/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp @@ -101,7 +101,7 @@ namespace libtorrent { namespace dht void getData(std::string const &username, std::string const &resource, bool multi, boost::function fdata, - boost::function fdone); + boost::function fdone, bool local); void dht_status(session_status& s); void network_stats(int& sent, int& received); diff --git a/libtorrent/include/libtorrent/kademlia/node.hpp b/libtorrent/include/libtorrent/kademlia/node.hpp index 56a2bb5d..0e1fe468 100644 --- a/libtorrent/include/libtorrent/kademlia/node.hpp +++ b/libtorrent/include/libtorrent/kademlia/node.hpp @@ -231,7 +231,7 @@ public: void getData(std::string const &username, std::string const &resource, bool multi, boost::function fdata, - boost::function fdone); + boost::function fdone, bool local); bool verify_token(std::string const& token, char const* info_hash , udp::endpoint const& addr); diff --git a/libtorrent/include/libtorrent/kademlia/observer.hpp b/libtorrent/include/libtorrent/kademlia/observer.hpp index b8fb1a17..381c093b 100644 --- a/libtorrent/include/libtorrent/kademlia/observer.hpp +++ b/libtorrent/include/libtorrent/kademlia/observer.hpp @@ -76,6 +76,7 @@ struct observer : boost::noncopyable , m_port(0) , m_transaction_id() , flags(0) + , m_dont_drop(true) { TORRENT_ASSERT(a); #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS @@ -171,6 +172,7 @@ public: bool m_was_abandoned:1; bool m_in_use:1; #endif + bool m_dont_drop:1; }; typedef boost::intrusive_ptr observer_ptr; diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp index 2b934af4..666c8010 100644 --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -441,7 +441,7 @@ namespace libtorrent void dht_putDataSigned(std::string const &username, std::string const &resource, bool multi, entry const &p, std::string const &sig_p, std::string const &sig_user, bool local); - void dht_getData(std::string const &username, std::string const &resource, bool multi); + void dht_getData(std::string const &username, std::string const &resource, bool multi, bool local); entry dht_getLocalData() const; #ifndef TORRENT_NO_DEPRECATE diff --git a/libtorrent/src/kademlia/dht_get.cpp b/libtorrent/src/kademlia/dht_get.cpp index 6e6fbf6d..51c51b1b 100644 --- a/libtorrent/src/kademlia/dht_get.cpp +++ b/libtorrent/src/kademlia/dht_get.cpp @@ -222,7 +222,8 @@ dht_get::dht_get( , bool multi , data_callback const& dcallback , nodes_callback const& ncallback - , bool justToken) + , bool justToken + , bool dontDrop) : traversal_algorithm(node, node_id()) , m_data_callback(dcallback) , m_nodes_callback(ncallback) @@ -233,6 +234,7 @@ dht_get::dht_get( , m_done(false) , m_got_data(false) , m_justToken(justToken) + , m_dontDrop(dontDrop) { m_target["n"] = m_targetUser; m_target["r"] = m_targetResource; @@ -276,6 +278,7 @@ bool dht_get::invoke(observer_ptr o) entry& target = a["target"]; target = m_target; if (m_justToken) a["justtoken"] = 1; + o->m_dont_drop = m_dontDrop; return m_node.m_rpc.invoke(e, o->target_ep(), o); } diff --git a/libtorrent/src/kademlia/dht_tracker.cpp b/libtorrent/src/kademlia/dht_tracker.cpp index 1469513f..e64caa36 100644 --- a/libtorrent/src/kademlia/dht_tracker.cpp +++ b/libtorrent/src/kademlia/dht_tracker.cpp @@ -441,9 +441,9 @@ namespace libtorrent { namespace dht void dht_tracker::getData(std::string const &username, std::string const &resource, bool multi, boost::function fdata, - boost::function fdone) + boost::function fdone, bool local) { - m_dht.getData(username, resource, multi, fdata, fdone); + m_dht.getData(username, resource, multi, fdata, fdone, local); } diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp index 10ebd390..b9371adc 100644 --- a/libtorrent/src/kademlia/node.cpp +++ b/libtorrent/src/kademlia/node.cpp @@ -239,8 +239,9 @@ void node_impl::incoming(msg const& m) if (!y_ent || y_ent->string_length() == 0) { entry e; - incoming_error(e, "missing 'y' entry"); - m_sock->send_packet(e, m.addr, 0); + incoming_error(e, "missing 'z' entry"); + // [MF] silently ignore bad packet + //m_sock->send_packet(e, m.addr, 0); return; } @@ -514,7 +515,7 @@ void node_impl::putDataSigned(std::string const &username, std::string const &re // for info-hash id. then send putData to them. boost::intrusive_ptr ta(new dht_get(*this, username, resource, multi, boost::bind(&nop), - boost::bind(&putData_fun, _1, boost::ref(*this), p, sig_p, sig_user), true)); + boost::bind(&putData_fun, _1, boost::ref(*this), p, sig_p, sig_user), true, local)); if( local ) { // store it locally so it will be automatically refreshed with the rest @@ -548,7 +549,7 @@ void node_impl::putDataSigned(std::string const &username, std::string const &re void node_impl::getData(std::string const &username, std::string const &resource, bool multi, boost::function fdata, - boost::function fdone) + boost::function fdone, bool local) { #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(node) << "getData [ username: " << info_hash << " res: " << resource << " ]" ; @@ -557,7 +558,7 @@ void node_impl::getData(std::string const &username, std::string const &resource // for info-hash id. callback is used to return data. boost::intrusive_ptr ta(new dht_get(*this, username, resource, multi, fdata, - boost::bind(&getDataDone_fun, _1, _2, _3, boost::ref(*this), fdone), false)); + boost::bind(&getDataDone_fun, _1, _2, _3, boost::ref(*this), fdone), false, local)); ta->start(); } @@ -698,7 +699,9 @@ bool node_impl::refresh_storage() { boost::intrusive_ptr ta(new dht_get(*this, username, resource, multi, boost::bind(&putData_confirm, _1, boost::ref(item)), boost::bind(&putData_fun, _1, boost::ref(*this), - entryP, item.sig_p, item.sig_user), item.confirmed)); + entryP, item.sig_p, item.sig_user), + item.confirmed, + item.local_add_time)); ta->start(); did_something = true; } diff --git a/libtorrent/src/kademlia/rpc_manager.cpp b/libtorrent/src/kademlia/rpc_manager.cpp index b55453ab..d310e042 100644 --- a/libtorrent/src/kademlia/rpc_manager.cpp +++ b/libtorrent/src/kademlia/rpc_manager.cpp @@ -492,7 +492,7 @@ bool rpc_manager::invoke(entry& e, udp::endpoint target_addr << e["q"].string() << " -> " << target_addr; #endif - if (m_sock->send_packet(e, target_addr, 1)) + if (m_sock->send_packet(e, target_addr, (o->m_dont_drop) ? 1 : 0)) // udp_socket::dont_drop = 1 { m_transactions.push_back(o); #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index c9374565..3da60e30 100644 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -332,6 +332,9 @@ namespace libtorrent #define TORRENT_ASYNC_CALL3(x, a1, a2, a3) \ m_impl->m_io_service.dispatch(boost::bind(&session_impl:: x, m_impl.get(), a1, a2, a3)) +#define TORRENT_ASYNC_CALL4(x, a1, a2, a3, a4) \ + m_impl->m_io_service.dispatch(boost::bind(&session_impl:: x, m_impl.get(), a1, a2, a3, a4)) + #define TORRENT_ASYNC_CALL6(x, a1, a2, a3, a4, a5, a6) \ m_impl->m_io_service.dispatch(boost::bind(&session_impl:: x, m_impl.get(), a1, a2, a3, a4, a5, a6)) @@ -862,10 +865,10 @@ namespace libtorrent #endif } - void session::dht_getData(std::string const &username, std::string const &resource, bool multi) + void session::dht_getData(std::string const &username, std::string const &resource, bool multi, bool local) { #ifndef TORRENT_DISABLE_DHT - TORRENT_ASYNC_CALL3(dht_getData, username, resource, multi); + TORRENT_ASYNC_CALL4(dht_getData, username, resource, multi, local); #endif } diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 99a03c26..da067f42 100644 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -5814,11 +5814,12 @@ retry: } } - void session_impl::dht_getData(std::string const &username, std::string const &resource, bool multi) + void session_impl::dht_getData(std::string const &username, std::string const &resource, bool multi, bool local) { if (m_dht) m_dht->getData(username, resource, multi, boost::bind( post_dht_getData, this, _1), - boost::bind( getDataDone_fun, this, username, resource, multi, _1, _2)); + boost::bind( getDataDone_fun, this, username, resource, multi, _1, _2), + local); } entry session_impl::dht_getLocalData() const diff --git a/src/clientversion.h b/src/clientversion.h index fde9e725..3d42c64d 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -8,7 +8,7 @@ // These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 -#define CLIENT_VERSION_REVISION 27 +#define CLIENT_VERSION_REVISION 28 #define CLIENT_VERSION_BUILD 0 // Set to true for release, false for prerelease or test build diff --git a/src/dhtproxy.cpp b/src/dhtproxy.cpp index f3dc863f..bde9db02 100644 --- a/src/dhtproxy.cpp +++ b/src/dhtproxy.cpp @@ -228,7 +228,7 @@ namespace DhtProxy sha1_hash ih = dhtTargetHash(username, resource, multi ? "m" : "s"); if( !req.stopReq ) { dhtgetPeerReqAdd(ih, pfrom); - dhtGetData(username, resource, multi); + dhtGetData(username, resource, multi, false); } else { dhtgetPeerReqRemove(ih, pfrom); } diff --git a/src/twister.cpp b/src/twister.cpp index e088b1ec..004e48b6 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -381,6 +381,9 @@ void ThreadWaitExtIP() settings.active_limit = 25; settings.unchoke_slots_limit = 20; settings.auto_manage_interval = 30; + // dht upload rate limit (enforced only for non-locally generated requests) + // limits: DHT replies, refreshes of stored items, checking for status/tracker and proxy server. + settings.dht_upload_rate_limit = 16000; ses->set_settings(settings); printf("libtorrent + dht started\n"); @@ -785,7 +788,7 @@ void ThreadSessionAlerts() t->string().c_str()); #endif neighborCheck[ih] = false; - dhtGetData(n->string(), r->string(), t->string() == "m"); + dhtGetData(n->string(), r->string(), t->string() == "m", false); } else if( neighborCheck[ih] ) { sha1_hash ihStatus = dhtTargetHash(n->string(), "status", "s"); @@ -796,7 +799,7 @@ void ThreadSessionAlerts() n->string().c_str(), "status", "s"); #endif statusCheck[ihStatus] = GetTime(); - dhtGetData(n->string(), "status", false); + dhtGetData(n->string(), "status", false, false); } } } @@ -832,7 +835,7 @@ void ThreadSessionAlerts() #endif sha1_hash ihStatus = dhtTargetHash(dd->m_username, "status", "s"); statusCheck[ihStatus] = GetTime(); - dhtGetData(dd->m_username, "status", false); + dhtGetData(dd->m_username, "status", false, false); } } if( statusCheck.count(ih) ) { @@ -1546,7 +1549,7 @@ entry formatSpamPost(const string &msg, const string &username, uint64_t utcTime } -void dhtGetData(std::string const &username, std::string const &resource, bool multi) +void dhtGetData(std::string const &username, std::string const &resource, bool multi, bool local) { if( DhtProxy::fEnabled ) { printf("dhtGetData: not allowed - using proxy (bug!)\n"); @@ -1557,7 +1560,7 @@ void dhtGetData(std::string const &username, std::string const &resource, bool m printf("dhtGetData: libtorrent session not ready\n"); return; } - ses->dht_getData(username,resource,multi); + ses->dht_getData(username,resource,multi,local); } void dhtPutData(std::string const &username, std::string const &resource, bool multi, @@ -1685,7 +1688,7 @@ Value dhtget(const Array& params, bool fHelp) vector dhtProxyNodes; if( !DhtProxy::fEnabled ) { dhtgetMapAdd(ih, &am); - dhtGetData(strUsername, strResource, multi); + dhtGetData(strUsername, strResource, multi, true); } else { DhtProxy::dhtgetMapAdd(ih, &am); dhtProxyNodes = DhtProxy::dhtgetStartRequest(strUsername, strResource, multi); diff --git a/src/twister.h b/src/twister.h index d219c6b7..a8b192ed 100644 --- a/src/twister.h +++ b/src/twister.h @@ -47,7 +47,7 @@ int getDhtNodes(boost::int64_t *dht_global_nodes = NULL); void updateSeenHashtags(std::string &message, int64_t msgTime); // interface to dht api of the libtorrent current session -void dhtGetData(std::string const &username, std::string const &resource, bool multi); +void dhtGetData(std::string const &username, std::string const &resource, bool multi, bool local); void dhtPutData(std::string const &username, std::string const &resource, bool multi, libtorrent::entry const &value, std::string const &sig_user, boost::int64_t timeutc, int seq);