Skip to content

Commit

Permalink
draft: find a PeerId closer to the attacked CID when running as sybil
Browse files Browse the repository at this point in the history
  • Loading branch information
bochaco committed Apr 9, 2024
1 parent d174d1a commit 38e406b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 22 deletions.
6 changes: 3 additions & 3 deletions sn_networking/src/sybil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const KL_DIVERGENCE_THRESHOLD: f64 = 10f64; // TODO: find a good value
const K: usize = 20;
const N: usize = 25; // TODO: replace with network size estimation;

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment

// Given the set of closest K peers ids to the passed content address, return 'true'
// if there is probabilistically a sybil attack around that CID address.
pub(super) async fn check_for_sybil_attack(peers: &[PeerId], cid: &XorName) -> bool {
// TODO: do we go ahead even if we don't have at least K peer ids...?

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
info!(
Expand All @@ -42,9 +44,7 @@ fn num_peers_per_cpl(peers: &[PeerId], cid: &XorName) -> usize {
peers_per_cpl / K
}

// TODO: this is a copy of the private XorName::common_prefix method which could be made public.
/// Returns the length of the common prefix with the `other` name; e. g.
/// the when `other = 11110000` and `self = 11111111` this is 4.
// TODO: use released https://github.com/maidsafe/xor_name/pull/96 instead

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
fn common_prefix(lhs: &XorName, rhs: &XorName) -> usize {
for byte_index in 0..XOR_NAME_LEN {
if lhs[byte_index] != rhs[byte_index] {
Expand Down
64 changes: 54 additions & 10 deletions sn_node/src/bin/safenode/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use sn_node::{Marker, NodeBuilder, NodeEvent, NodeEventsReceiver};
use sn_peers_acquisition::{get_peers_from_args, PeersArgs};
use sn_protocol::{node::get_safenode_root_dir, node_rpc::NodeCtrl};
use std::{
cmp::Ordering,
env,
io::Write,
net::{IpAddr, Ipv4Addr, SocketAddr},
Expand All @@ -34,6 +35,7 @@ use tokio::{
time::sleep,
};
use tracing_appender::non_blocking::WorkerGuard;
use xor_name::XorName;

#[derive(Debug, Clone)]
pub enum LogOutputDestArg {
Expand Down Expand Up @@ -165,7 +167,24 @@ fn main() -> Result<()> {
let opt = Opt::parse();

let node_socket_addr = SocketAddr::new(opt.ip, opt.port);
let (root_dir, keypair) = get_root_dir_and_keypair(&opt.root_dir)?;
let (root_dir, keypair, sybil) = if let Some(xorname_str) = &opt.sybil {
let bytes = hex::decode(xorname_str)?;
let mut arr = [0u8; xor_name::XOR_NAME_LEN];
arr.copy_from_slice(&bytes);
let xorname = xor_name::XorName(arr);
info!("Running as sybil node to eclipse XorName: {xorname}");

// FIXME: use the PeerId closest to the address found in routing table,
// we might need to connect with a random peerid andd get-closest-peer...
let closest_peer = PeerId::random();
let (root_dir, keypair) =
gen_keypair_closer_to_address(&opt.root_dir, &xorname, &closest_peer)?;

(root_dir, keypair, Some(xorname))
} else {
let (root_dir, keypair) = get_root_dir_and_keypair(&opt.root_dir)?;
(root_dir, keypair, None)
};

let (log_output_dest, log_reload_handle, _log_appender_guard) =
init_logging(&opt, keypair.public().to_peer_id())?;
Expand All @@ -182,15 +201,6 @@ fn main() -> Result<()> {

info!("Node started with initial_peers {bootstrap_peers:?}");

let sybil = opt.sybil.map(|xorname_str| {
let bytes = hex::decode(xorname_str).unwrap();
let mut arr = [0u8; xor_name::XOR_NAME_LEN];
arr.copy_from_slice(&bytes);
let xorname = xor_name::XorName(arr);
info!("Running as sybil node to eclipse XorName: {xorname}");
xorname
});

// Create a tokio runtime per `run_node` attempt, this ensures
// any spawned tasks are closed before we would attempt to run
// another process with these args.
Expand Down Expand Up @@ -516,6 +526,40 @@ fn get_root_dir_and_keypair(root_dir: &Option<PathBuf>) -> Result<(PathBuf, Keyp
}
}

/// Generate a keypair such that the PeerId is closer to the given address
/// than the closes peer found on the routing table.
fn gen_keypair_closer_to_address(
root_dir: &Option<PathBuf>,
addr: &XorName,
closest_peer: &PeerId,
) -> Result<(PathBuf, Keypair)> {
// TODO: put a limit to the number of iterations...?
let closest = XorName::from_content(&closest_peer.to_bytes());
info!("Trying to find a PeerId closer to {addr} than {closest} to act as sybil node...");
loop {
let secret_key = libp2p::identity::ed25519::SecretKey::generate();
let keypair: Keypair = libp2p::identity::ed25519::Keypair::from(secret_key.clone()).into();
let peer_id = keypair.public().to_peer_id();
let peer_kad_id = XorName::from_content(&peer_id.to_bytes());

if addr.cmp_distance(&peer_kad_id, &closest) == Ordering::Less {
// we found a closer peer id
let dir = if let Some(dir) = root_dir {
dir.to_owned()
} else {
get_safenode_root_dir(peer_id)?
};
std::fs::create_dir_all(&dir)?;
let secret_key_path = dir.join("secret-key");
let mut file = create_secret_key_file(secret_key_path)
.map_err(|err| eyre!("could not create secret key file: {err}"))?;
file.write_all(secret_key.as_ref())?;

break Ok((dir, keypair));
}
}
}

/// Starts a new process running the binary with the same args as
/// the current process
/// Optionally provide the node's root dir and listen port to retain it's PeerId
Expand Down
18 changes: 9 additions & 9 deletions sn_node_manager/src/cmd/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ pub async fn join(
peers: PeersArgs,
skip_validation: bool,
) -> Result<(), Report> {
let sybil = sybil.map(|xorname_str| {
let bytes = hex::decode(xorname_str).unwrap();
let mut arr = [0u8; XOR_NAME_LEN];
arr.copy_from_slice(&bytes);
xor_name::XorName(arr)
});

println!("====================================================");
println!(" Joining Local Network ");
if let Some(xorname) = sybil {
let sybil = if let Some(xorname_str) = sybil {
let bytes = hex::decode(xorname_str)?;
let mut arr = [0u8; XOR_NAME_LEN];
arr.copy_from_slice(&bytes);
let xorname = xor_name::XorName(arr);
println!("** WITH SYBIL NODE/s TO ECLIPSE XorName: {xorname} **");
}
Some(xorname)
} else {
None
};
println!("====================================================");

let local_node_reg_path = &get_local_node_registry_path()?;
Expand Down

0 comments on commit 38e406b

Please sign in to comment.