merged changes from RC_1_0

This commit is contained in:
Arvid Norberg 2014-11-03 06:15:51 +00:00
parent 3742fd2699
commit 601f0dc434
13 changed files with 106 additions and 18 deletions

View File

@ -370,7 +370,7 @@ namespace libtorrent
void resume(); void resume();
void set_ip_filter(ip_filter const& f); void set_ip_filter(ip_filter const& f);
ip_filter const& get_ip_filter() const; ip_filter& get_ip_filter();
void set_port_filter(port_filter const& f); void set_port_filter(port_filter const& f);
port_filter const& get_port_filter() const; port_filter const& get_port_filter() const;

View File

@ -142,7 +142,7 @@ namespace libtorrent { namespace aux
virtual void remove_torrent_impl(boost::shared_ptr<torrent> tptr, int options) = 0; virtual void remove_torrent_impl(boost::shared_ptr<torrent> tptr, int options) = 0;
// ip and port filter // ip and port filter
virtual ip_filter const& get_ip_filter() const = 0; virtual ip_filter& get_ip_filter() = 0;
virtual port_filter const& get_port_filter() const = 0; virtual port_filter const& get_port_filter() const = 0;
virtual boost::int64_t session_time() const = 0; virtual boost::int64_t session_time() const = 0;

View File

@ -63,6 +63,7 @@ int TORRENT_EXTRA_EXPORT distance_exp(node_id const& n1, node_id const& n2);
node_id TORRENT_EXTRA_EXPORT generate_id(address const& external_ip); node_id TORRENT_EXTRA_EXPORT generate_id(address const& external_ip);
node_id TORRENT_EXTRA_EXPORT generate_random_id(); node_id TORRENT_EXTRA_EXPORT generate_random_id();
bool TORRENT_EXTRA_EXPORT verify_random_id(node_id const& nid);
node_id TORRENT_EXTRA_EXPORT generate_id_impl(address const& ip_, boost::uint32_t r); node_id TORRENT_EXTRA_EXPORT generate_id_impl(address const& ip_, boost::uint32_t r);
bool TORRENT_EXTRA_EXPORT verify_id(node_id const& nid, address const& source_ip); bool TORRENT_EXTRA_EXPORT verify_id(node_id const& nid, address const& source_ip);

View File

@ -281,6 +281,8 @@ namespace libtorrent
// it to finish. The timeout can be set with apply_settings(). // it to finish. The timeout can be set with apply_settings().
~session(); ~session();
// TODO: 2 the ip filter should probably be saved here too
// flags that determines which aspects of the session should be // flags that determines which aspects of the session should be
// saved when calling save_state(). // saved when calling save_state().
enum save_state_flags_t enum save_state_flags_t

View File

@ -216,6 +216,8 @@ void get_item::put(std::vector<std::pair<node_entry, std::string> > const& v)
void* ptr = m_node.m_rpc.allocate_observer(); void* ptr = m_node.m_rpc.allocate_observer();
if (ptr == 0) return; if (ptr == 0) return;
// TODO: 3 we don't support CAS errors here! we need a custom observer
observer_ptr o(new (ptr) announce_observer(algo, i->first.ep(), i->first.id)); observer_ptr o(new (ptr) announce_observer(algo, i->first.ep(), i->first.id));
#if TORRENT_USE_ASSERTS #if TORRENT_USE_ASSERTS
o->m_in_constructor = false; o->m_in_constructor = false;

View File

@ -229,7 +229,7 @@ bool obfuscated_get_peers::invoke(observer_ptr o)
entry e; entry e;
e["y"] = "q"; e["y"] = "q";
e["q"] = "find_node"; e["q"] = "get_peers";
entry& a = e["a"]; entry& a = e["a"];
// This logic will obfuscate the target info-hash // This logic will obfuscate the target info-hash
@ -238,11 +238,11 @@ bool obfuscated_get_peers::invoke(observer_ptr o)
// bits in the info-hash for the node we're querying to // bits in the info-hash for the node we're querying to
// give a good answer, but not more. // give a good answer, but not more.
// now, obfuscate the bits past shared_prefix + 5 // now, obfuscate the bits past shared_prefix + 3
node_id obfuscated_target = generate_random_id(); node_id mask = generate_prefix_mask(shared_prefix + 3);
obfuscated_target >>= shared_prefix + 3; node_id obfuscated_target = generate_random_id() & ~mask;
obfuscated_target^= m_target; obfuscated_target |= m_target & mask;
a["target"] = obfuscated_target.to_string(); a["info_hash"] = obfuscated_target.to_string();
m_node.post_alert(new dht_outgoing_get_peers_alert(m_target m_node.post_alert(new dht_outgoing_get_peers_alert(m_target
, obfuscated_target, o->target_ep())); , obfuscated_target, o->target_ep()));

View File

@ -477,14 +477,9 @@ void node_impl::send_single_refresh(udp::endpoint const& ep, int bucket
// generate a random node_id within the given bucket // generate a random node_id within the given bucket
// TODO: 2 it would be nice to have a bias towards node-id prefixes that // TODO: 2 it would be nice to have a bias towards node-id prefixes that
// are missing in the bucket // are missing in the bucket
node_id target = generate_random_id();
node_id mask = generate_prefix_mask(bucket + 1); node_id mask = generate_prefix_mask(bucket + 1);
node_id target = generate_random_id() & ~mask;
// target = (target & ~mask) | (root & mask) target |= m_id & mask;
node_id root = m_id;
root &= mask;
target &= ~mask;
target |= root;
// create a dummy traversal_algorithm // create a dummy traversal_algorithm
// this is unfortunately necessary for the observer // this is unfortunately necessary for the observer

View File

@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/broadcast_socket.hpp" // for is_local et.al #include "libtorrent/broadcast_socket.hpp" // for is_local et.al
#include "libtorrent/socket_io.hpp" // for hash_address #include "libtorrent/socket_io.hpp" // for hash_address
#include "libtorrent/random.hpp" // for random #include "libtorrent/random.hpp" // for random
#include "libtorrent/hasher.hpp" // for hasher
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
@ -148,11 +149,34 @@ node_id generate_id_impl(address const& ip_, boost::uint32_t r)
return id; return id;
} }
static boost::uint32_t secret = 0;
node_id generate_random_id() node_id generate_random_id()
{ {
char r[20]; char r[20];
for (int i = 0; i < 20; ++i) r[i] = random() & 0xff; for (int i = 0; i < 20; ++i) r[i] = random() & 0xff;
return hasher(r, 20).final(); node_id ret = hasher(r, 20).final();
if (secret == 0) secret = (random() % 0xfffffffe) + 1;
// generate the last 4 bytes as a "signature" of the previous 4 bytes. This
// lets us verify whether a hash came from this function or not in the future.
hasher h((char*)&secret, 4);
h.update((char*)&ret[20-8], 4);
sha1_hash secret_hash = h.final();
memcpy(&ret[20-4], &secret_hash[0], 4);
return ret;
}
bool verify_random_id(node_id const& nid)
{
if (secret == 0) return false;
hasher h((char*)&secret, 4);
h.update((char const*)&nid[20-8], 4);
sha1_hash secret_hash = h.final();
return memcmp(&nid[20-4], &secret_hash[0], 4) == 0;
} }
// verifies whether a node-id matches the IP it's used from // verifies whether a node-id matches the IP it's used from

