mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-28 05:47:51 +08:00
dht: split out online record verification
Online record verification -- meaning record verification that might cause messages to other peers -- presents a way to perform an attack on a dht node: forge a record and make the node attempt to fetch the public key to verify. This becomes a very powerful amplification attack if online verification is done for records _received passively_. This means records that were received as the result of a PUT_VALUE or ADD_PROVIDER. Thus we only accept records we can verify offline (whose public keys we already have). In practice this is not at all a problem for us, because typical connections are encrypted: we've already exchanged public keys.
This commit is contained in:
parent
cb2e560c32
commit
0cdc2e0adf
@ -147,8 +147,8 @@ func (dht *IpfsDHT) getValueOrPeers(ctx context.Context, p peer.ID,
|
||||
// Success! We were given the value
|
||||
log.Debug("getValueOrPeers: got value")
|
||||
|
||||
// make sure record is still valid
|
||||
err = dht.verifyRecord(record)
|
||||
// make sure record is valid.
|
||||
err = dht.verifyRecordOnline(ctx, record)
|
||||
if err != nil {
|
||||
log.Error("Received invalid record!")
|
||||
return nil, nil, err
|
||||
@ -156,19 +156,20 @@ func (dht *IpfsDHT) getValueOrPeers(ctx context.Context, p peer.ID,
|
||||
return record.GetValue(), nil, nil
|
||||
}
|
||||
|
||||
// TODO decide on providers. This probably shouldn't be happening.
|
||||
// TODO what did "this" mean? i think it's the notion of receiving
|
||||
// a list of providers and then immediately requesting that value
|
||||
// from them. providers a higher level construct for dht clients:
|
||||
// the dht shouldn't be _using_ providers... -@jbenet 2014-12-20
|
||||
if prv := pmes.GetProviderPeers(); prv != nil && len(prv) > 0 {
|
||||
val, err := dht.getFromPeerList(ctx, key, prv)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
log.Debug("getValueOrPeers: get from providers")
|
||||
return val, nil, nil
|
||||
}
|
||||
// commenting out for now. i'm not sure this is correct -jbenet
|
||||
// // TODO decide on providers. This probably shouldn't be happening.
|
||||
// // TODO what did "this" mean? i think it's the notion of receiving
|
||||
// // a list of providers and then immediately requesting that value
|
||||
// // from them. providers a higher level construct for dht clients:
|
||||
// // the dht shouldn't be _using_ providers... -@jbenet 2014-12-20
|
||||
// if prv := pmes.GetProviderPeers(); prv != nil && len(prv) > 0 {
|
||||
// val, err := dht.getFromPeerList(ctx, key, prv)
|
||||
// if err != nil {
|
||||
// return nil, nil, err
|
||||
// }
|
||||
// log.Debug("getValueOrPeers: get from providers")
|
||||
// return val, nil, nil
|
||||
// }
|
||||
|
||||
// Perhaps we were given closer peers
|
||||
peers := pb.PBPeersToPeerInfos(pmes.GetCloserPeers())
|
||||
@ -189,43 +190,44 @@ func (dht *IpfsDHT) getValueSingle(ctx context.Context, p peer.ID,
|
||||
return dht.sendRequest(ctx, p, pmes)
|
||||
}
|
||||
|
||||
// TODO: Im not certain on this implementation, we get a list of peers/providers
|
||||
// from someone what do we do with it? Connect to each of them? randomly pick
|
||||
// one to get the value from? Or just connect to one at a time until we get a
|
||||
// successful connection and request the value from it?
|
||||
func (dht *IpfsDHT) getFromPeerList(ctx context.Context, key u.Key,
|
||||
peerlist []*pb.Message_Peer) ([]byte, error) {
|
||||
// commenting out until i figure out whether this is needed -jbenet
|
||||
// // TODO: Im not certain on this implementation, we get a list of peers/providers
|
||||
// // from someone what do we do with it? Connect to each of them? randomly pick
|
||||
// // one to get the value from? Or just connect to one at a time until we get a
|
||||
// // successful connection and request the value from it?
|
||||
// func (dht *IpfsDHT) getFromPeerList(ctx context.Context, key u.Key,
|
||||
// peerlist []*pb.Message_Peer) ([]byte, error) {
|
||||
|
||||
peerinfos := pb.PBPeersToPeerInfos(peerlist)
|
||||
for _, pinfo := range peerinfos {
|
||||
p := pinfo.ID
|
||||
if err := dht.ensureConnectedToPeer(ctx, p); err != nil {
|
||||
log.Errorf("getFromPeers error: %s", err)
|
||||
continue
|
||||
}
|
||||
// peerinfos := pb.PBPeersToPeerInfos(peerlist)
|
||||
// for _, pinfo := range peerinfos {
|
||||
// p := pinfo.ID
|
||||
// if err := dht.ensureConnectedToPeer(ctx, p); err != nil {
|
||||
// log.Errorf("getFromPeers error: %s", err)
|
||||
// continue
|
||||
// }
|
||||
|
||||
pmes, err := dht.getValueSingle(ctx, p, key)
|
||||
if err != nil {
|
||||
log.Errorf("getFromPeers error: %s\n", err)
|
||||
continue
|
||||
}
|
||||
// pmes, err := dht.getValueSingle(ctx, p, key)
|
||||
// if err != nil {
|
||||
// log.Errorf("getFromPeers error: %s\n", err)
|
||||
// continue
|
||||
// }
|
||||
|
||||
if record := pmes.GetRecord(); record != nil {
|
||||
// Success! We were given the value
|
||||
// if record := pmes.GetRecord(); record != nil {
|
||||
// // Success! We were given the value
|
||||
|
||||
err := dht.verifyRecord(record)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dht.providers.AddProvider(key, p)
|
||||
return record.GetValue(), nil
|
||||
}
|
||||
}
|
||||
return nil, routing.ErrNotFound
|
||||
}
|
||||
// err := dht.verifyRecord(ctx, record)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// dht.providers.AddProvider(key, p)
|
||||
// return record.GetValue(), nil
|
||||
// }
|
||||
// }
|
||||
// return nil, routing.ErrNotFound
|
||||
// }
|
||||
|
||||
// getLocal attempts to retrieve the value from the datastore
|
||||
func (dht *IpfsDHT) getLocal(key u.Key) ([]byte, error) {
|
||||
func (dht *IpfsDHT) getLocal(ctx context.Context, key u.Key) ([]byte, error) {
|
||||
|
||||
log.Debug("getLocal %s", key)
|
||||
v, err := dht.datastore.Get(key.DsKey())
|
||||
@ -246,7 +248,7 @@ func (dht *IpfsDHT) getLocal(key u.Key) ([]byte, error) {
|
||||
|
||||
// TODO: 'if paranoid'
|
||||
if u.Debug {
|
||||
err = dht.verifyRecord(rec)
|
||||
err = dht.verifyRecordLocally(rec)
|
||||
if err != nil {
|
||||
log.Errorf("local record verify failed: %s", err)
|
||||
return nil, err
|
||||
|
||||
Loading…
Reference in New Issue
Block a user