Browse Source

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.
miguelfreitas
Miguel Freitas 10 years ago
parent
commit
b8e264f4d1
  1. 2
      libtorrent/include/libtorrent/aux_/session_impl.hpp
  2. 3
      libtorrent/include/libtorrent/kademlia/dht_get.hpp
  3. 2
      libtorrent/include/libtorrent/kademlia/dht_tracker.hpp
  4. 2
      libtorrent/include/libtorrent/kademlia/node.hpp
  5. 2
      libtorrent/include/libtorrent/kademlia/observer.hpp
  6. 2
      libtorrent/include/libtorrent/session.hpp
  7. 5
      libtorrent/src/kademlia/dht_get.cpp
  8. 4
      libtorrent/src/kademlia/dht_tracker.cpp
  9. 15
      libtorrent/src/kademlia/node.cpp
  10. 2
      libtorrent/src/kademlia/rpc_manager.cpp
  11. 7
      libtorrent/src/session.cpp
  12. 5
      libtorrent/src/session_impl.cpp
  13. 2
      src/clientversion.h
  14. 2
      src/dhtproxy.cpp
  15. 15
      src/twister.cpp
  16. 2
      src/twister.h

2
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, 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); 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; entry dht_getLocalData() const;

3
libtorrent/include/libtorrent/kademlia/dht_get.hpp

@ -74,7 +74,7 @@ public:
, std::string const &targetUser, std::string const &targetResource, bool multi , std::string const &targetUser, std::string const &targetResource, bool multi
, data_callback const& dcallback , data_callback const& dcallback
, nodes_callback const& ncallback , nodes_callback const& ncallback
, bool justToken); , bool justToken, bool dontDrop );
virtual char const* name() const { return "getData"; } virtual char const* name() const { return "getData"; }
@ -98,6 +98,7 @@ private:
bool m_done:1; bool m_done:1;
bool m_got_data:1; bool m_got_data:1;
bool m_justToken:1; bool m_justToken:1;
bool m_dontDrop:1;
friend class dht_get_observer; friend class dht_get_observer;
}; };

2
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, void getData(std::string const &username, std::string const &resource, bool multi,
boost::function<void(entry::list_type const&)> fdata, boost::function<void(entry::list_type const&)> fdata,
boost::function<void(bool, bool)> fdone); boost::function<void(bool, bool)> fdone, bool local);
void dht_status(session_status& s); void dht_status(session_status& s);
void network_stats(int& sent, int& received); void network_stats(int& sent, int& received);

2
libtorrent/include/libtorrent/kademlia/node.hpp

@ -231,7 +231,7 @@ public:
void getData(std::string const &username, std::string const &resource, bool multi, void getData(std::string const &username, std::string const &resource, bool multi,
boost::function<void(entry::list_type const&)> fdata, boost::function<void(entry::list_type const&)> fdata,
boost::function<void(bool, bool)> fdone); boost::function<void(bool, bool)> fdone, bool local);
bool verify_token(std::string const& token, char const* info_hash bool verify_token(std::string const& token, char const* info_hash
, udp::endpoint const& addr); , udp::endpoint const& addr);

2
libtorrent/include/libtorrent/kademlia/observer.hpp

@ -76,6 +76,7 @@ struct observer : boost::noncopyable
, m_port(0) , m_port(0)
, m_transaction_id() , m_transaction_id()
, flags(0) , flags(0)
, m_dont_drop(true)
{ {
TORRENT_ASSERT(a); TORRENT_ASSERT(a);
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
@ -171,6 +172,7 @@ public:
bool m_was_abandoned:1; bool m_was_abandoned:1;
bool m_in_use:1; bool m_in_use:1;
#endif #endif
bool m_dont_drop:1;
}; };
typedef boost::intrusive_ptr<observer> observer_ptr; typedef boost::intrusive_ptr<observer> observer_ptr;

2
libtorrent/include/libtorrent/session.hpp

@ -441,7 +441,7 @@ namespace libtorrent
void dht_putDataSigned(std::string const &username, std::string const &resource, bool multi, 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); 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; entry dht_getLocalData() const;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE

5
libtorrent/src/kademlia/dht_get.cpp