View File

@ -328,7 +328,7 @@ bool rpc_manager::incoming(msg const& m, node_id* id, libtorrent::dht_settings c
if (ret_ent == 0) if (ret_ent == 0)
{ {
// it may be an error // it may be an error
ret_ent = m.message.dict_find_dict("e"); ret_ent = m.message.dict_find("e");
o->timeout(); o->timeout();
if (ret_ent == NULL) if (ret_ent == NULL)
{ {

View File

@ -66,6 +66,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/request_blocks.hpp" // for request_a_block #include "libtorrent/request_blocks.hpp" // for request_a_block
#include "libtorrent/performance_counters.hpp" // for counters #include "libtorrent/performance_counters.hpp" // for counters
#include "libtorrent/alert_manager.hpp" // for alert_manageralert_manager #include "libtorrent/alert_manager.hpp" // for alert_manageralert_manager
#include "libtorrent/ip_filter.hpp"
#include "libtorrent/kademlia/node_id.hpp"
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
#include <set> #include <set>
@ -1219,6 +1221,17 @@ namespace libtorrent
peer_log("*** couldn't find a torrent with the given info_hash: %s torrents:", to_hex(ih.to_string()).c_str()); peer_log("*** couldn't find a torrent with the given info_hash: %s torrents:", to_hex(ih.to_string()).c_str());
m_ses.log_all_torrents(this); m_ses.log_all_torrents(this);
#endif #endif
#ifndef TORRENT_DISABLE_DHT
if (dht::verify_random_id(ih))
{
// this means the hash was generated from our generate_random_id()
// as part of DHT traffic. The fact that we got an incoming
// connection on this info-hash, means the other end, making this
// connection fished it out of the DHT chatter. That's suspicious.
m_ses.get_ip_filter().add_rule(m_remote.address(), m_remote.address(), 0);
}
#endif
disconnect(errors::invalid_info_hash, op_bittorrent, 1); disconnect(errors::invalid_info_hash, op_bittorrent, 1);
return; return;
} }

View File

@ -1130,7 +1130,7 @@ namespace aux {
i->second->port_filter_updated(); i->second->port_filter_updated();
} }
ip_filter const& session_impl::get_ip_filter() const ip_filter& session_impl::get_ip_filter()
{ {
return m_ip_filter; return m_ip_filter;
} }

View File

@ -617,6 +617,16 @@ int test_main()
fprintf(stderr, " invalid get_peers response: %s\n", error_string); fprintf(stderr, " invalid get_peers response: %s\n", error_string);
} }
// ====== test node ID testing =====
{
node_id rnd = generate_random_id();
TEST_CHECK(verify_random_id(rnd));
rnd[19] ^= 0x55;
TEST_CHECK(!verify_random_id(rnd));
}
// ====== test node ID enforcement ====== // ====== test node ID enforcement ======
// enable node_id enforcement // enable node_id enforcement

