further adjusting storage and setup to allow for wg use

This commit is contained in:
Jędrzej Stuczyński
2024-03-08 14:54:16 +00:00
parent 6e1b869c99
commit fc43cb590b
15 changed files with 291 additions and 179 deletions
@@ -24,7 +24,8 @@ CREATE TABLE remote_gateway_details
gateway_id_bs58 TEXT NOT NULL UNIQUE PRIMARY KEY REFERENCES registered_gateway (gateway_id_bs58),
derived_aes128_ctr_blake3_hmac_keys_bs58 TEXT NOT NULL,
gateway_owner_address TEXT NOT NULL,
gateway_listener TEXT NOT NULL
gateway_listener TEXT NOT NULL,
wg_tun_address TEXT
);
CREATE TABLE custom_gateway_details
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::types::GatewayRegistration;
use crate::{GatewaysDetailsStore, StorageError};
use crate::{ActiveGateway, GatewaysDetailsStore, StorageError};
use async_trait::async_trait;
use manager::StorageManager;
use std::path::Path;
@@ -26,11 +26,12 @@ impl OnDiskGatewaysDetails {
#[async_trait]
impl GatewaysDetailsStore for OnDiskGatewaysDetails {
type StorageError = error::StorageError;
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError> {
todo!()
}
async fn active_gateway(&self) -> Result<Option<GatewayRegistration>, Self::StorageError> {
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> {
todo!()
}
@@ -1,7 +1,7 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::GatewayRegistration;
use crate::types::{ActiveGateway, GatewayRegistration};
use crate::{BadGateway, GatewaysDetailsStore};
use async_trait::async_trait;
use std::collections::HashMap;
@@ -38,14 +38,16 @@ impl GatewaysDetailsStore for InMemGatewaysDetails {
Ok(self.inner.read().await.gateways.contains_key(gateway_id))
}
async fn active_gateway(&self) -> Result<Option<GatewayRegistration>, Self::StorageError> {
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> {
let guard = self.inner.read().await;
Ok(guard.active_gateway.as_ref().map(|id| {
let registration = guard.active_gateway.as_ref().map(|id| {
// SAFETY: if particular gateway is set as active, its details MUST exist
#[allow(clippy::unwrap_used)]
guard.gateways.get(id).unwrap().clone()
}))
});
Ok(ActiveGateway { registration })
}
async fn set_active_gateway(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
@@ -13,8 +13,8 @@ pub mod types;
// todo: export port types
pub use crate::types::{
CustomGatewayDetails, GatewayDetails, GatewayRegistration, GatewayType, RegisteredGateway,
RemoteGatewayDetails,
ActiveGateway, CustomGatewayDetails, GatewayDetails, GatewayRegistration, GatewayType,
RegisteredGateway, RemoteGatewayDetails,
};
pub use backend::mem_backend::{InMemGatewaysDetails, InMemStorageError};
pub use error::BadGateway;
@@ -29,7 +29,7 @@ pub trait GatewaysDetailsStore {
type StorageError: Error + From<error::BadGateway>;
/// Returns details of the currently active gateway, if available.
async fn active_gateway(&self) -> Result<Option<GatewayRegistration>, Self::StorageError>;
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError>;
/// Set the provided gateway as the currently active gateway.
async fn set_active_gateway(&self, gateway_id: &str) -> Result<(), Self::StorageError>;
@@ -16,6 +16,11 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
pub const REMOTE_GATEWAY_TYPE: &str = "remote";
pub const CUSTOM_GATEWAY_TYPE: &str = "custom";
#[derive(Debug, Clone, Default)]
pub struct ActiveGateway {
pub registration: Option<GatewayRegistration>,
}
#[derive(Debug, Clone)]
pub struct GatewayRegistration {
pub details: GatewayDetails,
@@ -46,12 +51,14 @@ impl GatewayDetails {
derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
gateway_owner_address: AccountId,
gateway_listener: Url,
wg_tun_address: Option<Url>,
) -> Self {
GatewayDetails::Remote(RemoteGatewayDetails {
gateway_id,
derived_aes128_ctr_blake3_hmac_keys,
gateway_owner_address,
gateway_listener,
wg_tun_address,
})
}
@@ -136,6 +143,7 @@ pub struct RawRemoteGatewayDetails {
pub derived_aes128_ctr_blake3_hmac_keys_bs58: String,
pub gateway_owner_address: String,
pub gateway_listener: String,
pub wg_tun_address: Option<String>,
}
impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
@@ -175,11 +183,24 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
}
})?;
let wg_tun_address = value
.wg_tun_address
.as_ref()
.map(|addr| {
Url::parse(addr).map_err(|source| BadGateway::MalformedListener {
gateway_id: value.gateway_id_bs58.clone(),
raw_listener: addr.clone(),
source,
})
})
.transpose()?;
Ok(RemoteGatewayDetails {
gateway_id,
derived_aes128_ctr_blake3_hmac_keys,
gateway_owner_address,
gateway_listener,
wg_tun_address,
})
}
}
@@ -193,6 +214,7 @@ impl From<RemoteGatewayDetails> for RawRemoteGatewayDetails {
.to_base58_string(),
gateway_owner_address: value.gateway_owner_address.to_string(),
gateway_listener: value.gateway_listener.to_string(),
wg_tun_address: value.wg_tun_address.map(|addr| addr.to_string()),
}
}
}
@@ -208,6 +230,8 @@ pub struct RemoteGatewayDetails {
pub gateway_owner_address: AccountId,
pub gateway_listener: Url,
pub wg_tun_address: Option<Url>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -236,6 +236,7 @@ where
specification: selection_spec,
available_gateways,
overwrite_data: common_args.force_register_gateway,
wg_tun_address: None,
};
let init_details =
@@ -35,7 +35,7 @@ use crate::init::{
};
use crate::{config, spawn_future};
use futures::channel::mpsc;
use log::{debug, error, info};
use log::{debug, error, info, warn};
use nym_bandwidth_controller::BandwidthController;
use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore};
use nym_credential_storage::storage::Storage as CredentialStorage;
@@ -43,6 +43,7 @@ use nym_crypto::asymmetric::encryption;
use nym_gateway_client::{
AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter,
};
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, WG_TUN_DEVICE_ADDRESS};
use nym_sphinx::acknowledgements::AckKey;
use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::addressing::nodes::NodeIdentity;
@@ -179,6 +180,7 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
dkg_query_client: Option<C>,
wait_for_gateway: bool,
wireguard_connection: bool,
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
shutdown: Option<TaskClient>,
@@ -201,6 +203,7 @@ where
client_store,
dkg_query_client,
wait_for_gateway: false,
wireguard_connection: false,
custom_topology_provider: None,
custom_gateway_transceiver: None,
shutdown: None,
@@ -220,6 +223,12 @@ where
self
}
#[must_use]
pub fn with_wireguard_connection(mut self, wireguard_connection: bool) -> Self {
self.wireguard_connection = wireguard_connection;
self
}
#[must_use]
pub fn with_topology_provider(
mut self,
@@ -343,6 +352,7 @@ where
async fn start_gateway_client(
config: &Config,
wireguard_connection: bool,
initialisation_result: InitialisationResult,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
packet_router: PacketRouter,
@@ -358,27 +368,41 @@ where
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails);
};
let mut gateway_client =
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client {
existing_client.upgrade(packet_router, bandwidth_controller, shutdown)
let mut gateway_client = if let Some(existing_client) =
initialisation_result.authenticated_ephemeral_client
{
existing_client.upgrade(packet_router, bandwidth_controller, shutdown)
} else {
let gateway_listener = if wireguard_connection {
if let Some(tun_address) = details.wg_tun_address {
tun_address.to_string()
} else {
let default =
format!("ws://{WG_TUN_DEVICE_ADDRESS}:{DEFAULT_CLIENT_LISTENING_PORT}");
warn!("gateway {} does not have tun device address set. defaulting to '{default}'", details.gateway_id);
default
}
} else {
let cfg = GatewayConfig::new(
details.gateway_id,
Some(details.gateway_owner_address.to_string()),
details.gateway_listener.to_string(),
);
GatewayClient::new(
cfg,
managed_keys.identity_keypair(),
Some(details.derived_aes128_ctr_blake3_hmac_keys),
packet_router,
bandwidth_controller,
shutdown,
)
.with_disabled_credentials_mode(config.client.disabled_credentials_mode)
.with_response_timeout(config.debug.gateway_connection.gateway_response_timeout)
details.gateway_listener.to_string()
};
let cfg = GatewayConfig::new(
details.gateway_id,
Some(details.gateway_owner_address.to_string()),
gateway_listener,
);
GatewayClient::new(
cfg,
managed_keys.identity_keypair(),
Some(details.derived_aes128_ctr_blake3_hmac_keys),
packet_router,
bandwidth_controller,
shutdown,
)
.with_disabled_credentials_mode(config.client.disabled_credentials_mode)
.with_response_timeout(config.debug.gateway_connection.gateway_response_timeout)
};
gateway_client
.authenticate_and_start()
.await
@@ -396,6 +420,7 @@ where
async fn setup_gateway_transceiver(
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
config: &Config,
wireguard_connection: bool,
initialisation_result: InitialisationResult,
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
packet_router: PacketRouter,
@@ -424,6 +449,7 @@ where
// otherwise, setup normal gateway client, etc
let gateway_client = Self::start_gateway_client(
config,
wireguard_connection,
initialisation_result,
bandwidth_controller,
packet_router,
@@ -680,6 +706,7 @@ where
let gateway_transceiver = Self::setup_gateway_transceiver(
self.custom_gateway_transceiver,
self.config,
self.wireguard_connection,
init_res,
bandwidth_controller,
gateway_packet_router,
@@ -5,7 +5,7 @@ use crate::client::key_manager::persistence::KeyStore;
use crate::client::key_manager::ClientKeys;
use crate::error::ClientCoreError;
use nym_client_core_gateways_storage::{
GatewayRegistration, GatewaysDetailsStore, GatewaysDetailsStoreExt,
ActiveGateway, GatewayRegistration, GatewaysDetailsStore, GatewaysDetailsStoreExt,
};
use nym_crypto::asymmetric::identity;
@@ -59,18 +59,16 @@ where
pub async fn load_active_gateway_details<D>(
details_store: &D,
) -> Result<GatewayRegistration, ClientCoreError>
) -> Result<ActiveGateway, ClientCoreError>
where
D: GatewaysDetailsStore,
D::StorageError: Send + Sync + 'static,
{
details_store
.active_gateway()
.await
.map_err(|source| ClientCoreError::GatewaysDetailsStoreError {
details_store.active_gateway().await.map_err(|source| {
ClientCoreError::GatewaysDetailsStoreError {
source: Box::new(source),
})?
.ok_or(ClientCoreError::NoActiveGatewaySet)
}
})
}
pub async fn load_gateway_details<D>(
@@ -102,6 +102,7 @@ pub mod v1_1_33 {
message: format!("the stored gateway listener address was malformed: {err}"),
}
})?,
wg_tun_address: None,
}))
}
+18 -13
View File
@@ -23,6 +23,7 @@ use nym_topology::gateway;
use rand::rngs::OsRng;
use rand::{CryptoRng, RngCore};
use serde::Serialize;
use std::net::IpAddr;
pub mod helpers;
pub mod types;
@@ -46,19 +47,13 @@ where
})
}
// fn ensure_valid_details(
// details: &PersistedGatewayDetails,
// loaded_keys: &ManagedKeys,
// ) -> Result<(), ClientCoreError> {
// details.validate(loaded_keys.gateway_shared_key().as_deref())
// }
async fn setup_new_gateway<K, D>(
key_store: &K,
details_store: &D,
overwrite_data: bool,
selection_specification: GatewaySelectionSpecification,
available_gateways: Vec<gateway::Node>,
wg_tun_ip_address: Option<IpAddr>,
) -> Result<InitialisationResult, ClientCoreError>
where
K: KeyStore,
@@ -76,19 +71,19 @@ where
let selected_gateway = match selection_specification {
GatewaySelectionSpecification::UniformRemote { must_use_tls } => {
let gateway = uniformly_random_gateway(&mut rng, &available_gateways, must_use_tls)?;
SelectedGateway::from_topology_node(gateway, must_use_tls)?
SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)?
}
GatewaySelectionSpecification::RemoteByLatency { must_use_tls } => {
let gateway =
choose_gateway_by_latency(&mut rng, &available_gateways, must_use_tls).await?;
SelectedGateway::from_topology_node(gateway, must_use_tls)?
SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)?
}
GatewaySelectionSpecification::Specified {
must_use_tls,
identity,
} => {
let gateway = get_specified_gateway(&identity, &available_gateways, must_use_tls)?;
SelectedGateway::from_topology_node(gateway, must_use_tls)?
SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)?
}
GatewaySelectionSpecification::Custom {
gateway_identity,
@@ -110,18 +105,23 @@ where
gateway_id,
gateway_owner_address,
gateway_listener,
wg_tun_address,
} => {
// if we're using a 'normal' gateway setup, do register
let our_identity = client_keys.identity_keypair();
// if wg address is set, use that one
let url = wg_tun_address.clone().unwrap_or(gateway_listener.clone());
let registration =
helpers::register_with_gateway(gateway_id, gateway_listener.clone(), our_identity)
.await?;
helpers::register_with_gateway(gateway_id, url, our_identity).await?;
(
GatewayDetails::new_remote(
gateway_id,
registration.shared_keys,
gateway_owner_address,
gateway_listener,
wg_tun_address,
),
Some(registration.authenticated_ephemeral_client),
)
@@ -161,7 +161,10 @@ where
let loaded_details = if let Some(gateway_id) = gateway_id {
load_gateway_details(details_store, &gateway_id).await?
} else {
load_active_gateway_details(details_store).await?
load_active_gateway_details(details_store)
.await?
.registration
.ok_or(ClientCoreError::NoActiveGatewaySet)?
};
let loaded_keys = load_client_keys(key_store).await?;
@@ -205,6 +208,7 @@ where
specification,
available_gateways,
overwrite_data,
wg_tun_address,
} => {
setup_new_gateway(
key_store,
@@ -212,6 +216,7 @@ where
overwrite_data,
specification,
available_gateways,
wg_tun_address,
)
.await
}
+53
View File
@@ -6,6 +6,7 @@ use crate::client::key_manager::ClientKeys;
use crate::config::Config;
use crate::error::ClientCoreError;
use crate::init::{setup_gateway, use_loaded_gateway_details};
use log::info;
use nym_client_core_gateways_storage::{
GatewayRegistration, GatewaysDetailsStore, RemoteGatewayDetails,
};
@@ -18,6 +19,7 @@ use nym_validator_client::client::IdentityKey;
use nym_validator_client::nyxd::AccountId;
use serde::Serialize;
use std::fmt::Display;
use std::net::IpAddr;
use std::str::FromStr;
use std::sync::Arc;
use time::OffsetDateTime;
@@ -30,6 +32,8 @@ pub enum SelectedGateway {
gateway_owner_address: AccountId,
gateway_listener: Url,
wg_tun_address: Option<Url>,
},
Custom {
gateway_id: identity::PublicKey,
@@ -37,9 +41,36 @@ pub enum SelectedGateway {
},
}
fn wg_tun_address(
tun_ip: Option<IpAddr>,
gateway: &gateway::Node,
) -> Result<Option<Url>, ClientCoreError> {
let Some(tun_ip) = tun_ip else {
return Ok(None);
};
// log this so we'd remember about it if we ever decided to actually use that port
if gateway.clients_wss_port.is_some() {
info!(
"gateway {} exposes wss but for wireguard we're going to use ws",
gateway.identity_key
);
}
let raw_url = format!("ws://{tun_ip}:{}", gateway.clients_ws_port);
Ok(Some(raw_url.as_str().parse().map_err(|source| {
ClientCoreError::MalformedListener {
gateway_id: gateway.identity_key.to_base58_string(),
raw_listener: raw_url,
source,
}
})?))
}
impl SelectedGateway {
pub fn from_topology_node(
node: gateway::Node,
wg_tun_ip_address: Option<IpAddr>,
must_use_tls: bool,
) -> Result<Self, ClientCoreError> {
let gateway_listener = if must_use_tls {
@@ -51,6 +82,8 @@ impl SelectedGateway {
node.clients_address()
};
let wg_tun_address = wg_tun_address(wg_tun_ip_address, &node)?;
let gateway_owner_address = AccountId::from_str(&node.owner).map_err(|source| {
ClientCoreError::MalformedGatewayOwnerAccountAddress {
gateway_id: node.identity_key.to_base58_string(),
@@ -70,6 +103,7 @@ impl SelectedGateway {
gateway_id: node.identity_key,
gateway_owner_address,
gateway_listener,
wg_tun_address,
})
}
@@ -209,6 +243,12 @@ pub enum GatewaySetup {
/// Specifies whether old data should be overwritten whilst setting up new gateway client.
overwrite_data: bool,
/// Implicitly specify whether the chosen gateway must use wireguard mode by setting the tun address.
///
/// Currently this is imperfect solution as I'd imagine this address could vary from gateway to gateway
/// so perhaps it should be part of gateway::Node struct
wg_tun_address: Option<IpAddr>,
},
ReuseConnection {
@@ -235,6 +275,19 @@ impl GatewaySetup {
}
}
/// new gateway setup performed by each client that's inbuilt in a gateway (like NR or IPR)
pub fn new_inbuilt(identity: identity::PublicKey) -> Self {
GatewaySetup::New {
specification: GatewaySelectionSpecification::Custom {
gateway_identity: identity.to_base58_string(),
additional_data: None,
},
available_gateways: vec![],
overwrite_data: false,
wg_tun_address: None,
}
}
pub async fn try_setup<K, D>(
self,
key_store: &K,
+2
View File
@@ -4,6 +4,7 @@
use crate::var_names::{DEPRECATED_API_VALIDATOR, DEPRECATED_NYMD_VALIDATOR, NYM_API, NYXD};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::net::{IpAddr, Ipv4Addr};
use std::path::Path;
use std::{
env::{var, VarError},
@@ -521,4 +522,5 @@ pub const WG_PORT: u16 = 51822;
// The interface used to route traffic
pub const WG_TUN_BASE_NAME: &str = "nymwg";
pub const WG_TUN_DEVICE_ADDRESS: &str = "10.1.0.1";
pub const WG_TUN_DEVICE_IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::new(10, 1, 0, 1));
pub const WG_TUN_DEVICE_NETMASK: &str = "255.255.255.0";
+4 -21
View File
@@ -16,10 +16,7 @@ use nym_network_defaults::mainnet;
use nym_network_defaults::var_names::NYXD;
use nym_network_defaults::var_names::{BECH32_PREFIX, NYM_API, STATISTICS_SERVICE_DOMAIN_ADDRESS};
use nym_network_requester::config::BaseClientConfig;
use nym_network_requester::{
setup_fs_gateways_storage, setup_gateway, GatewaySelectionSpecification, GatewaySetup,
OnDiskKeys,
};
use nym_network_requester::{setup_fs_gateways_storage, setup_gateway, GatewaySetup, OnDiskKeys};
use nym_types::gateway::{GatewayIpPacketRouterDetails, GatewayNetworkRequesterDetails};
use nym_validator_client::nyxd::AccountId;
use std::net::IpAddr;
@@ -251,7 +248,7 @@ pub(crate) fn override_ip_packet_router_config(
// disable poisson rate in the BASE client if the IPR option is enabled
if cfg.ip_packet_router.disable_poisson_rate {
log::info!("Disabling poisson rate for ip packet router");
info!("Disabling poisson rate for ip packet router");
cfg.set_no_poisson_process();
}
@@ -280,14 +277,7 @@ pub(crate) async fn initialise_local_network_requester(
// gateway setup here is way simpler as we're 'connecting' to ourselves
let init_res = setup_gateway(
GatewaySetup::New {
specification: GatewaySelectionSpecification::Custom {
gateway_identity: identity.to_base58_string(),
additional_data: Default::default(),
},
available_gateways: vec![],
overwrite_data: false,
},
GatewaySetup::new_inbuilt(identity),
&key_store,
&details_store,
)
@@ -353,14 +343,7 @@ pub(crate) async fn initialise_local_ip_packet_router(
// gateway setup here is way simpler as we're 'connecting' to ourselves
let init_res = setup_gateway(
GatewaySetup::New {
specification: GatewaySelectionSpecification::Custom {
gateway_identity: identity.to_base58_string(),
additional_data: Default::default(),
},
available_gateways: vec![],
overwrite_data: false,
},
GatewaySetup::new_inbuilt(identity),
&key_store,
&details_store,
)
+1 -1
View File
@@ -56,7 +56,7 @@ pub use nym_client_core::{
},
topology_control::geo_aware_provider::{CountryGroup, GeoAwareTopologyProvider},
},
config::{GatewayEndpointConfig, GroupBy},
config::GroupBy,
};
pub use nym_credential_storage::{
ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage,
+120 -106
View File
@@ -11,25 +11,27 @@ use crate::{Error, Result};
use futures::channel::mpsc;
use futures::StreamExt;
use log::warn;
use nym_client_core::client::base_client::storage::helpers::get_all_registered_identities;
use nym_client_core::client::base_client::storage::{
Ephemeral, GatewaysDetailsStore, MixnetClientStorage, OnDiskPersistent,
};
use nym_client_core::client::base_client::BaseClient;
use nym_client_core::client::key_manager::persistence::KeyStore;
use nym_client_core::client::{
base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend,
};
use nym_client_core::config::DebugConfig;
use nym_client_core::error::ClientCoreError;
use nym_client_core::init::helpers::current_gateways;
use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup};
use nym_client_core::{
client::{base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend},
config::GatewayEndpointConfig,
};
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, WG_TUN_DEVICE_ADDRESS};
use nym_network_defaults::WG_TUN_DEVICE_IP_ADDRESS;
use nym_socks5_client_core::config::Socks5;
use nym_task::manager::TaskStatus;
use nym_task::{TaskClient, TaskHandle};
use nym_topology::provider_trait::TopologyProvider;
use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient};
use rand::rngs::OsRng;
use std::net::IpAddr;
use std::path::Path;
use std::path::PathBuf;
use url::Url;
@@ -41,7 +43,6 @@ const DEFAULT_NUMBER_OF_SURBS: u32 = 10;
pub struct MixnetClientBuilder<S: MixnetClientStorage = Ephemeral> {
config: Config,
storage_paths: Option<StoragePaths>,
gateway_config: Option<GatewayEndpointConfig>,
socks5_config: Option<Socks5>,
wireguard_mode: bool,
@@ -78,7 +79,6 @@ impl MixnetClientBuilder<OnDiskPersistent> {
Ok(MixnetClientBuilder {
config: Default::default(),
storage_paths: None,
gateway_config: None,
socks5_config: None,
wireguard_mode: false,
wait_for_gateway: false,
@@ -98,6 +98,7 @@ impl<S> MixnetClientBuilder<S>
where
S: MixnetClientStorage + 'static,
S::ReplyStore: Send + Sync,
S::GatewaysDetailsStore: Sync,
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync,
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
@@ -109,7 +110,6 @@ where
MixnetClientBuilder {
config: Default::default(),
storage_paths: None,
gateway_config: None,
socks5_config: None,
wireguard_mode: false,
wait_for_gateway: false,
@@ -128,7 +128,6 @@ where
MixnetClientBuilder {
config: self.config,
storage_paths: self.storage_paths,
gateway_config: self.gateway_config,
socks5_config: self.socks5_config,
wireguard_mode: self.wireguard_mode,
wait_for_gateway: self.wait_for_gateway,
@@ -303,6 +302,7 @@ impl<S> DisconnectedMixnetClient<S>
where
S: MixnetClientStorage + 'static,
S::ReplyStore: Send + Sync,
S::GatewaysDetailsStore: Sync,
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync,
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
@@ -410,40 +410,58 @@ where
.collect()
}
/// Client keys are generated at client creation if none were found. The gateway shared
/// key, however, is created during the gateway registration handshake, so it might not
/// necessarily be available.
/// Furthermore, it has to be coupled with particular gateway's config.
async fn has_valid_gateway_info(&self) -> bool {
let keys = match self.storage.key_store().load_keys().await {
Ok(keys) => keys,
fn wireguard_tun_address(&self) -> Option<IpAddr> {
// currently use a hardcoded value here, but perhaps we should change that later
if self.wireguard_mode {
Some(WG_TUN_DEVICE_IP_ADDRESS)
} else {
None
}
}
async fn new_gateway_setup(&self) -> Result<GatewaySetup, ClientCoreError> {
let nym_api_endpoints = self.get_api_endpoints();
let selection_spec = GatewaySelectionSpecification::new(
self.config.user_chosen_gateway.clone(),
None,
self.force_tls,
);
let mut rng = OsRng;
let available_gateways = current_gateways(&mut rng, &nym_api_endpoints).await?;
Ok(GatewaySetup::New {
specification: selection_spec,
available_gateways,
overwrite_data: !self.config.key_mode.is_keep(),
wg_tun_address: self.wireguard_tun_address(),
})
}
/// Check if the client already has an active gateway enabled.
async fn has_active_gateway(&self) -> bool {
let storage = self.storage.gateway_details_store();
if storage.active_gateway().await.is_ok() {
return true;
}
match get_all_registered_identities(storage).await {
Err(err) => {
warn!("failed to load stored keys: {err}");
return false;
warn!("failed to query for all registered gateways: {err}")
}
};
Ok(all_ids) => {
if !all_ids.is_empty() {
warn!("this client doesn't have an active gateway set, however, it's already registered with the following gateways (consider making one of them active):");
for id in all_ids {
warn!("{id}")
}
}
}
}
todo!()
// let gateway_details = match self
// .storage
// .gateway_details_store()
// .load_gateway_details()
// .await
// {
// Ok(details) => details,
// Err(err) => {
// warn!("failed to load stored gateway details: {err}");
// return false;
// }
// };
//
// if let Err(err) = gateway_details.validate(keys.gateway_shared_key().as_deref()) {
// warn!("stored key verification failure: {err}");
// return false;
// }
//
// true
false
}
/// Register with a gateway. If a gateway is provided in the config then that will try to be
@@ -460,24 +478,10 @@ where
log::debug!("Registering with gateway");
let api_endpoints = self.get_api_endpoints();
let gateway_setup = if self.has_valid_gateway_info().await {
let gateway_setup = if self.has_active_gateway().await {
GatewaySetup::MustLoad { gateway_id: None }
} else {
let selection_spec = GatewaySelectionSpecification::new(
self.config.user_chosen_gateway.clone(),
None,
self.force_tls,
);
let mut rng = OsRng;
GatewaySetup::New {
specification: selection_spec,
available_gateways: current_gateways(&mut rng, &api_endpoints).await?,
overwrite_data: !self.config.key_mode.is_keep(),
}
self.new_gateway_setup().await?
};
// this will perform necessary key and details load and optional store
@@ -525,60 +529,70 @@ where
.config
.as_base_client_config(nyxd_endpoints, nym_api_endpoints.clone());
let known_gateway = self.has_valid_gateway_info().await;
let known_gateway = self.has_active_gateway().await;
let mut base_builder: BaseClientBuilder<_, _> = if !known_gateway {
let selection_spec = GatewaySelectionSpecification::new(
self.config.user_chosen_gateway,
None,
self.force_tls,
);
let mut rng = OsRng;
let mut available_gateways = current_gateways(&mut rng, &nym_api_endpoints).await?;
if self.wireguard_mode {
available_gateways
.iter_mut()
.for_each(|node| node.host = WG_TUN_DEVICE_ADDRESS.parse().unwrap());
}
let setup = GatewaySetup::New {
specification: selection_spec,
available_gateways,
overwrite_data: !self.config.key_mode.is_keep(),
};
BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
.with_wait_for_gateway(self.wait_for_gateway)
.with_gateway_setup(setup)
} else if self.wireguard_mode {
todo!()
// if let Ok(PersistedGatewayDetails::Default(mut config)) = self
// .storage
// .gateway_details_store()
// .load_gateway_details()
// .await
// {
// config.details.gateway_listener = format!(
// "ws://{}:{}",
// WG_TUN_DEVICE_ADDRESS, DEFAULT_CLIENT_LISTENING_PORT
// );
// if let Err(e) = self
// .storage
// .gateway_details_store()
// .store_gateway_details(&PersistedGatewayDetails::Default(config))
// .await
// {
// warn!("Could not switch to using wireguard mode - {:?}", e);
// }
// } else {
// warn!("Storage type not supported with wireguard mode");
// }
// BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
// .with_wait_for_gateway(self.wait_for_gateway)
// if we have a known gateway, don't bother doing all of those queries
let gateway_setup = if known_gateway {
None
} else {
Some(self.new_gateway_setup().await?)
};
let mut base_builder: BaseClientBuilder<_, _> =
BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
.with_wait_for_gateway(self.wait_for_gateway)
};
.with_wireguard_connection(self.wireguard_mode);
if !known_gateway {
// safety: `gateway_setup` is always set whenever `known_gateway` is false
base_builder = base_builder.with_gateway_setup(gateway_setup.unwrap());
}
// let mut base_builder: BaseClientBuilder<_, _> = if !known_gateway {
// // we need to setup a new gateway
// let setup = self.new_gateway_setup().await;
//
// BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
// .with_wait_for_gateway(self.wait_for_gateway)
// .with_gateway_setup(setup)
// // } else if self.wireguard_mode {
// // // load current active gateway in wireguard mode
// // details_store.set_wireguard_mode(true).await?;
// //
// // if let Ok(PersistedGatewayDetails::Default(mut config)) = self
// // .storage
// // .gateway_details_store()
// // .load_gateway_details()
// // .await
// // {
// // config.details.gateway_listener = format!(
// // "ws://{}:{}",
// // WG_TUN_DEVICE_ADDRESS, DEFAULT_CLIENT_LISTENING_PORT
// // );
// // if let Err(e) = self
// // .storage
// // .gateway_details_store()
// // .store_gateway_details(&PersistedGatewayDetails::Default(config))
// // .await
// // {
// // warn!("Could not switch to using wireguard mode - {:?}", e);
// // }
// // } else {
// // warn!("Storage type not supported with wireguard mode");
// // }
// // BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
// // .with_wait_for_gateway(self.wait_for_gateway)
// } else {
// // load current active gateway in non-wireguard mode
//
// // make sure our current storage mode matches the desired wg mode
// details_store
// .set_wireguard_mode(self.wireguard_mode)
// .await?;
//
// BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client)
// .with_wait_for_gateway(self.wait_for_gateway)
// };
if let Some(topology_provider) = self.custom_topology_provider {
base_builder = base_builder.with_topology_provider(topology_provider);