protocol/service: Use block list for connections
The service learns to consult the policies database to check if a `NodeId` is blocked. When a node is blocked the service will prevent any inbound or outbound connection. In the case of an inbound connection, a disconnect must be submitted to the reactor. In the case of an outbound connection, nodes are filtered out from any connection lists, and prevented from submitting a connect to the reactor.
This commit is contained in:
parent
94e0a5128d
commit
1fa14ef529
|
|
@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## New Features
|
||||
|
||||
- The block policy for `NodeId`'s is used for limiting the namespaces fetched
|
||||
from other nodes. It is now also extended to block connections to the blocked
|
||||
`NodeId`.
|
||||
- The set of references returned by `references_of` were restricted to `heads`,
|
||||
`tags`, `notes`, `rad`, and `cobs`. The restriction is lifted, and the only
|
||||
references filtered out are `refs/tmp/heads` – used by `radicle-remote-helper`
|
||||
|
|
|
|||
|
|
@ -230,6 +230,8 @@ pub enum ConnectError {
|
|||
"attempted connection to {nid}, via {addr} but addresses of this kind are not supported"
|
||||
)]
|
||||
UnsupportedAddress { nid: NodeId, addr: Address },
|
||||
#[error("attempted connection with blocked peer {nid}")]
|
||||
Blocked { nid: NodeId },
|
||||
}
|
||||
|
||||
/// A store for all node data.
|
||||
|
|
@ -1219,6 +1221,16 @@ where
|
|||
}
|
||||
|
||||
pub fn connected(&mut self, remote: NodeId, addr: Address, link: Link) {
|
||||
if let Ok(true) = self.policies.is_blocked(&remote) {
|
||||
self.emitter.emit(Event::PeerDisconnected {
|
||||
nid: remote,
|
||||
reason: format!("{remote} is blocked"),
|
||||
});
|
||||
info!(target: "service", "Disconnecting blocked inbound peer {remote}");
|
||||
self.outbox.disconnect(remote, DisconnectReason::Policy);
|
||||
return;
|
||||
}
|
||||
|
||||
info!(target: "service", "Connected to {remote} ({addr}) ({link:?})");
|
||||
self.emitter.emit(Event::PeerConnected { nid: remote });
|
||||
|
||||
|
|
@ -2164,6 +2176,9 @@ where
|
|||
if nid == self.node_id() {
|
||||
return Err(ConnectError::SelfConnection);
|
||||
}
|
||||
if let Ok(true) = self.policies.is_blocked(&nid) {
|
||||
return Err(ConnectError::Blocked { nid });
|
||||
}
|
||||
if !self.is_supported_address(&addr) {
|
||||
return Err(ConnectError::UnsupportedAddress { nid, addr });
|
||||
}
|
||||
|
|
@ -2397,6 +2412,7 @@ where
|
|||
.filter(|entry| !entry.address.banned)
|
||||
.filter(|entry| !entry.penalty.is_connect_threshold_reached())
|
||||
.filter(|entry| !self.sessions.contains_key(&entry.node))
|
||||
.filter(|entry| !self.policies.is_blocked(&entry.node).unwrap_or(false))
|
||||
.filter(|entry| !self.config.external_addresses.contains(&entry.address.addr))
|
||||
.filter(|entry| &entry.node != self.nid())
|
||||
.filter(|entry| self.is_supported_address(&entry.address.addr))
|
||||
|
|
@ -2564,6 +2580,9 @@ where
|
|||
|
||||
for (nid, session) in self.sessions.iter_mut() {
|
||||
if self.config.is_persistent(nid) {
|
||||
if self.policies.is_blocked(nid).unwrap_or(false) {
|
||||
continue;
|
||||
}
|
||||
if let session::State::Disconnected { retry_at, .. } = &mut session.state {
|
||||
// TODO: Try to reconnect only if the peer was attempted. A disconnect without
|
||||
// even a successful attempt means that we're unlikely to be able to reconnect.
|
||||
|
|
|
|||
Loading…
Reference in New Issue