View File

@ -3,6 +3,9 @@ import sys
import os import os
import time import time
import calendar import calendar
import pprint
pp = pprint.PrettyPrinter(indent=4)
up_time_quanta = 500 up_time_quanta = 500
@ -38,6 +41,10 @@ last_incoming = ''
our_node_id = '' our_node_id = ''
unique_ips = set()
client_version_histogram = {}
client_histogram = {}
for line in f: for line in f:
counter += 1 counter += 1
# if counter % 1000 == 0: # if counter % 1000 == 0:
@ -47,6 +54,31 @@ for line in f:
if 'starting DHT tracker with node id:' in line: if 'starting DHT tracker with node id:' in line:
our_node_id = l[l.index('id:') + 1].strip() our_node_id = l[l.index('id:') + 1].strip()
try:
if len(l) > 4 and l[2] == '<==' and l[1] == '[dht_tracker]':
ip = l[3].split(':')[0]
if ip not in unique_ips:
unique_ips.add(ip)
json_blob = line.split(l[3])[1]
version = json_blob.split("'v': '")[1].split("'")[0]
if len(version) == 4:
v = '%s-%d' % (version[0:2], (ord(version[2]) << 8) + ord(version[3]))
elif len(version) == 8:
v = '%c%c-%d' % (chr(int(version[0:2], 16)), chr(int(version[2:4], 16)), int(version[4:8], 16))
else:
v = 'unknown'
if not v in client_version_histogram:
client_version_histogram[v] = 1
else:
client_version_histogram[v] += 1
if not v[0:2] in client_histogram:
client_histogram[v[0:2]] = 1
else:
client_histogram[v[0:2]] += 1
except: pass
if 'announce-distance:' in line: if 'announce-distance:' in line:
idx = l.index('announce-distance:') idx = l.index('announce-distance:')
@ -215,6 +247,15 @@ for k,v in sorted(node_uptime_histogram.items()):
print '%f %f' % (k / float(60), s / float(total_uptime_nodes)) print '%f %f' % (k / float(60), s / float(total_uptime_nodes))
out.close() out.close()
print 'clients by version'
client_version_histogram = sorted(client_version_histogram.items(), key=lambda x: x[1], reverse=True)
pp.pprint(client_version_histogram)
print 'clients'
client_histogram = sorted(client_histogram.items(), key=lambda x: x[1], reverse=True)
pp.pprint(client_histogram)
out = open('dht.gnuplot', 'w+') out = open('dht.gnuplot', 'w+')
out.write(''' out.write('''
set term png size 1200,700 small set term png size 1200,700 small