Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve spam protections #284

Merged
merged 15 commits into from
Apr 20, 2020
Merged

Improve spam protections #284

merged 15 commits into from
Apr 20, 2020

Conversation

vyzo
Copy link
Collaborator

@vyzo vyzo commented Apr 20, 2020

Currently we return a PRUNE for every GRAFT we are rejecting, even if the GRAFTs are coming too fast, in flood style. Similarly, we are asking for every (unknown) message advertised in an IHAVE even if these are too many, and potentially a flood.

This patch adds rudimentary protections for both, closing the (single node) flood holes:

  • We limit the number of message ids we emit in an IHAVE and accept in an IWANT per heartbeat to GossipSubMaxIHaveLength; default is 5000 message ids, which would take some 200KB.
    We also only accept up to GossipSubMaxIHaveMessages IHAVE messages per heartbeat from each peer.
  • We stop emitting PRUNES if a GRAFT is coming too fast since the last backoff, controlled by the GossipSubGraftFloodThreshold parameter. We also add an extended backoff penalty to avoid GRAFTING ourselves on this peer for a while.

Also merges in #283 which tests the spam protections.

@vyzo vyzo requested review from dirkmc and raulk April 20, 2020 09:23
@vyzo vyzo mentioned this pull request Apr 20, 2020
4 tasks
@vyzo vyzo force-pushed the feat/spam-protections branch 2 times, most recently from de9ed51 to cb1c181 Compare April 20, 2020 11:42
@vyzo vyzo force-pushed the feat/spam-protections branch from cb1c181 to dfb15de Compare April 20, 2020 11:45
Copy link
Member

@raulk raulk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few comments.

// to protect from IHAVE floods. You should adjust this value from the default if your
// system is pushing more than 5000 messages in GossipSubHistoryGossip heartbeats; with the
// defaults this is 1666 messages/s.
GossipSubMaxIHaveLength = 5000
Copy link
Member

@raulk raulk Apr 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related question: do we track inflight IWANTs? My rationale is that if we are poorly connected to the mesh and we recurrently only hear about a subset of messages via gossip, we might end up asking many peers for the same message at once, unless we deduplicate inflight requests.

If we don't, we'd be selfishly causing more traffic than necessary. However, I acknowledge this is tricky logic to implement, because it needs to factor in many concerns:

  • What if the peer we ask never sends back the message?
  • Do we queue up other candidates we know we can fall back on?
  • What is the grace period? And how does it relate to window sliding? (by the time we fall back to the next candidate, the message might have slid away from the cache)
  • Memory footprint of this new state to maintain.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we are not tracking in flight IWANTs.
I agree that we do want to track them, and it will make it much easier to respond to distributed IHAVE floods as well.
I'll open an issue so that we can tackle this, as it is rather complex and I want to think a bit about it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow up in #285.

gossip: make(map[peer.ID][]*pb.ControlIHave),
control: make(map[peer.ID]*pb.ControlMessage),
backoff: make(map[string]map[peer.ID]time.Time),
peerhave: make(map[peer.ID]int),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note for reviewers: peerhave is what was added here. GitHub diffs don't make it easy to hunt down the change :D

gossipsub.go Show resolved Hide resolved
gossipsub.go Show resolved Hide resolved
gossipsub.go Show resolved Hide resolved
gossipsub.go Outdated Show resolved Hide resolved
// refresh the backoff
gs.addBackoff(p, topic)
// check the flood cutoff -- is the GRAFT coming too fast?
floodCutoff := expire.Add(GossipSubGraftFloodThreshold - GossipSubPruneBackoff)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another (possibly more correct) way of implementing this could be sending back the desired backoff time to a peer at the time of PRUNE, and penalising peers who do not honour it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it would be nice of us to send the backoff period and it makes things more robust for peers with different values of it.
It will take a protocol change however, so let me consider a bit and do it in a follow up PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow up in #286.

gossipsub.go Outdated Show resolved Hide resolved
Copy link
Contributor

@dirkmc dirkmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

In Bitswap we try to "keep peers busy" when serving blocks, meaning we send messages to whichever peer has the least amount of data in its send queue. It may make sense to follow an analogous approach here, whereby when deciding how many messages to send to each peer we prioritize them by score, and then round-robin

@vyzo vyzo merged commit 235c28f into master Apr 20, 2020
@vyzo vyzo deleted the feat/spam-protections branch April 20, 2020 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants