feat(wire): allow NodeInterface to request peer banning#872
feat(wire): allow NodeInterface to request peer banning#872Micah-Shallom wants to merge 1 commit intogetfloresta:masterfrom
Conversation
65d637f to
2256574
Compare
jaoleal
left a comment
There was a problem hiding this comment.
Thanks for taking a look at this.
|
|
||
| UserRequest::BanPeer((addr, port)) => { | ||
| let node_response = match self.handle_ban_peer(addr, port) { | ||
| Ok(_) => { |
There was a problem hiding this comment.
| Ok(_) => { | |
| Ok(()) => { |
| pub fn handle_ban_peer(&mut self, addr: IpAddr, port: u16) -> Result<(), WireError> { | ||
| let peer_id = self | ||
| .peers | ||
| .iter() | ||
| .find(|(_, peer)| addr == peer.address && port == peer.port) | ||
| .map(|(&peer_id, _)| peer_id); | ||
|
|
||
| match peer_id { | ||
| Some(peer_id) => { | ||
| self.disconnect_and_ban(peer_id)?; | ||
| Ok(()) | ||
| } | ||
| None => Err(WireError::PeerNotFoundAtAddress(addr, port)), | ||
| } | ||
| } |
There was a problem hiding this comment.
Here some suggestions:
I think that you can make port optional, you can also simplify the handling on 518.
/// Bans a peer for `T::BAN_TIME`.
pub fn handle_ban_peer(&mut self, addr: IpAddr, port: Option<u16>) -> Result<(), WireError> {
let peer_id = self
.peers
.iter()
.find(|(_, peer)| {
addr == peer.address && port.unwrap_or(get_port(&self.network)) == peer.port
})
.map(|(&peer_id, _)| peer_id);
match peer_id {
Some(peer_id) => self.disconnect_and_ban(peer_id),
None => Err(WireError::PeerNotFoundAtAddress(
addr,
port.unwrap_or(get_port(&self.network)),
)),
}
}Also, it appears that Bitcoin Core allows banning peers that arent known by the time. cc @Davidson-Souza
2256574 to
2beb1b9
Compare
|
hi @jaoleal ...thank you for your review.. i have addressed your suggestions. |
|
Okay, the changes LGTM. |
| Ok(()) | ||
| } | ||
|
|
||
| /// Bans a peer for `T::BAN_TIME`. |
There was a problem hiding this comment.
This works only for connected peers, right? I think the comment should mention that
| .peers | ||
| .iter() | ||
| .find(|(_, peer)| { | ||
| addr == peer.address && port.unwrap_or(Self::get_port(self.network)) == peer.port |
There was a problem hiding this comment.
Perhaps if a port isn't provided, we should ban all peers on that ip?
Wdyt @luisschwab?
There was a problem hiding this comment.
Just chiming in.
It seems that banning all peers is the way to go. Right now None is the default port number.
ban_peer(1.2.3.4, None) -> ban_peer(1.2.3.4, 8333)
But an attacker could reconnect on 1.2.3.4:50000
| Some(peer_id) => self.disconnect_and_ban(peer_id), | ||
| None => Err(WireError::PeerNotFoundAtAddress( | ||
| addr, | ||
| port.unwrap_or(Self::get_port(self.network)), |
There was a problem hiding this comment.
And return an option here
| UserRequest::BanPeer((addr, port)) => { | ||
| let node_response = match self.handle_ban_peer(addr, port) { | ||
| Ok(()) => { | ||
| info!("Banned peer {addr}:{}",port.unwrap_or(Self::get_port(self.network))); |
There was a problem hiding this comment.
| info!("Banned peer {addr}:{}",port.unwrap_or(Self::get_port(self.network))); | |
| info!("Banned peer {addr}:{}", port.unwrap_or(Self::get_port(self.network))); |
|
I think we should have an actual |
I think the proposed PR aggregates on floresta as it is. Cant we work on a We could open a tracking issue for that, I did some looking around of what we need to satisfy |
This interface (which is pretty much what #809 asks for) is not the same as Since you opened the issue, it's up to you whether this is useful or not. Edit: forgot to quote |
No, it takes extra arguments: https://developer.bitcoin.org/reference/rpc/setban.html I think these should also be exposed to the |
I meant it doesn't take a port, just an ip. I like the idea of adding a bantime. Banning forever isn't a good idea. Since the way to go seems to be adding the |
|
thanks for your reviews @jaoleal @Davidson-Souza @luisschwab ...seeing that the conversation is pretty much drifting into the banman implementation #820 . If y'all will be okay with me looking into it, i could go through the docs and the existing banman code over the next few days and see what i can come up with.. if thats fine i'll appreciate being assigned to it @luisschwab 🙏🏾🙏🏾 |
| .peers | ||
| .iter() | ||
| .find(|(_, peer)| { | ||
| addr == peer.address && port.unwrap_or(Self::get_port(self.network)) == peer.port |
There was a problem hiding this comment.
Just chiming in.
It seems that banning all peers is the way to go. Right now None is the default port number.
ban_peer(1.2.3.4, None) -> ban_peer(1.2.3.4, 8333)
But an attacker could reconnect on 1.2.3.4:50000
| Some(peer_id) => self.disconnect_and_ban(peer_id), | ||
| None => Err(WireError::PeerNotFoundAtAddress( | ||
| addr, | ||
| port.unwrap_or(Self::get_port(self.network)), |
There was a problem hiding this comment.
port.unwrap_or(Self::get_port(self.network)) is being computed twice.
| TransactionBroadcastResult(Result<Txid, AcceptToMempoolError>), | ||
|
|
||
| /// A response indicating whether a peer was successfully banned. | ||
| BanPeer(bool), |
There was a problem hiding this comment.
Have you considered a richer type instead a bool?
Only bool loses information. What happens with the error computed in handle_ban_peer if the bool is false?
| Disconnect((IpAddr, u16)), | ||
|
|
||
| /// Ban a peer by its address. | ||
| BanPeer((IpAddr, Option<u16>)), |
There was a problem hiding this comment.
This look odd to users of the API. If the default port inference is useful here, it should probably also apply to Disconnect (and also other operations like Remove) since they are "similar" operations.
Should we keep port an optional? Any take on that @Davidson-Souza, @luisschwab, @jaoleal ?
2beb1b9 to
3ba5b8e
Compare
Description
Closes #809.
Adds ban_peer() to NodeInterface, allowing external consumers to ban a peer by address and port. Follows the same pattern as the existing disconnect_peer() flow. Internally calls the existing disconnect_and_ban() method.
AI was used for codebase understanding; but all code was written manually.