twisterp2pnetworkbittorrentblockchainipv6microbloggingsocial-networkdhtdecentralizedtwister-servertwister-ipv6twister-coretwisterarmyp2p-network
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
11 KiB
231 lines
11 KiB
<?xml version="1.0" encoding="utf-8" ?> |
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
|
<head> |
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
|
<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> |
|
<title>BitTorrent DHT security extension</title> |
|
<meta name="author" content="Arvid Norberg, arvid@rasterbar.com" /> |
|
<link rel="stylesheet" type="text/css" href="../../css/base.css" /> |
|
<link rel="stylesheet" type="text/css" href="../../css/rst.css" /> |
|
<script type="text/javascript"> |
|
/* <![CDATA[ */ |
|
(function() { |
|
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0]; |
|
s.type = 'text/javascript'; |
|
s.async = true; |
|
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto'; |
|
t.parentNode.insertBefore(s, t); |
|
})(); |
|
/* ]]> */ |
|
</script> |
|
<link rel="stylesheet" href="style.css" type="text/css" /> |
|
<style type="text/css"> |
|
/* Hides from IE-mac \*/ |
|
* html pre { height: 1%; } |
|
/* End hide from IE-mac */ |
|
</style> |
|
</head> |
|
<body> |
|
<div class="document" id="bittorrent-dht-security-extension"> |
|
<div id="container"> |
|
<div id="headerNav"> |
|
<ul> |
|
<li class="first"><a href="/">Home</a></li> |
|
<li><a href="../../products.html">Products</a></li> |
|
<li><a href="../../contact.html">Contact</a></li> |
|
</ul> |
|
</div> |
|
<div id="header"> |
|
<h1><span>Rasterbar Software</span></h1> |
|
<h2><span>Software developement and consulting</span></h2> |
|
</div> |
|
<div id="main"> |
|
<h1 class="title">BitTorrent DHT security extension</h1> |
|
<table class="docinfo" frame="void" rules="none"> |
|
<col class="docinfo-name" /> |
|
<col class="docinfo-content" /> |
|
<tbody valign="top"> |
|
<tr><th class="docinfo-name">Author:</th> |
|
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@rasterbar.com</a></td></tr> |
|
<tr><th class="docinfo-name">Version:</th> |
|
<td>1.0.0</td></tr> |
|
</tbody> |
|
</table> |
|
<div class="contents topic" id="table-of-contents"> |
|
<p class="topic-title first">Table of contents</p> |
|
<ul class="simple"> |
|
<li><a class="reference internal" href="#id1" id="id2">BitTorrent DHT security extension</a></li> |
|
<li><a class="reference internal" href="#considerations" id="id3">considerations</a></li> |
|
<li><a class="reference internal" href="#node-id-restriction" id="id4">Node ID restriction</a></li> |
|
<li><a class="reference internal" href="#bootstrapping" id="id5">bootstrapping</a></li> |
|
<li><a class="reference internal" href="#enforcement" id="id6">enforcement</a></li> |
|
<li><a class="reference internal" href="#backwards-compatibility-and-transition" id="id7">backwards compatibility and transition</a></li> |
|
<li><a class="reference internal" href="#forward-compatibility" id="id8">forward compatibility</a></li> |
|
</ul> |
|
</div> |
|
<div class="section" id="id1"> |
|
<h1>BitTorrent DHT security extension</h1> |
|
<p>The purpose of this extension is to make it harder to launch a few |
|
specific attacks against the BitTorrent DHT and also to make it harder |
|
to snoop the network.</p> |
|
<p>Specifically the attack this extension intends to make harder is launching |
|
8 or more DHT nodes which node-IDs selected close to a specific target |
|
info-hash, in order to become the main nodes hosting peers for it. Currently |
|
this is very easy to do and lets the attacker not only see all the traffic |
|
related to this specific info-hash but also block access to it by other |
|
peers.</p> |
|
<p>The proposed guard against this is to enforce restrictions on which node-ID |
|
a node can choose, based on its external IP address.</p> |
|
</div> |
|
<div class="section" id="considerations"> |
|
<h1>considerations</h1> |
|
<p>One straight forward scheme to tie the node ID to an IP would be to hash |
|
the IP and force the node ID to share the prefix of that hash. One main |
|
draw back of this approach is that an entities control over the DHT key |
|
space grows linearly with its control over the IP address space.</p> |
|
<p>In order to successfully launch an attack, you just need to find 8 IPs |
|
whose hash will be <em>closest</em> to the target info-hash. Given the current |
|
size of the DHT, that is quite likely to be possible by anyone in control |
|
of a /8 IP block.</p> |
|
<p>The size of the DHT is approximately 8.4 million nodes. This is estmiated |
|
by observing that a typical routing table typically has about 20 of its |
|
top routing table buckets full. That means the key space is dense enough |
|
to contain 8 nodes for every combination of the 20 top bits of node IDs.</p> |
|
<blockquote> |
|
<tt class="docutils literal">2^20 * 8 = 8388608</tt></blockquote> |
|
<p>By controlling that many IP addresses, an attacker could snoop any info-hash. |
|
By controlling 8 times that many IP addresses, an attacker could actually |
|
take over any info-hash.</p> |
|
<p>With IPv4, snooping would require a /8 IP block, giving access to 16.7 million |
|
Ips.</p> |
|
<p>Another problem with hashing the IP is that multiple users behind a NAT are |
|
forced to run their DHT nodes on the same node ID.</p> |
|
</div> |
|
<div class="section" id="node-id-restriction"> |
|
<h1>Node ID restriction</h1> |
|
<p>In order to avoid the number node IDs controlled to grow linearly by the number |
|
of IPs, as well as allowing more than one node ID per external IP, the node |
|
ID can be restricted at each class level of the IP.</p> |
|
<p>The expression to calculate a valid ID prefix (from an IPv4 address) is:</p> |
|
<pre class="literal-block"> |
|
sha1((ip & 0x01071f7f) .. r) |
|
</pre> |
|
<p>And for an IPv6 address (<tt class="docutils literal">ip</tt> is the high 64 bits of the address):</p> |
|
<pre class="literal-block"> |
|
sha1((ip & 0x000103070f1f3f7f) .. r) |
|
</pre> |
|
<p><tt class="docutils literal">r</tt> is a random number in the range [0, 7]. The resulting integer, |
|
representing the masked IP address is supposed to be big-endian before |
|
hashed. The ".." means concatenation.</p> |
|
<p>The details of implementing this is to evaluate the expression, store the |
|
result in a big endian 64 bit integer and hash those 8 bytes with SHA-1.</p> |
|
<p>The first 4 bytes of the node ID used in the DHT MUST match the first 4 |
|
bytes in the resulting hash. The last byte of the hash MUST match the |
|
random number (<tt class="docutils literal">r</tt>) used to generate the hash.</p> |
|
<img alt="ip_id_v4.png" src="ip_id_v4.png" /> |
|
<img alt="ip_id_v6.png" src="ip_id_v6.png" /> |
|
<p>Example code code for calculating a valid node ID:</p> |
|
<pre class="literal-block"> |
|
uint8_t* ip; // our external IPv4 or IPv6 address (network byte order) |
|
int num_octets; // the number of octets to consider in ip (4 or 8) |
|
uint8_t node_id[20]; // resulting node ID |
|
|
|
uint8_t v4mask[] = { 0x01, 0x07, 0x1f, 0x7f }; |
|
uint8_t v6mask[] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f }; |
|
uint8_t* mask = num_octets == 4 ? v4_mask : v8_mask; |
|
|
|
for (int i = 0; i < num_octets; ++i) |
|
ip[i] &= mask[i]; |
|
|
|
SHA_CTX ctx; |
|
SHA1_Init(&ctx); |
|
SHA1_Update(&ctx, (unsigned char*)ip, num_octets); |
|
uint32_t rand = rand() & 0xff; |
|
uint8_t r = rand & 0x7; |
|
SHA1_Update(&ctx, (unsigned char*)&r, 1); |
|
SHA1_Final(&ctx, node_id); |
|
for (int i = 4; i < 19; ++i) node_id[i] = std::rand(); |
|
node_id[19] = rand; |
|
</pre> |
|
<p>test vectors:</p> |
|
<pre class="literal-block"> |
|
IP rand example node ID |
|
============ ===== ========================================== |
|
124.31.75.21 1 <strong>f766f9f5</strong> 0c5d6a4ec8a88e4c6ab4c28b95eee4 <strong>01</strong> |
|
21.75.31.124 86 <strong>7ee04779</strong> 4e7a08645677bbd1cfe7d8f956d532 <strong>56</strong> |
|
65.23.51.170 22 <strong>76a626ff</strong> bc8f112a3d426c84764f8c2a1150e6 <strong>16</strong> |
|
84.124.73.14 65 <strong>beb4e619</strong> 1bb1fe518101ceef99462b947a01ff <strong>41</strong> |
|
43.213.53.83 90 <strong>ace5613a</strong> 5b7c4be0237986d5243b87aa6d5130 <strong>5a</strong> |
|
</pre> |
|
<p>The bold parts of the node ID are the important parts. The rest are |
|
random numbers.</p> |
|
</div> |
|
<div class="section" id="bootstrapping"> |
|
<h1>bootstrapping</h1> |
|
<p>In order to set ones initial node ID, the external IP needs to be known. This |
|
is not a trivial problem. With this extension, <em>all</em> DHT requests whose node |
|
ID does not match its IP address MUST be serviced and MUST also include one |
|
extra result value (inside the <tt class="docutils literal">r</tt> dictionary) called <tt class="docutils literal">ip</tt>. The IP field |
|
contains the raw (big endian) byte representation of the external IP address. |
|
This is the same byte sequence used to verify the node ID.</p> |
|
<p>A DHT node which receives an <tt class="docutils literal">ip</tt> result in a request SHOULD consider restarting |
|
its DHT node with a new node ID, taking this IP into account. Since a single node |
|
can not be trusted, there should be some mechanism of determining whether or |
|
not the node has a correct understanding of its external IP or not. This could |
|
be done by voting, or only restart the DHT once at least a certain number of |
|
nodes, from separate searches, tells you your node ID is incorrect.</p> |
|
</div> |
|
<div class="section" id="enforcement"> |
|
<h1>enforcement</h1> |
|
<p>Once enforced, write tokens from peers whose node ID does not match its external |
|
IP should be considered dropped. In other words, a peer that uses a non-matching |
|
ID MUST never be used to store information on, regardless of which request. In the |
|
original DHT specification only <tt class="docutils literal">announce_peer</tt> stores data in the network, |
|
but any future extension which stores data in the network SHOULD use the same |
|
restriction.</p> |
|
<p>Any peer on a local network address is exempt from this node ID verification. |
|
This includes the following IP blocks:</p> |
|
<dl class="docutils"> |
|
<dt>10.0.0.0/8</dt> |
|
<dd>reserved for local networks</dd> |
|
<dt>172.16.0.0/12</dt> |
|
<dd>reserved for local networks</dd> |
|
<dt>192.168.0.0/16</dt> |
|
<dd>reserved for local networks</dd> |
|
<dt>169.254.0.0/16</dt> |
|
<dd>reserved for self-assigned IPs</dd> |
|
<dt>127.0.0.0/8</dt> |
|
<dd>reserved for loopback</dd> |
|
</dl> |
|
</div> |
|
<div class="section" id="backwards-compatibility-and-transition"> |
|
<h1>backwards compatibility and transition</h1> |
|
<p>During some transition period, this restriction should not be enforced, and |
|
peers whose node ID does not match this formula relative to their external IP |
|
should not be blocked.</p> |
|
<p>Requests from peers whose node ID does not match their external IP should |
|
always be serviced, even after the transition period. The attack this protects |
|
from is storing data on an attacker's node, not servicing an attackers request.</p> |
|
</div> |
|
<div class="section" id="forward-compatibility"> |
|
<h1>forward compatibility</h1> |
|
<p>If the total size of the DHT grows to the point where the inherent size limit |
|
in this proposal is too small, the modulus constants can be updated in a new |
|
proposal, and another transition period where both sets of modulus constants |
|
are accepted.</p> |
|
</div> |
|
</div> |
|
<div id="footer"> |
|
<span>Copyright © 2005 Rasterbar Software.</span> |
|
</div> |
|
</div> |
|
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> |
|
</script> |
|
<script type="text/javascript"> |
|
_uacct = "UA-1599045-1"; |
|
urchinTracker(); |
|
</script> |
|
</div> |
|
</body> |
|
</html>
|
|
|