mirror of
https://github.com/logos-messaging/go-libp2p-pubsub.git
synced 2026-01-02 12:53:09 +00:00
add backoff penalty for GRAFT floods
This commit is contained in:
parent
9ab44c5069
commit
a645afd1b3
22
gossipsub.go
22
gossipsub.go
@ -76,6 +76,9 @@ var (
|
||||
// less than GossipSubPruneBackoff.
|
||||
GossipSubGraftFloodThreshold = 10 * time.Second
|
||||
|
||||
// backoff penalty for GRAFT floods
|
||||
GossipSubPruneBackoffPenalty = time.Hour
|
||||
|
||||
// Maximum number of messages to include in an IHAVE message. Also controls the maximum
|
||||
// number of IHAVE ids we will accept and request with IWANT from a peer within a heartbeat,
|
||||
// to protect from IHAVE floods. You should adjust this value from the default if your
|
||||
@ -503,15 +506,17 @@ func (gs *GossipSubRouter) handleGraft(p peer.ID, ctl *pb.ControlMessage) []*pb.
|
||||
expire, backoff := gs.backoff[topic][p]
|
||||
if backoff && now.Before(expire) {
|
||||
log.Debugf("GRAFT: ignoring backed off peer %s", p)
|
||||
// refresh the backoff
|
||||
gs.addBackoff(p, topic)
|
||||
// check the flood cutoff -- is the GRAFT coming too fast?
|
||||
floodCutoff := expire.Add(GossipSubGraftFloodThreshold - GossipSubPruneBackoff)
|
||||
if now.Before(floodCutoff) {
|
||||
// no prune, and no PX either
|
||||
doPX = false
|
||||
// and a penalty so that we don't GRAFT on this peer ourselves for a while
|
||||
gs.addBackoffPenalty(p, topic)
|
||||
} else {
|
||||
prune = append(prune, topic)
|
||||
// refresh the backoff
|
||||
gs.addBackoff(p, topic)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@ -577,12 +582,23 @@ func (gs *GossipSubRouter) handlePrune(p peer.ID, ctl *pb.ControlMessage) {
|
||||
}
|
||||
|
||||
func (gs *GossipSubRouter) addBackoff(p peer.ID, topic string) {
|
||||
gs.doAddBackoff(p, topic, GossipSubPruneBackoff)
|
||||
}
|
||||
|
||||
func (gs *GossipSubRouter) addBackoffPenalty(p peer.ID, topic string) {
|
||||
gs.doAddBackoff(p, topic, GossipSubPruneBackoffPenalty)
|
||||
}
|
||||
|
||||
func (gs *GossipSubRouter) doAddBackoff(p peer.ID, topic string, interval time.Duration) {
|
||||
backoff, ok := gs.backoff[topic]
|
||||
if !ok {
|
||||
backoff = make(map[peer.ID]time.Time)
|
||||
gs.backoff[topic] = backoff
|
||||
}
|
||||
backoff[p] = time.Now().Add(GossipSubPruneBackoff)
|
||||
expire := time.Now().Add(interval)
|
||||
if backoff[p].Before(expire) {
|
||||
backoff[p] = expire
|
||||
}
|
||||
}
|
||||
|
||||
func (gs *GossipSubRouter) pxConnect(peers []*pb.PeerInfo) {
|
||||
|
||||
@ -318,8 +318,11 @@ func TestGossipsubAttackGRAFTDuringBackoff(t *testing.T) {
|
||||
GossipSubPruneBackoff = 200 * time.Millisecond
|
||||
originalGossipSubGraftFloodThreshold := GossipSubGraftFloodThreshold
|
||||
GossipSubGraftFloodThreshold = 100 * time.Millisecond
|
||||
originalGossipSubPruneBackoffPenalty := GossipSubPruneBackoffPenalty
|
||||
GossipSubPruneBackoffPenalty = 500 * time.Millisecond
|
||||
defer func() {
|
||||
GossipSubPruneBackoff = originalGossipSubPruneBackoff
|
||||
GossipSubPruneBackoffPenalty = originalGossipSubPruneBackoffPenalty
|
||||
GossipSubGraftFloodThreshold = originalGossipSubGraftFloodThreshold
|
||||
}()
|
||||
|
||||
@ -414,8 +417,8 @@ func TestGossipsubAttackGRAFTDuringBackoff(t *testing.T) {
|
||||
t.Fatalf("Expected %d PRUNE messages but got %d", 1, pc)
|
||||
}
|
||||
|
||||
// Wait until after the prune backoff period
|
||||
time.Sleep(GossipSubPruneBackoff * 2)
|
||||
// Wait until after the prune backoff penalty period
|
||||
time.Sleep(GossipSubPruneBackoffPenalty + time.Second)
|
||||
|
||||
// Send a GRAFT again to attempt to rejoin the mesh
|
||||
writeMsg(&pb.RPC{
|
||||
@ -430,6 +433,19 @@ func TestGossipsubAttackGRAFTDuringBackoff(t *testing.T) {
|
||||
if pc != 1 {
|
||||
t.Fatalf("Expected %d PRUNE messages but got %d", 1, pc)
|
||||
}
|
||||
|
||||
// make sure we are in the mesh of the legit host now
|
||||
res := make(chan bool)
|
||||
ps.eval <- func() {
|
||||
mesh := ps.rt.(*GossipSubRouter).mesh[mytopic]
|
||||
_, inMesh := mesh[attacker.ID()]
|
||||
res <- inMesh
|
||||
}
|
||||
|
||||
inMesh := <-res
|
||||
if !inMesh {
|
||||
t.Fatal("Expected to be in the mesh of the legitimate host")
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user