-
Notifications
You must be signed in to change notification settings - Fork 899
Penalize peers that send an invalid rpc request #6986
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
base: unstable
Are you sure you want to change the base?
Conversation
ConnectionEvent::ListenUpgradeError(e) => { | ||
if matches!(e.error, RPCError::InvalidData(_)) { | ||
// Peer is not complying with the protocol. Notify the application and disconnect. | ||
let inbound_substream_id = self.current_inbound_substream_id; | ||
self.current_inbound_substream_id.0 += 1; | ||
|
||
self.events_out.push(HandlerEvent::Err(HandlerErr::Inbound { | ||
id: inbound_substream_id, | ||
proto: Protocol::DataColumnsByRange, // FIXME: replace this hardcoded protocol | ||
error: e.error, | ||
})); | ||
self.shutdown(None); | ||
} | ||
} |
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.
// FIXME: replace this hardcoded protocol
The RPCError::InvalidData
error is emitted by the inbound codec here. The problem I'm facing is that the handler cannot determine which protocol the invalid data belongs to. I think changing the type of InboundUpgrade::Error
from RPCError
to (Protocol, RPCError)
might solves this. What do you think?
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.
Updated in 2ff8cf2
This pull request has merge conflicts. Could you please resolve them @ackintosh? 🙏 |
# Conflicts: # beacon_node/lighthouse_network/tests/rpc_tests.rs
Some required checks have failed. Could you please take a look @ackintosh? 🙏 |
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.
Hi Akihito, overall this looks good to me, sorry for the delay in the review, left some comments
ConnectionEvent::ListenUpgradeError(e) => { | ||
if matches!(e.error.1, RPCError::InvalidData(_)) { |
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.
you don't need the nested matches Akihito, you can do:
ConnectionEvent::ListenUpgradeError(e) => { | |
if matches!(e.error.1, RPCError::InvalidData(_)) { | |
ConnectionEvent::ListenUpgradeError(ListenUpgradeError { | |
error: (_, RPCError::IoError(_)), | |
.. | |
}) => { |
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.
Refactored in 7e09c47
@@ -652,7 +652,7 @@ where | |||
E: EthSpec, | |||
{ | |||
type Output = InboundOutput<TSocket, E>; | |||
type Error = RPCError; | |||
type Error = (Protocol, RPCError); |
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.
why use a tuple instead of putting the Protocol
inside RPCError
?
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.
I saw a struct that has Protocol
and RPCError
as separate fields like this, and I thought it was a reasonable way to represent what the error is and where it happened separately:
lighthouse/beacon_node/lighthouse_network/src/rpc/handler.rs
Lines 938 to 946 in c56c63e
self.events_out.push(HandlerEvent::Err(HandlerErr::Inbound { | |
id: self.current_inbound_substream_id, | |
proto: Protocol::BlocksByRange, | |
error: RPCError::InvalidData(format!( | |
"requested exceeded limit. allowed: {}, requested: {}", | |
max_allowed, | |
request.count() | |
)), | |
})); |
Issue Addressed
Since #6847, invalid
BlocksByRange
/BlobsByRange
requests, which do not comply with the spec, are handled in the Handler. Any peer that sends an invalid request is penalized and disconnected.However, other kinds of invalid rpc request, which result in decoding errors, are just dropped. No penalty is applied and the connection with the peer remains.
Proposed Changes
I have added handling for the
ListenUpgradeError
event to notify the application of anRPCError:InvalidData
error and disconnect to the peer that sent the invalid rpc request.I also added tests for handling invalid rpc requests.