@ -222,7 +222,8 @@ dht_get::dht_get(
, bool multi , bool multi
, data_callback const& dcallback , data_callback const& dcallback
, nodes_callback const& ncallback , nodes_callback const& ncallback
, bool justToken) , bool justToken
, bool dontDrop)
: traversal_algorithm(node, node_id()) : traversal_algorithm(node, node_id())
, m_data_callback(dcallback) , m_data_callback(dcallback)
, m_nodes_callback(ncallback) , m_nodes_callback(ncallback)
@ -233,6 +234,7 @@ dht_get::dht_get(
, m_done(false) , m_done(false)
, m_got_data(false) , m_got_data(false)
, m_justToken(justToken) , m_justToken(justToken)
, m_dontDrop(dontDrop)
{ {
m_target["n"] = m_targetUser; m_target["n"] = m_targetUser;
m_target["r"] = m_targetResource; m_target["r"] = m_targetResource;
@ -276,6 +278,7 @@ bool dht_get::invoke(observer_ptr o)
entry& target = a["target"]; entry& target = a["target"];
target = m_target; target = m_target;
if (m_justToken) a["justtoken"] = 1; if (m_justToken) a["justtoken"] = 1;
o->m_dont_drop = m_dontDrop;
return m_node.m_rpc.invoke(e, o->target_ep(), o); return m_node.m_rpc.invoke(e, o->target_ep(), o);
} }

4
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, void dht_tracker::getData(std::string const &username, std::string const &resource, bool multi,
boost::function<void(entry::list_type const&)> fdata, boost::function<void(entry::list_type const&)> fdata,
boost::function<void(bool, bool)> fdone) boost::function<void(bool, bool)> fdone, bool local)
{ {
m_dht.getData(username, resource, multi, fdata, fdone); m_dht.getData(username, resource, multi, fdata, fdone, local);
} }

15
libtorrent/src/kademlia/node.cpp

