remove absolute dependence on topology

This commit is contained in:
Simon Wicky
2023-07-28 12:09:13 +02:00
parent 9e3bb6ef24
commit 331a0328c7
8 changed files with 146 additions and 95 deletions
+7 -10
View File
@@ -1,13 +1,12 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::encryption::{PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE};
use futures::channel::mpsc;
use futures::StreamExt;
use log::*;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_crypto::asymmetric::encryption;
use nym_noise::upgrade_noise_initiator;
use nym_noise::upgrade_noise_initiator_with_topology;
use nym_sphinx::addressing::nodes::NymNodeRoutingAddress;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
@@ -64,8 +63,7 @@ pub struct Client {
conn_new: HashMap<NymNodeRoutingAddress, ConnectionSender>,
config: Config,
topology_access: TopologyAccessor,
public_id_key: [u8; PUBLIC_KEY_SIZE],
private_id_key: [u8; PRIVATE_KEY_SIZE],
local_identity: Arc<encryption::KeyPair>,
}
struct ConnectionSender {
@@ -86,14 +84,13 @@ impl Client {
pub fn new(
config: Config,
topology_access: TopologyAccessor,
id_key: &encryption::KeyPair,
local_identity: Arc<encryption::KeyPair>,
) -> Client {
Client {
conn_new: HashMap::new(),
config,
topology_access,
public_id_key: id_key.public_key().to_bytes(),
private_id_key: id_key.private_key().to_bytes(),
local_identity,
}
}
@@ -124,7 +121,7 @@ impl Client {
}
};
let noise_stream = match upgrade_noise_initiator(
let noise_stream = match upgrade_noise_initiator_with_topology(
stream,
topology_ref,
local_public_key,
@@ -218,8 +215,8 @@ impl Client {
let initial_connection_timeout = self.config.initial_connection_timeout;
let topology_access_clone = self.topology_access.clone();
let local_private_key = self.private_id_key.clone();
let local_public_key = self.public_id_key.clone();
let local_public_key = self.local_identity.public_key().to_bytes();
let local_private_key = self.local_identity.private_key().to_bytes();
tokio::spawn(async move {
// before executing the manager, wait for what was specified, if anything
@@ -8,6 +8,7 @@ use log::*;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_crypto::asymmetric::encryption;
use nym_sphinx::forwarding::packet::MixPacket;
use std::sync::Arc;
use std::time::Duration;
pub type MixForwardingSender = mpsc::UnboundedSender<MixPacket>;
@@ -29,7 +30,7 @@ impl PacketForwarder {
maximum_connection_buffer_size: usize,
use_legacy_version: bool,
topology_access: TopologyAccessor,
sphinx_key: &encryption::KeyPair,
local_identity: Arc<encryption::KeyPair>,
shutdown: nym_task::TaskClient,
) -> (PacketForwarder, MixForwardingSender) {
let client_config = Config::new(
@@ -44,7 +45,7 @@ impl PacketForwarder {
(
PacketForwarder {
mixnet_client: Client::new(client_config, topology_access, sphinx_key),
mixnet_client: Client::new(client_config, topology_access, local_identity),
packet_receiver,
shutdown,
},
+63 -29
View File
@@ -198,31 +198,14 @@ impl AsyncWrite for NoiseStream {
pub async fn upgrade_noise_initiator(
mut conn: TcpStream,
topology: &NymTopology,
local_public_key: &[u8],
local_public_key: Option<&[u8]>,
local_private_key: &[u8],
remote_pub_key: &[u8],
) -> Result<NoiseStream, NoiseError> {
trace!("Perform Noise Handshake, initiator side");
//Get init material
let responder_addr = match conn.peer_addr() {
Ok(addr) => addr,
Err(err) => {
error!("Unable to extract peer address from connection - {err}");
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
let remote_pub_key = match topology.find_node_key_by_mix_host(responder_addr) {
Some(pub_key) => pub_key.to_bytes(),
None => {
error!(
"Cannot find public key for node with address {:?}",
responder_addr
);
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
let secret = [local_public_key, &remote_pub_key].concat();
//In case the local key cannot be known by the remote party, e.g. in a client-gateway connection
let secret = [local_public_key.unwrap_or(&[]), remote_pub_key].concat();
let secret_hash = Sha256::digest(secret);
let builder = Builder::new(NOISE_HS_PATTERN.parse().unwrap()); //This cannot fail, hardcoded pattern must be correct
@@ -250,33 +233,50 @@ pub async fn upgrade_noise_initiator(
Ok(NoiseStream::new(conn, noise))
}
pub async fn upgrade_noise_responder(
mut conn: TcpStream,
pub async fn upgrade_noise_initiator_with_topology(
conn: TcpStream,
topology: &NymTopology,
local_public_key: &[u8],
local_private_key: &[u8],
) -> Result<NoiseStream, NoiseError> {
trace!("Perform Noise Handshake, responder side");
//Get init material
let initiator_addr = match conn.peer_addr() {
let responder_addr = match conn.peer_addr() {
Ok(addr) => addr,
Err(err) => {
error!("Unable to extract peer address from connection - {err}");
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
let remote_pub_key = match topology.find_node_key_by_mix_host(initiator_addr) {
let remote_pub_key = match topology.find_node_key_by_mix_host(responder_addr) {
Some(pub_key) => pub_key.to_bytes(),
None => {
error!(
"Cannot find public key for node with address {:?}",
initiator_addr
responder_addr
);
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
let secret = [&remote_pub_key, local_public_key].concat();
upgrade_noise_initiator(
conn,
Some(local_public_key),
local_private_key,
&remote_pub_key,
)
.await
}
pub async fn upgrade_noise_responder(
mut conn: TcpStream,
local_public_key: &[u8],
local_private_key: &[u8],
remote_pub_key: Option<&[u8]>,
) -> Result<NoiseStream, NoiseError> {
trace!("Perform Noise Handshake, responder side");
//If the remote_key cannot be kwnown, e.g. in a client-gateway connection
let secret = [&remote_pub_key.unwrap_or(&[]), local_public_key].concat();
let secret_hash = Sha256::digest(secret);
let builder = Builder::new(NOISE_HS_PATTERN.parse().unwrap()); //This cannot fail, hardcoded pattern must be correct
@@ -302,6 +302,40 @@ pub async fn upgrade_noise_responder(
Ok(NoiseStream::new(conn, noise))
}
pub async fn upgrade_noise_responder_with_topology(
conn: TcpStream,
topology: &NymTopology,
local_public_key: &[u8],
local_private_key: &[u8],
) -> Result<NoiseStream, NoiseError> {
//Get init material
let initiator_addr = match conn.peer_addr() {
Ok(addr) => addr,
Err(err) => {
error!("Unable to extract peer address from connection - {err}");
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
let remote_pub_key = match topology.find_node_key_by_mix_host(initiator_addr) {
Some(pub_key) => pub_key.to_bytes(),
None => {
error!(
"Cannot find public key for node with address {:?}",
initiator_addr
);
return Err(Error::Prereq(Prerequisite::RemotePublicKey).into());
}
};
upgrade_noise_responder(
conn,
local_public_key,
local_private_key,
Some(&remote_pub_key),
)
.await
}
/// Hyper-basic stream transport receiver. 16-bit BE size followed by payload.
async fn recv(stream: &mut TcpStream) -> io::Result<Vec<u8>> {
let mut msg_len_buf = [0u8; HEADER_SIZE];
@@ -6,8 +6,9 @@ use crate::node::client_handling::websocket::connection_handler::coconut::Coconu
use crate::node::client_handling::websocket::connection_handler::FreshHandler;
use crate::node::storage::Storage;
use log::*;
use nym_crypto::asymmetric::identity;
use nym_crypto::asymmetric::{encryption, identity};
use nym_mixnet_client::forwarder::MixForwardingSender;
use nym_noise::upgrade_noise_responder;
use rand::rngs::OsRng;
use std::net::SocketAddr;
use std::process;
@@ -17,6 +18,7 @@ use tokio::task::JoinHandle;
pub(crate) struct Listener {
address: SocketAddr,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
only_coconut_credentials: bool,
pub(crate) coconut_verifier: Arc<CoconutVerifier>,
}
@@ -25,12 +27,14 @@ impl Listener {
pub(crate) fn new(
address: SocketAddr,
local_identity: Arc<identity::KeyPair>,
local_sphinx: Arc<encryption::KeyPair>,
only_coconut_credentials: bool,
coconut_verifier: Arc<CoconutVerifier>,
) -> Self {
Listener {
address,
local_identity,
local_sphinx,
only_coconut_credentials,
coconut_verifier,
}
@@ -58,34 +62,49 @@ impl Listener {
while !shutdown.is_shutdown() {
tokio::select! {
biased;
_ = shutdown.recv() => {
log::trace!("client_handling::Listener: received shutdown");
}
connection = tcp_listener.accept() => {
match connection {
Ok((socket, remote_addr)) => {
trace!("received a socket connection from {remote_addr}");
// TODO: I think we *REALLY* need a mechanism for having a maximum number of connected
// clients or spawned tokio tasks -> perhaps a worker system?
let handle = FreshHandler::new(
OsRng,
socket,
self.only_coconut_credentials,
outbound_mix_sender.clone(),
Arc::clone(&self.local_identity),
storage.clone(),
active_clients_store.clone(),
Arc::clone(&self.coconut_verifier),
);
let shutdown = shutdown.clone();
tokio::spawn(async move { handle.start_handling(shutdown).await });
}
Err(err) => warn!("failed to get client: {err}"),
}
}
biased;
_ = shutdown.recv() => {
log::trace!("client_handling::Listener: received shutdown");
}
connection = tcp_listener.accept() => {
match connection {
Ok((socket, remote_addr)) => {
trace!("received a socket connection from {remote_addr}");
// TODO: I think we *REALLY* need a mechanism for having a maximum number of connected
// clients or spawned tokio tasks -> perhaps a worker system?
// let noise_stream = match upgrade_noise_responder(
// socket,
// &self.local_sphinx.public_key().to_bytes(),
// &self.local_sphinx.private_key().to_bytes(),
// None, //connection from client, no remote pub key
// )
// .await
// {
// Ok(noise_stream) => noise_stream,
// Err(err) => {
// error!("Failed to perform Noise handshake with {remote_addr} - {err}");
// return;
// }
// };
let handle = FreshHandler::new(
OsRng,
socket,
// noise_stream,
self.only_coconut_credentials,
outbound_mix_sender.clone(),
Arc::clone(&self.local_identity),
storage.clone(),
active_clients_store.clone(),
Arc::clone(&self.coconut_verifier),
);
let shutdown = shutdown.clone();
tokio::spawn(async move { handle.start_handling(shutdown).await });
}
Err(err) => warn!("failed to get client: {err}"),
}
}
}
}
}
}
@@ -3,7 +3,6 @@
use crate::node::client_handling::active_clients::ActiveClientsStore;
use crate::node::client_handling::websocket::message_receiver::MixMessageSender;
use crate::node::encryption::{PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE};
use crate::node::mixnet_handling::receiver::packet_processing::PacketProcessor;
use crate::node::storage::error::StorageError;
use crate::node::storage::Storage;
@@ -13,7 +12,7 @@ use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_crypto::asymmetric::encryption;
use nym_mixnet_client::forwarder::MixForwardingSender;
use nym_mixnode_common::packet_processor::processor::ProcessedFinalHop;
use nym_noise::upgrade_noise_responder;
use nym_noise::upgrade_noise_responder_with_topology;
use nym_sphinx::forwarding::packet::MixPacket;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
@@ -21,6 +20,7 @@ use nym_sphinx::DestinationAddressBytes;
use nym_task::TaskClient;
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::TcpStream;
use tokio_util::codec::Framed;
@@ -36,8 +36,7 @@ pub(crate) struct ConnectionHandler<St: Storage> {
storage: St,
ack_sender: MixForwardingSender,
topology_access: TopologyAccessor,
public_identity_key: [u8; PUBLIC_KEY_SIZE],
private_identity_key: [u8; PRIVATE_KEY_SIZE],
local_identity: Arc<encryption::KeyPair>,
}
impl<St: Storage + Clone> Clone for ConnectionHandler<St> {
@@ -57,8 +56,7 @@ impl<St: Storage + Clone> Clone for ConnectionHandler<St> {
storage: self.storage.clone(),
ack_sender: self.ack_sender.clone(),
topology_access: self.topology_access.clone(),
public_identity_key: self.public_identity_key.clone(),
private_identity_key: self.private_identity_key.clone(),
local_identity: self.local_identity.clone(),
}
}
}
@@ -70,7 +68,7 @@ impl<St: Storage> ConnectionHandler<St> {
ack_sender: MixForwardingSender,
active_clients_store: ActiveClientsStore,
topology_access: TopologyAccessor,
identity_key: &encryption::KeyPair,
local_identity: Arc<encryption::KeyPair>,
) -> Self {
ConnectionHandler {
packet_processor,
@@ -79,8 +77,7 @@ impl<St: Storage> ConnectionHandler<St> {
active_clients_store,
ack_sender,
topology_access,
public_identity_key: identity_key.public_key().to_bytes(),
private_identity_key: identity_key.private_key().to_bytes(),
local_identity,
}
}
@@ -208,11 +205,11 @@ impl<St: Storage> ConnectionHandler<St> {
}
};
let noise_stream = match upgrade_noise_responder(
let noise_stream = match upgrade_noise_responder_with_topology(
conn,
topology_ref,
&self.public_identity_key,
&self.private_identity_key,
&self.local_identity.public_key().to_bytes(),
&self.local_identity.private_key().to_bytes(),
)
.await
{
+3 -2
View File
@@ -146,7 +146,7 @@ impl<St> Gateway<St> {
ack_sender,
active_clients_store,
topology_access,
&self.sphinx_keypair,
Arc::clone(&self.sphinx_keypair),
);
let listening_address = SocketAddr::new(
@@ -176,6 +176,7 @@ impl<St> Gateway<St> {
websocket::Listener::new(
listening_address,
Arc::clone(&self.identity_keypair),
Arc::clone(&self.sphinx_keypair),
self.config.gateway.only_coconut_credentials,
coconut_verifier,
)
@@ -201,7 +202,7 @@ impl<St> Gateway<St> {
self.config.debug.maximum_connection_buffer_size,
self.config.debug.use_legacy_framed_packet_version,
topology_access,
&self.sphinx_keypair,
Arc::clone(&self.sphinx_keypair),
shutdown,
);
@@ -1,7 +1,6 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::node::encryption::{PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE};
use crate::node::listener::connection_handler::packet_processing::{
MixProcessingResult, PacketProcessor,
};
@@ -11,12 +10,13 @@ use futures::StreamExt;
use nym_client_core::client::topology_control::accessor::TopologyAccessor;
use nym_crypto::asymmetric::encryption;
use nym_mixnode_common::measure;
use nym_noise::upgrade_noise_responder;
use nym_noise::upgrade_noise_responder_with_topology;
use nym_sphinx::forwarding::packet::MixPacket;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
use nym_sphinx::Delay as SphinxDelay;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::TcpStream;
use tokio::time::Instant;
use tokio_util::codec::Framed;
@@ -30,8 +30,7 @@ pub(crate) struct ConnectionHandler {
packet_processor: PacketProcessor,
delay_forwarding_channel: PacketDelayForwardSender,
topology_access: TopologyAccessor,
private_identity_key: [u8; PRIVATE_KEY_SIZE],
public_identity_key: [u8; PUBLIC_KEY_SIZE],
local_identity: Arc<encryption::KeyPair>,
}
impl ConnectionHandler {
@@ -39,14 +38,13 @@ impl ConnectionHandler {
packet_processor: PacketProcessor,
delay_forwarding_channel: PacketDelayForwardSender,
topology_access: TopologyAccessor,
identity_key: &encryption::KeyPair,
local_identity: Arc<encryption::KeyPair>,
) -> Self {
ConnectionHandler {
packet_processor,
delay_forwarding_channel,
topology_access,
public_identity_key: identity_key.public_key().to_bytes(),
private_identity_key: identity_key.private_key().to_bytes(),
local_identity,
}
}
@@ -109,11 +107,11 @@ impl ConnectionHandler {
}
};
let noise_stream = match upgrade_noise_responder(
let noise_stream = match upgrade_noise_responder_with_topology(
conn,
topology_ref,
&self.public_identity_key,
&self.private_identity_key,
&self.local_identity.public_key().to_bytes(),
&self.local_identity.private_key().to_bytes(),
)
.await
{
+6 -2
View File
@@ -164,7 +164,7 @@ impl MixNode {
packet_processor,
delay_forwarding_channel,
topology_access,
&self.sphinx_keypair,
Arc::clone(&self.sphinx_keypair),
);
let listening_address = SocketAddr::new(
@@ -192,7 +192,11 @@ impl MixNode {
);
let mut packet_forwarder = DelayForwarder::new(
nym_mixnet_client::Client::new(client_config, topology_access, &self.sphinx_keypair),
nym_mixnet_client::Client::new(
client_config,
topology_access,
Arc::clone(&self.sphinx_keypair),
),
node_stats_update_sender,
shutdown,
);