-
Notifications
You must be signed in to change notification settings - Fork 175
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
[Networking] GossipSub Publish Message Validation (Unknown Topic Spam) #4720
Conversation
…ossiping-unknown-invalid-topics
…builder -> control message validaiton inspector
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #4720 +/- ##
==========================================
+ Coverage 52.96% 55.86% +2.90%
==========================================
Files 754 945 +191
Lines 68045 88259 +20214
==========================================
+ Hits 36037 49304 +13267
- Misses 29289 35243 +5954
- Partials 2719 3712 +993
Flags with carried forward coverage won't be shown. Click here to find out more.
☔ View full report in Codecov by Sentry. |
….com:onflow/flow-go into khalil/6798-gossiping-unknown-invalid-topics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall, I have a suggestion about the dependency inversion that is imposed through SetSubscriptions
. Please find my comment here.
integration/tests/bft/gossipsub/signature/requirement/orchestrator.go
Outdated
Show resolved
Hide resolved
@@ -310,7 +322,8 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, e | |||
g.metricsCfg.Metrics, | |||
g.metricsCfg.HeroCacheFactory, | |||
g.networkType, | |||
g.idProvider) | |||
g.idProvider, | |||
g.subscriptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p2p.Subscriptions
object to the GossipSub RPC inspector. Doing so violates the Dependency Inversion Principle and the Interface Segregation Principle. The p2p.Subscriptions
interface is higher-level and should not be depended upon by a lower-level component like the RPC inspector. This design choice risks circular dependencies and also breaks encapsulation, as methods irrelevant to the RPC inspector get exposed.
Moreover, using p2p.Subscription
to query active subscriptions is unreliable, as it queries the Flow node than the GossipSub router; it's more accurate to consult the underlying pubsub router to avoid any false-positive due to glitches. To address this, I suggest refactoring to use the PubSubAdapter.GetTopics()
method.
Dependency injection is required between the RPC inspector and the GossipSub adapter. To solve this, inject gossipSub.GetTopics()
as a topic oracle within the RPC inspector by adding a method SetTopicOracle(topicOracle func()[]string)
to the GossipSubInspectorSuite
interface:
type GossipSubInspectorSuite interface {
// existing methods ...
// SetTopicOracle sets the topic oracle of the gossipsub inspector suite.
// The topic oracle is used to determine the list of topics that the node is subscribed to.
// If an oracle is not set, the node will not be able to determine the list of topics that the node is subscribed to.
// If an oracle is already set, a fatal error is logged.
SetTopicOracle(topicOracle func()[]string)
}
Inject this dependency in the codebase like so:
gossipSub, err := g.gossipSubFactory(ctx, g.logger, g.h, gossipSubConfigs, inspectorSuite)
if err != nil {
return nil, fmt.Errorf("could not create gossipsub: %w", err)
}
inspectorSuite.SetTopicOracle(gossipSub.GetTopics())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for applying the comment. However, there is still a minor concern. In reviewing the interfaces GossipSubInspectorSuite
and InspectorTopicOracle
, it's apparent that the encapsulation of SetTopicOracle
within a separate interface does not provide a coherent or meaningful abstraction.
The InspectorTopicOracle
has a single method SetTopicOracle
, which is more of a configuration aspect rather than a functional capability deserving a separate interface. This violates the Single Responsibility Principle as it doesn’t represent a distinct responsibility that warrants a separate abstraction. Also, the name InspectorTopicOracle
implies a broader functionality than merely setting a topic oracle. However, the sole method it encapsulates doesn't justify the semantics of an oracle. In this case, the oracle interface generally implies a source of information or decision-making capability, however, the capability this interface abstracts does not behave as a source of information.
My suggestion is to directly integrate the SetTopicOracle
method into GossipSubInspectorSuite
, which makes the design becomes more intuitive:
type GossipSubInspectorSuite interface {
// existing methods ...
// SetTopicOracle sets the topic oracle of the gossipsub inspector suite.
// The topic oracle is used to determine the list of topics that the node is subscribed to.
// If an oracle is not set, the node will not be able to determine the list of topics that the node is subscribed to.
// If an oracle is already set, a fatal error is logged.
SetTopicOracle(topicOracle func()[]string)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
network/p2p/inspector/validation/control_message_validation_inspector_test.go
Show resolved
Hide resolved
network/p2p/inspector/validation/control_message_validation_inspector_test.go
Outdated
Show resolved
Hide resolved
network/p2p/inspector/validation/control_message_validation_inspector_test.go
Show resolved
Hide resolved
insecure/integration/functional/test/gossipsub/rpc_inspector/validation_inspector_test.go
Outdated
Show resolved
Hide resolved
insecure/integration/functional/test/gossipsub/rpc_inspector/validation_inspector_test.go
Outdated
Show resolved
Hide resolved
network/p2p/inspector/validation/control_message_validation_inspector_test.go
Show resolved
Hide resolved
network/p2p/inspector/validation/control_message_validation_inspector_test.go
Outdated
Show resolved
Hide resolved
network/p2p/inspector/validation/control_message_validation_inspector_test.go
Outdated
Show resolved
Hide resolved
network/p2p/inspector/validation/control_message_validation_inspector_test.go
Outdated
Show resolved
Hide resolved
Co-authored-by: Yahya Hassanzadeh, Ph.D. <yhassanzadeh@ieee.org>
Co-authored-by: Yahya Hassanzadeh, Ph.D. <yhassanzadeh@ieee.org>
…spector_test.go Co-authored-by: Misha <15269764+gomisha@users.noreply.github.com>
…spector_test.go Co-authored-by: Misha <15269764+gomisha@users.noreply.github.com>
…spector_test.go Co-authored-by: Misha <15269764+gomisha@users.noreply.github.com>
…spector_test.go Co-authored-by: Misha <15269764+gomisha@users.noreply.github.com>
….com:onflow/flow-go into khalil/6798-gossiping-unknown-invalid-topics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks very good, please address this comment before merging.
….com:onflow/flow-go into khalil/6798-gossiping-unknown-invalid-topics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing all my comments.
…ossiping-unknown-invalid-topics
….com:onflow/flow-go into khalil/6798-gossiping-unknown-invalid-topics
This PR adds RPC Publish messages validation to the control message validation inspector. When a node receives messages via a direct RPC from a remote peer, it processes them sequentially. However, if a message is on a topic the node has not subscribed, it is discarded. While this may seem harmless, an attacker can exploit this behavior to stage a Denial-of-Service attack by spamming a victim with a high volume of messages on unknown/invalid topics. This forces the victim to consume resources processing each message only to discard them. The control message validation inspector will now inspect a sample of the RPC publish messages and disseminate an invalid control message notification when the number of invalid messages exceeds the configured threshold.
This PR
gossipsub-rpc-message-max-sample-size
: The max sample size used for RPC message validation. If the total number of RPC messages exceeds this value a sample will be taken but messages will not be truncatedgossipsub-rpc-message-error-threshold
: The threshold at which an error will be returned if the number of invalid RPC messages exceeds this valueref: https://github.com/dapperlabs/flow-go/issues/6798