@ -239,8 +239,9 @@ void node_impl::incoming(msg const& m)
if (!y_ent || y_ent->string_length() == 0) if (!y_ent || y_ent->string_length() == 0)
{ {
entry e; entry e;
incoming_error(e, "missing 'y' entry"); incoming_error(e, "missing 'z' entry");
m_sock->send_packet(e, m.addr, 0); // [MF] silently ignore bad packet
//m_sock->send_packet(e, m.addr, 0);
return; 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. // for info-hash id. then send putData to them.
boost::intrusive_ptr<dht_get> ta(new dht_get(*this, username, resource, multi, boost::intrusive_ptr<dht_get> ta(new dht_get(*this, username, resource, multi,
boost::bind(&nop), 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 ) { if( local ) {
// store it locally so it will be automatically refreshed with the rest // 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, void node_impl::getData(std::string const &username, std::string const &resource, bool multi,
boost::function<void(entry::list_type const&)> fdata, boost::function<void(entry::list_type const&)> fdata,
boost::function<void(bool, bool)> fdone) boost::function<void(bool, bool)> fdone, bool local)
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(node) << "getData [ username: " << info_hash << " res: " << resource << " ]" ; 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. // for info-hash id. callback is used to return data.
boost::intrusive_ptr<dht_get> ta(new dht_get(*this, username, resource, multi, boost::intrusive_ptr<dht_get> ta(new dht_get(*this, username, resource, multi,
fdata, 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(); ta->start();
} }
@ -698,7 +699,9 @@ bool node_impl::refresh_storage() {
boost::intrusive_ptr<dht_get> ta(new dht_get(*this, username, resource, multi, boost::intrusive_ptr<dht_get> ta(new dht_get(*this, username, resource, multi,
boost::bind(&putData_confirm, _1, boost::ref(item)), boost::bind(&putData_confirm, _1, boost::ref(item)),
boost::bind(&putData_fun, _1, boost::ref(*this), 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(); ta->start();
did_something = true; did_something = true;
} }

2
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; << e["q"].string() << " -> " << target_addr;
#endif #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); m_transactions.push_back(o);
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS

7
libtorrent/src/session.cpp

@ -332,6 +332,9 @@ namespace libtorrent
#define TORRENT_ASYNC_CALL3(x, a1, a2, a3) \ #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)) 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) \ #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)) 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 #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 #ifndef TORRENT_DISABLE_DHT
TORRENT_ASYNC_CALL3(dht_getData, username, resource, multi); TORRENT_ASYNC_CALL4(dht_getData, username, resource, multi, local);
#endif #endif
} }

5
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, if (m_dht) m_dht->getData(username, resource, multi,
boost::bind( post_dht_getData, this, _1), 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 entry session_impl::dht_getLocalData() const

2
src/clientversion.h

@ -8,7 +8,7 @@
// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it // 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_MAJOR 0
#define CLIENT_VERSION_MINOR 9 #define CLIENT_VERSION_MINOR 9
#define CLIENT_VERSION_REVISION 27 #define CLIENT_VERSION_REVISION 28
#define CLIENT_VERSION_BUILD 0 #define CLIENT_VERSION_BUILD 0
// Set to true for release, false for prerelease or test build // Set to true for release, false for prerelease or test build

2
src/dhtproxy.cpp

@ -228,7 +228,7 @@ namespace DhtProxy
sha1_hash ih = dhtTargetHash(username, resource, multi ? "m" : "s"); sha1_hash ih = dhtTargetHash(username, resource, multi ? "m" : "s");
if( !req.stopReq ) { if( !req.stopReq ) {
dhtgetPeerReqAdd(ih, pfrom); dhtgetPeerReqAdd(ih, pfrom);
dhtGetData(username, resource, multi); dhtGetData(username, resource, multi, false);
} else { } else {
dhtgetPeerReqRemove(ih, pfrom); dhtgetPeerReqRemove(ih, pfrom);
} }

15
src/twister.cpp

@ -381,6 +381,9 @@ void ThreadWaitExtIP()
settings.active_limit = 25; settings.active_limit = 25;
settings.unchoke_slots_limit = 20; settings.unchoke_slots_limit = 20;
settings.auto_manage_interval = 30; 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); ses->set_settings(settings);
printf("libtorrent + dht started\n"); printf("libtorrent + dht started\n");
@ -785,7 +788,7 @@ void ThreadSessionAlerts()
t->string().c_str()); t->string().c_str());
#endif #endif
neighborCheck[ih] = false; neighborCheck[ih] = false;
dhtGetData(n->string(), r->string(), t->string() == "m"); dhtGetData(n->string(), r->string(), t->string() == "m", false);
} else if( neighborCheck[ih] ) { } else if( neighborCheck[ih] ) {
sha1_hash ihStatus = dhtTargetHash(n->string(), "status", "s"); sha1_hash ihStatus = dhtTargetHash(n->string(), "status", "s");
@ -796,7 +799,7 @@ void ThreadSessionAlerts()
n->string().c_str(), "status", "s"); n->string().c_str(), "status", "s");
#endif #endif
statusCheck[ihStatus] = GetTime(); statusCheck[ihStatus] = GetTime();
dhtGetData(n->string(), "status", false); dhtGetData(n->string(), "status", false, false);
} }
} }
} }
@ -832,7 +835,7 @@ void ThreadSessionAlerts()
#endif #endif
sha1_hash ihStatus = dhtTargetHash(dd->m_username, "status", "s"); sha1_hash ihStatus = dhtTargetHash(dd->m_username, "status", "s");
statusCheck[ihStatus] = GetTime(); statusCheck[ihStatus] = GetTime();
dhtGetData(dd->m_username, "status", false); dhtGetData(dd->m_username, "status", false, false);
} }
} }
if( statusCheck.count(ih) ) { 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 ) { if( DhtProxy::fEnabled ) {
printf("dhtGetData: not allowed - using proxy (bug!)\n"); 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"); printf("dhtGetData: libtorrent session not ready\n");
return; 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, void dhtPutData(std::string const &username, std::string const &resource, bool multi,
@ -1685,7 +1688,7 @@ Value dhtget(const Array& params, bool fHelp)
vector<CNode*> dhtProxyNodes; vector<CNode*> dhtProxyNodes;
if( !DhtProxy::fEnabled ) { if( !DhtProxy::fEnabled ) {
dhtgetMapAdd(ih, &am); dhtgetMapAdd(ih, &am);
dhtGetData(strUsername, strResource, multi); dhtGetData(strUsername, strResource, multi, true);
} else { } else {
DhtProxy::dhtgetMapAdd(ih, &am); DhtProxy::dhtgetMapAdd(ih, &am);
dhtProxyNodes = DhtProxy::dhtgetStartRequest(strUsername, strResource, multi); dhtProxyNodes = DhtProxy::dhtgetStartRequest(strUsername, strResource, multi);

2
src/twister.h

@ -47,7 +47,7 @@ int getDhtNodes(boost::int64_t *dht_global_nodes = NULL);
void updateSeenHashtags(std::string &message, int64_t msgTime); void updateSeenHashtags(std::string &message, int64_t msgTime);
// interface to dht api of the libtorrent current session // 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, void dhtPutData(std::string const &username, std::string const &resource, bool multi,
libtorrent::entry const &value, std::string const &sig_user, libtorrent::entry const &value, std::string const &sig_user,
boost::int64_t timeutc, int seq); boost::int64_t timeutc, int seq);

Loading…
Cancel
Save