On Thursday 24 June 2010 04:05:48 Evan Daniel wrote:
> On Wed, Jun 23, 2010 at 5:43 PM, Matthew Toseland
> <t...@amphibian.dyndns.org> wrote:
> > On Wednesday 23 June 2010 20:33:50 Sich wrote:
> >> Le 23/06/2010 21:01, Matthew Toseland a écrit :
> >> > Insert a random, safe key
> >> > This is much safer than the first option, but the key will be different 
> >> > every time you or somebody else inserts the key. Use this if you are the 
> >> > original source of some sensitive data.
> >> >
> >> >
> >> Very interesting for filesharing if we split the file.
> >> When some chunk are lost, you have only to reinsert those who are
> >> lost... But then we use much datastore... But it's more secure...
> >> Loosing datastore space is a big problem no ?
> >
> > If some people use the new key and some use the old then it's a problem. If 
> > everyone uses one or the other it isn't. I guess this is another reason to 
> > use par files etc (ugh).
> >
> > The next round of major changes (probably in 1255) will introduce 
> > cross-segment redundancy which should improve the reliability of  really 
> > big files.
> >
> > Long term we may have selective reinsert support, but of course that would 
> > be nearly as unsafe as reinserting the whole file to the same key ...
> >
> > If you're building a reinsert-on-demand based filesharing system let me 
> > know if you need any specific functionality...
> The obvious intermediate is to reinsert a small portion of a file.
> The normal case is (and will continue to be) that when a file becomes
> unretrievable, it's because one or more segments is only a couple
> blocks short of being retrievable.  If you reinsert say 8 blocks out
> of each segment (1/32 of the file), you'll be reinserting on average 4
> unretrievable blocks from each segment.  That should be enough in a
> lot of cases.  This is probably better than selective reinsert (the
> attacker doesn't get to choose which blocks you reinsert as easily),
> though it does mean reinserting more blocks (8 per segment when merely
> reinserting the correct 3 blocks might suffice).
> The simple defense against a mobile opennet attacker that has been
> proposed before would be particularly well suited to partial
> randomized reinserts.  The insert comes with a time (randomized per
> block, to some time a bit before the reinsert started), and is only
> routed along connections that were established before that time, until
> it reaches some relatively low HTL (10?).  This prevents the attacker
> from moving during the insert.  On a large file that takes a long time
> to insert, this is problematic, because there aren't enough
> connections that are old enough to route along.  For a partial
> reinsert, this is less of a concern, simply because it doesn't take as
> long.

This is a very good point. What if we can improve on this further?

By implementing long-term requests, we could have *all* the requests for a 
splitfile go out *at once*, be routed immediately, and then return the data 
over a long period. This means that:
1) The data needs to be trickled back even if nodes go offline - either via 
rerouting (but consider carefully how to make this safe, e.g. establishing 
backup routes at the time, or using a node identifier for the next hop so we 
can reroute via FOAFs without involving the originator so not giving a data 
point away), or by waiting for the nodes to come back online.
2) Load management needs to be able to deal with the fact that we have 
thousands of requests in flight. This means it may not work on opennet, because 
there is no underlying trust; although we could maybe have a reputation system 
to build up some amount of trust. Trust can be translated into capacity limits.
3) The mobile attacker defence holds: If all the requests get routed inside a 
few minutes, and then return data along fixed paths, the attacker has no chance 
of moving towards the originator. And this works even for fairly big files, 
without the overhead of tunnels, for requests and inserts of predictable data.
4) Overheads should be reasonable, because we can bundle a large number of 
requests together efficiently.
5) We get "burst" behaviour. If we have a fast connection, the data will be 
returned fast.
6) We get slow-return behaviour. In many cases it will take a long time for the 
data to trickle back. At each hop it will make sense to send one key at a time, 
if we happen to have multiple keys fully available.
7) The node needs to be able to cope with a large number of requests pending: 
We can keep the current code for routing them but once we have a route, the 
requests as well as the transfers need to be threadless.
8) We need to be able to specify that we want a fast response on a request and 
that it should not get queued and trickled through/around offline nodes.
9) We need a different way to handle timeouts. At the moment we detect when a 
node is busted by not getting the data within X period. If the node has a 
backlog of thousands of blocks then this is clearly not going to work. However 
we do expect a response eventually. So we need some way to take this into 
account and identify problems.

