From e67e6a9838b690d884273e1a2e1e2e23043fc4d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 26 Oct 2023 17:06:45 +0100 Subject: [PATCH] [gateway] using the ingress filter for incoming (mix) connections --- gateway/src/config/mod.rs | 3 +- gateway/src/error.rs | 7 +++++ .../node/mixnet_handling/receiver/listener.rs | 20 +++++++++++-- gateway/src/node/mod.rs | 29 ++++++++++++++++++- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index b872a1dffd..ff021048d5 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -328,7 +328,8 @@ pub struct Gateway { #[zeroize(skip)] pub nym_api_urls: Vec, - /// Addresses to validators which the node uses to check for double spending of ERC20 tokens. + /// Addresses to nyxd validators via which the node can communicate with the chain directly, + /// including for checking for double spending of coconut credentials. #[serde(alias = "validator_nymd_urls")] #[zeroize(skip)] pub nyxd_urls: Vec, diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 61f75981ef..8cc8f765bb 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -3,6 +3,7 @@ use crate::node::storage::error::StorageError; use nym_ip_packet_router::error::IpPacketRouterError; +use nym_mixnode_common::forward_travel::error::ForwardTravelError; use nym_network_requester::error::{ClientCoreError, NetworkRequesterError}; use nym_validator_client::nyxd::error::NyxdError; use nym_validator_client::nyxd::AccountId; @@ -131,6 +132,12 @@ pub(crate) enum GatewayError { source: NyxdError, }, + #[error("failure in enforcing forward travel of mix packets: {source}")] + ForwardTravel { + #[from] + source: ForwardTravelError, + }, + // TODO: in the future this should work the other way, i.e. NymNode depending on Gateway errors #[error(transparent)] NymNodeError(#[from] nym_node::error::NymNodeError), diff --git a/gateway/src/node/mixnet_handling/receiver/listener.rs b/gateway/src/node/mixnet_handling/receiver/listener.rs index 9ca22c77af..eebfbf9fd7 100644 --- a/gateway/src/node/mixnet_handling/receiver/listener.rs +++ b/gateway/src/node/mixnet_handling/receiver/listener.rs @@ -4,6 +4,7 @@ use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler; use crate::node::storage::Storage; use log::*; +use nym_mixnode_common::forward_travel::AllowedIngress; use nym_task::TaskClient; use std::net::SocketAddr; use std::process; @@ -11,13 +12,22 @@ use tokio::task::JoinHandle; pub(crate) struct Listener { address: SocketAddr, + allowed_ingress: AllowedIngress, shutdown: TaskClient, } // TODO: this file is nearly identical to the one in mixnode impl Listener { - pub(crate) fn new(address: SocketAddr, shutdown: TaskClient) -> Self { - Listener { address, shutdown } + pub(crate) fn new( + address: SocketAddr, + allowed_ingress: AllowedIngress, + shutdown: TaskClient, + ) -> Self { + Listener { + address, + allowed_ingress, + shutdown, + } } pub(crate) async fn run(&mut self, connection_handler: ConnectionHandler) @@ -42,6 +52,12 @@ impl Listener { connection = tcp_listener.accept() => { match connection { Ok((socket, remote_addr)) => { + if !self.allowed_ingress.is_allowed(remote_addr.ip()) { + // TODO: perhaps this should get lowered in severity? + warn!("received an incoming connection from {remote_addr}, but this address does not belong to any node on the previous layer - dropping the connection"); + continue + } + let handler = connection_handler.clone(); tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone().named(format!("MixnetConnectionHandler_{remote_addr}")))); } diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index fa0f8b35b0..67f321a9c3 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -28,6 +28,7 @@ use futures::channel::{mpsc, oneshot}; use log::*; use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnet_client::forwarder::{MixForwardingSender, PacketForwarder}; +use nym_mixnode_common::forward_travel::{AllowedAddressesProvider, AllowedEgress, AllowedIngress}; use nym_network_defaults::NymNetworkDetails; use nym_network_requester::{LocalGateway, NRServiceProviderBuilder, RequestFilter}; use nym_node::wireguard::types::GatewayClientRegistry; @@ -178,6 +179,7 @@ impl Gateway { &self, ack_sender: MixForwardingSender, active_clients_store: ActiveClientsStore, + ingress: AllowedIngress, shutdown: TaskClient, ) where St: Storage + Clone + 'static, @@ -199,7 +201,8 @@ impl Gateway { self.config.gateway.mix_port, ); - mixnet_handling::Listener::new(listening_address, shutdown).start(connection_handler); + mixnet_handling::Listener::new(listening_address, ingress, shutdown) + .start(connection_handler); } #[cfg(feature = "wireguard")] @@ -240,6 +243,23 @@ impl Gateway { ); } + async fn start_allowed_addresses_provider( + &self, + task_client: TaskClient, + ) -> Result<(AllowedIngress, AllowedEgress), GatewayError> { + let identity = self.identity_keypair.public_key().to_base58_string(); + let nyxd_endpoints = self.config.gateway.nyxd_urls.clone(); + + let network = NymNetworkDetails::new_from_env(); + let mut provider = + AllowedAddressesProvider::new(identity, nyxd_endpoints, Some(network)).await?; + + let filters = (provider.ingress(), provider.egress()); + + tokio::spawn(async move { provider.run(task_client).await }); + Ok(filters) + } + fn start_packet_forwarder(&self, shutdown: TaskClient) -> MixForwardingSender { info!("Starting mix packet forwarder..."); @@ -449,6 +469,12 @@ impl Gateway { let shutdown = TaskManager::new(10); + let (ingress, egress) = self + .start_allowed_addresses_provider( + shutdown.subscribe().named("AllowedAddressesProvider"), + ) + .await?; + let coconut_verifier = { let nyxd_client = self.random_nyxd_client()?; CoconutVerifier::new(nyxd_client) @@ -461,6 +487,7 @@ impl Gateway { self.start_mix_socket_listener( mix_forwarding_channel.clone(), active_clients_store.clone(), + ingress, shutdown.subscribe().named("mixnet_handling::Listener"), );