This is an elaboration on a chain of thought that goes way back, thanks 
particularly to the person who came up with the mobile attacker countermeasure, 
but we've been pondering passive requests for a long time ... It also combines 
ideas from CCN's hands off load management and various people who have 
suggested load management changes over the years e.g. on Frost...

This looks like a major rewrite, maybe 0.10 era, but it would be worth it, the 
potential benefits are rather enormous...

Of course we'd still need tunnels for e.g. Frost posts, stuff where you have 
multiple completed tasks over a period where the attacker could get a sample 
from each one.


1. We send requests when we have requests. We queue them as little as possible. 
Of course we have a queue of stuff we want to fetch - we recognise blocks that 
we want - but in terms of the actual queues of requests to send, we minimise 
this - stuff is sent immediately or near to immediately.
2. We send all the requests for a single bundle at once. We queue other bundles 
if necessary to fit into our capacity limit. If two bundles are related (e.g. 
different levels of a splitfile or frost posts), we try to send them close 
3. Any request in a bundle has a starting timestamp, which is the same or very 
close for all the requests in the bundle. We don't route to any node that has 
connected since the starting timestamp.
4. Any given link (connection between a pair of nodes) has a capacity in 
outstanding requests. On darknet this is fixed, or depends on the trust level 
for the connection. On opennet this is fixed but much lower, or depends on some 
sort of trust/history/reputation algorithm.
5. Requests (and inserts) are routed reasonably quickly, but may be queued 
briefly if necessary to achieve good routing.
6. Once a request has reached its destination, where the data is available, it 
is converted into a pending transfer. We exit the request thread and handle it 
7. On any link there may be a large number of pending transfers, up to a given 
capacity. If a request fails, we free up the capacity; hence we keep the number 
of pending transfers under the limit. As long as we have data to transfer, we 
transfer it. If we have a full blocks (e.g. if we are the data source), we 
transfer that first, then look for another one, then look for other blocks etc.
8. As long as data is being transferred over a link, and requests are being 
completed regularly (this is why we try to transfer one block at a time rather 
than multiplexing everything), we don't timeout any of the transfers. We may 
have to incorporate age into the error detection somehow.
9. As a request reaches each hop, we give it the identifier for a node for an 
alternative path. This can either be the previous hop or another node which has 
agreed to be a fallback path, depending on security requirements. The node 
identifier must be accessible within two hops of the node being routed to. If 
the predecessor node goes offline, we will try to route to the fallback path. 
If the fallback path is offline, we check whether we have the persistent flag 
(which may be disallowed on opennet): If we have the persistent flag we suspend 
the request until either the predecessor or the fallback comes online, and 
write it to disk. If we don't have the persistent flag, we store the returning 
data locally only, and penalise the predecessor if it comes back online. Once 
we have sent a request we are committed to accepting the returned data, this is 
essential to prevent probing-based censorship attacks. This is why opennet is a 
problem with this scheme: If you get any nontrivial trust from announcing, you 
can announce, connect to nodes, use that capacity to DoS them and then 
disconnect and talk to another node. However, if everyone has fast links, it 
could return data very quickly on opennet...
10. If our capacity limits are low then we will have to send requests (or 
inserts) for big files in a series of separate bundles. We warn the user that 
we cannot guarantee full security, and get a confirmation. Unless seclevel = 
LOW, in which case we just proceed anyway without asking. One interesting point 
is that this allows us to quantify the loss of security on opennet, although 
arguably that will just result in more people getting connections to random 
strangers out of band, many of whom will turn out to be NSA...

Of course there are security risks with bursting, in that if an attacker has 
access to traffic analysis as well as nodes close to the originator, he may be 
able to tie the two together. But the above is not limited to bursting: The 
principle is we burst the routing phase and then return the data as fast or as 
slow as possible. It is compatible with sneakernet, it is compatible with CBR 

Ideas? Challenges? Suggestions for how to deal with opennet in this framework?

Attachment: signature.asc
Description: This is a digitally signed message part.

Devl mailing list

Reply via email to