Get wireguard keypair as arg instead of reading it from disk (#6078)
* Get wireguard keypair as arg instead of reading it from disk * Move keypair out of NymNode * Remove legacy auth client
This commit is contained in:
committed by
GitHub
parent
53c4fde314
commit
026d3a6466
Generated
-2
@@ -4926,13 +4926,11 @@ dependencies = [
|
||||
"nym-bandwidth-controller",
|
||||
"nym-credentials-interface",
|
||||
"nym-crypto",
|
||||
"nym-pemstore",
|
||||
"nym-registration-common",
|
||||
"nym-sdk",
|
||||
"nym-service-provider-requests-common",
|
||||
"nym-validator-client",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"semver 1.0.26",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
|
||||
@@ -8,11 +8,6 @@ use nym_crypto::asymmetric::x25519::PublicKey;
|
||||
use nym_ip_packet_requests::IpPair;
|
||||
use nym_sphinx::addressing::{NodeIdentity, Recipient};
|
||||
|
||||
pub const DEFAULT_PRIVATE_ENTRY_WIREGUARD_KEY_FILENAME: &str = "free_private_entry_wireguard.pem";
|
||||
pub const DEFAULT_PUBLIC_ENTRY_WIREGUARD_KEY_FILENAME: &str = "free_public_entry_wireguard.pem";
|
||||
pub const DEFAULT_PRIVATE_EXIT_WIREGUARD_KEY_FILENAME: &str = "free_private_exit_wireguard.pem";
|
||||
pub const DEFAULT_PUBLIC_EXIT_WIREGUARD_KEY_FILENAME: &str = "free_public_exit_wireguard.pem";
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct NymNode {
|
||||
pub identity: NodeIdentity,
|
||||
|
||||
@@ -14,7 +14,6 @@ workspace = true
|
||||
[dependencies]
|
||||
bincode.workspace = true
|
||||
futures.workspace = true
|
||||
rand.workspace = true
|
||||
semver.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio-util.workspace = true
|
||||
@@ -25,7 +24,6 @@ nym-authenticator-requests = { path = "../common/authenticator-requests" }
|
||||
nym-bandwidth-controller = { path = "../common/bandwidth-controller" }
|
||||
nym-credentials-interface = { path = "../common/credentials-interface" }
|
||||
nym-crypto = { path = "../common/crypto" }
|
||||
nym-pemstore = { path = "../common/pemstore" }
|
||||
nym-registration-common = { path = "../common/registration" }
|
||||
nym-sdk = { path = "../sdk/rust/nym-sdk" }
|
||||
nym-service-provider-requests-common = { path = "../common/service-provider-requests-common" }
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_crypto::asymmetric::x25519::KeyPair;
|
||||
use nym_pemstore::KeyPairPath;
|
||||
use nym_sdk::mixnet::{IncludedSurbs, Recipient, TransmissionLane};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
|
||||
pub(crate) fn create_input_message(
|
||||
recipient: Recipient,
|
||||
@@ -27,23 +24,3 @@ pub(crate) fn create_input_message(
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load_or_generate_keypair<R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
paths: KeyPairPath,
|
||||
) -> KeyPair {
|
||||
match nym_pemstore::load_keypair(&paths) {
|
||||
Ok(keypair) => keypair,
|
||||
Err(_) => {
|
||||
let keypair = KeyPair::new(rng);
|
||||
if let Err(e) = nym_pemstore::store_keypair(&keypair, &paths) {
|
||||
tracing::error!(
|
||||
"could not store generated keypair at {:?} - {:?}; will use ephemeral keys",
|
||||
paths,
|
||||
e
|
||||
);
|
||||
}
|
||||
keypair
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::time::Duration;
|
||||
use tracing::{debug, error};
|
||||
|
||||
use crate::mixnet_listener::{MixnetMessageBroadcastReceiver, MixnetMessageInputSender};
|
||||
use crate::{helpers, ClientMessage, Error, Result};
|
||||
use nym_authenticator_requests::{
|
||||
client_message::QueryMessageImpl, response::AuthenticatorResponse, traits::Id, v2, v3, v4, v5,
|
||||
AuthenticatorVersion,
|
||||
};
|
||||
use nym_credentials_interface::CredentialSpendingData;
|
||||
use nym_crypto::asymmetric::x25519::{KeyPair, PublicKey};
|
||||
use nym_sdk::mixnet::{IncludedSurbs, Recipient};
|
||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderTypeExt};
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
|
||||
impl crate::AuthenticatorClient {
|
||||
pub fn into_legacy_and_keypair(self) -> (LegacyAuthenticatorClient, KeyPair) {
|
||||
(
|
||||
LegacyAuthenticatorClient {
|
||||
public_key: *self.keypair.public_key(),
|
||||
mixnet_listener: self.mixnet_listener,
|
||||
mixnet_sender: self.mixnet_sender,
|
||||
our_nym_address: self.our_nym_address,
|
||||
auth_recipient: self.auth_recipient,
|
||||
auth_version: self.auth_version,
|
||||
},
|
||||
self.keypair,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// This is the legacy Authenticator that has to be used to handle bandwidth top up for legacy gateaways
|
||||
pub struct LegacyAuthenticatorClient {
|
||||
public_key: PublicKey,
|
||||
mixnet_listener: MixnetMessageBroadcastReceiver,
|
||||
mixnet_sender: MixnetMessageInputSender,
|
||||
our_nym_address: Recipient,
|
||||
pub auth_recipient: Recipient,
|
||||
auth_version: AuthenticatorVersion,
|
||||
}
|
||||
|
||||
impl LegacyAuthenticatorClient {
|
||||
pub async fn send_and_wait_for_response(
|
||||
&mut self,
|
||||
message: &ClientMessage,
|
||||
) -> Result<AuthenticatorResponse> {
|
||||
let request_id = self.send_request(message).await?;
|
||||
|
||||
debug!("Waiting for reply...");
|
||||
self.listen_for_response(request_id).await
|
||||
}
|
||||
|
||||
async fn send_request(&self, message: &ClientMessage) -> Result<u64> {
|
||||
let (data, request_id) = message.bytes(self.our_nym_address)?;
|
||||
|
||||
// We use 20 surbs for the connect request because typically the
|
||||
// authenticator mixnet client on the nym-node is configured to have a min
|
||||
// threshold of 10 surbs that it reserves for itself to request additional
|
||||
// surbs.
|
||||
let surbs = if message.use_surbs() {
|
||||
match &message {
|
||||
ClientMessage::Initial(_) => IncludedSurbs::new(20),
|
||||
_ => IncludedSurbs::new(1),
|
||||
}
|
||||
} else {
|
||||
IncludedSurbs::ExposeSelfAddress
|
||||
};
|
||||
let input_message = helpers::create_input_message(self.auth_recipient, data, surbs);
|
||||
|
||||
self.mixnet_sender
|
||||
.send(input_message)
|
||||
.await
|
||||
.map_err(|e| Error::SendMixnetMessage(Box::new(e)))?;
|
||||
|
||||
Ok(request_id)
|
||||
}
|
||||
|
||||
async fn listen_for_response(&mut self, request_id: u64) -> Result<AuthenticatorResponse> {
|
||||
let timeout = tokio::time::sleep(Duration::from_secs(10));
|
||||
tokio::pin!(timeout);
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = &mut timeout => {
|
||||
error!("Timed out waiting for reply to connect request");
|
||||
return Err(Error::TimeoutWaitingForConnectResponse);
|
||||
}
|
||||
msg = self.mixnet_listener.recv() => match msg {
|
||||
Err(_) => {
|
||||
return Err(Error::NoMixnetMessagesReceived);
|
||||
}
|
||||
Ok(msg) => {
|
||||
let Some(header) = msg.message.first_chunk::<2>() else {
|
||||
debug!("received too short message that couldn't have been from the authenticator while waiting for connect response");
|
||||
continue;
|
||||
};
|
||||
|
||||
let Ok(protocol) = Protocol::try_from(header) else {
|
||||
debug!("received a message not meant to any service provider while waiting for connect response");
|
||||
continue;
|
||||
};
|
||||
|
||||
if !protocol.service_provider_type.is_authenticator() {
|
||||
debug!("Received non-authenticator message while waiting for connect response");
|
||||
continue;
|
||||
}
|
||||
// Confirm that the version is correct
|
||||
let version = AuthenticatorVersion::from(protocol.version);
|
||||
|
||||
// Then we deserialize the message
|
||||
debug!("AuthClient: got message while waiting for connect response with version {version:?}");
|
||||
let ret: Result<AuthenticatorResponse> = match version {
|
||||
AuthenticatorVersion::V1 => Err(Error::UnsupportedVersion),
|
||||
AuthenticatorVersion::V2 => v2::response::AuthenticatorResponse::from_reconstructed_message(&msg).map(Into::into).map_err(Into::into),
|
||||
AuthenticatorVersion::V3 => v3::response::AuthenticatorResponse::from_reconstructed_message(&msg).map(Into::into).map_err(Into::into),
|
||||
AuthenticatorVersion::V4 => v4::response::AuthenticatorResponse::from_reconstructed_message(&msg).map(Into::into).map_err(Into::into),
|
||||
AuthenticatorVersion::V5 => v5::response::AuthenticatorResponse::from_reconstructed_message(&msg).map(Into::into).map_err(Into::into),
|
||||
AuthenticatorVersion::UNKNOWN => Err(Error::UnknownVersion),
|
||||
};
|
||||
let Ok(response) = ret else {
|
||||
// This is ok, it's likely just one of our self-pings
|
||||
debug!("Failed to deserialize reconstructed message");
|
||||
continue;
|
||||
};
|
||||
|
||||
if response.id() == request_id {
|
||||
debug!("Got response with matching id");
|
||||
return Ok(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn query_bandwidth(&mut self) -> Result<Option<i64>> {
|
||||
let query_message = match self.auth_version {
|
||||
AuthenticatorVersion::V1 => return Err(Error::UnsupportedAuthenticatorVersion),
|
||||
AuthenticatorVersion::V2 => ClientMessage::Query(Box::new(QueryMessageImpl {
|
||||
pub_key: PeerPublicKey::new(self.public_key.to_bytes().into()),
|
||||
version: AuthenticatorVersion::V2,
|
||||
})),
|
||||
AuthenticatorVersion::V3 => ClientMessage::Query(Box::new(QueryMessageImpl {
|
||||
pub_key: PeerPublicKey::new(self.public_key.to_bytes().into()),
|
||||
version: AuthenticatorVersion::V3,
|
||||
})),
|
||||
AuthenticatorVersion::V4 => ClientMessage::Query(Box::new(QueryMessageImpl {
|
||||
pub_key: PeerPublicKey::new(self.public_key.to_bytes().into()),
|
||||
version: AuthenticatorVersion::V4,
|
||||
})),
|
||||
AuthenticatorVersion::V5 => ClientMessage::Query(Box::new(QueryMessageImpl {
|
||||
pub_key: PeerPublicKey::new(self.public_key.to_bytes().into()),
|
||||
version: AuthenticatorVersion::V5,
|
||||
})),
|
||||
AuthenticatorVersion::UNKNOWN => return Err(Error::UnsupportedAuthenticatorVersion),
|
||||
};
|
||||
let response = self.send_and_wait_for_response(&query_message).await?;
|
||||
|
||||
let available_bandwidth = match response {
|
||||
AuthenticatorResponse::RemainingBandwidth(remaining_bandwidth_response) => {
|
||||
if let Some(available_bandwidth) =
|
||||
remaining_bandwidth_response.available_bandwidth()
|
||||
{
|
||||
available_bandwidth
|
||||
} else {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::InvalidGatewayAuthResponse),
|
||||
};
|
||||
|
||||
let remaining_pretty = if available_bandwidth > 1024 * 1024 {
|
||||
format!("{:.2} MB", available_bandwidth as f64 / 1024.0 / 1024.0)
|
||||
} else {
|
||||
format!("{} KB", available_bandwidth / 1024)
|
||||
};
|
||||
tracing::debug!(
|
||||
"Remaining wireguard bandwidth with gateway {} for today: {}",
|
||||
self.auth_recipient.gateway(),
|
||||
remaining_pretty
|
||||
);
|
||||
if available_bandwidth < 1024 * 1024 {
|
||||
tracing::warn!(
|
||||
"Remaining bandwidth is under 1 MB. The wireguard mode will get suspended after that until tomorrow, UTC time. The client might shutdown with timeout soon"
|
||||
);
|
||||
}
|
||||
Ok(Some(available_bandwidth))
|
||||
}
|
||||
|
||||
pub async fn top_up(&mut self, credential: CredentialSpendingData) -> Result<i64> {
|
||||
let top_up_message = match self.auth_version {
|
||||
AuthenticatorVersion::V3 => ClientMessage::TopUp(Box::new(v3::topup::TopUpMessage {
|
||||
pub_key: PeerPublicKey::new(self.public_key.to_bytes().into()),
|
||||
credential,
|
||||
})),
|
||||
// NOTE: looks like a bug here using v3. But we're leaving it as is since it's working
|
||||
// and V4 is deprecated in favour of V5
|
||||
AuthenticatorVersion::V4 => ClientMessage::TopUp(Box::new(v4::topup::TopUpMessage {
|
||||
pub_key: PeerPublicKey::new(self.public_key.to_bytes().into()),
|
||||
credential,
|
||||
})),
|
||||
AuthenticatorVersion::V5 => ClientMessage::TopUp(Box::new(v5::topup::TopUpMessage {
|
||||
pub_key: PeerPublicKey::new(self.public_key.to_bytes().into()),
|
||||
credential,
|
||||
})),
|
||||
AuthenticatorVersion::V1 | AuthenticatorVersion::V2 | AuthenticatorVersion::UNKNOWN => {
|
||||
return Err(Error::UnsupportedAuthenticatorVersion);
|
||||
}
|
||||
};
|
||||
let response = self.send_and_wait_for_response(&top_up_message).await?;
|
||||
|
||||
let remaining_bandwidth = match response {
|
||||
AuthenticatorResponse::TopUpBandwidth(top_up_bandwidth_response) => {
|
||||
top_up_bandwidth_response.available_bandwidth()
|
||||
}
|
||||
_ => return Err(Error::InvalidGatewayAuthResponse),
|
||||
};
|
||||
|
||||
Ok(remaining_bandwidth)
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_authenticator_requests::client_message::QueryMessageImpl;
|
||||
use nym_bandwidth_controller::{BandwidthTicketProvider, DEFAULT_TICKETS_TO_SPEND};
|
||||
use nym_registration_common::{
|
||||
GatewayData, DEFAULT_PRIVATE_ENTRY_WIREGUARD_KEY_FILENAME,
|
||||
DEFAULT_PRIVATE_EXIT_WIREGUARD_KEY_FILENAME, DEFAULT_PUBLIC_ENTRY_WIREGUARD_KEY_FILENAME,
|
||||
DEFAULT_PUBLIC_EXIT_WIREGUARD_KEY_FILENAME,
|
||||
};
|
||||
use rand::rngs::OsRng;
|
||||
use nym_crypto::asymmetric::x25519::KeyPair;
|
||||
use nym_registration_common::GatewayData;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
@@ -19,20 +16,16 @@ use nym_authenticator_requests::{
|
||||
client_message::ClientMessage, response::AuthenticatorResponse, traits::Id, v2, v3, v4, v5,
|
||||
AuthenticatorVersion,
|
||||
};
|
||||
use nym_credentials_interface::TicketType;
|
||||
use nym_crypto::asymmetric::x25519::KeyPair;
|
||||
use nym_pemstore::KeyPairPath;
|
||||
use nym_credentials_interface::{CredentialSpendingData, TicketType};
|
||||
use nym_sdk::mixnet::{IncludedSurbs, Recipient};
|
||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderTypeExt};
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
|
||||
mod error;
|
||||
mod helpers;
|
||||
mod legacy;
|
||||
mod mixnet_listener;
|
||||
|
||||
pub use crate::error::{Error, Result};
|
||||
pub use crate::legacy::LegacyAuthenticatorClient;
|
||||
pub use crate::mixnet_listener::{AuthClientMixnetListener, AuthClientMixnetListenerHandle};
|
||||
|
||||
pub struct AuthenticatorClient {
|
||||
@@ -42,34 +35,21 @@ pub struct AuthenticatorClient {
|
||||
pub auth_recipient: Recipient,
|
||||
auth_version: AuthenticatorVersion,
|
||||
|
||||
keypair: KeyPair,
|
||||
keypair: Arc<KeyPair>,
|
||||
ip_addr: IpAddr,
|
||||
}
|
||||
|
||||
impl AuthenticatorClient {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn new_type(
|
||||
data_path: &Option<PathBuf>,
|
||||
pub fn new(
|
||||
mixnet_listener: MixnetMessageBroadcastReceiver,
|
||||
mixnet_sender: MixnetMessageInputSender,
|
||||
our_nym_address: Recipient,
|
||||
auth_recipient: Recipient,
|
||||
auth_version: AuthenticatorVersion,
|
||||
private_file_name: &str,
|
||||
public_file_name: &str,
|
||||
keypair: Arc<KeyPair>,
|
||||
ip_addr: IpAddr,
|
||||
) -> Self {
|
||||
let mut rng = OsRng;
|
||||
|
||||
let keypair = if let Some(data_path) = data_path {
|
||||
let paths = KeyPairPath::new(
|
||||
data_path.join(private_file_name),
|
||||
data_path.join(public_file_name),
|
||||
);
|
||||
helpers::load_or_generate_keypair(&mut rng, paths)
|
||||
} else {
|
||||
KeyPair::new(&mut rng)
|
||||
};
|
||||
Self {
|
||||
mixnet_listener,
|
||||
mixnet_sender,
|
||||
@@ -81,50 +61,6 @@ impl AuthenticatorClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_entry(
|
||||
data_path: &Option<PathBuf>,
|
||||
mixnet_listener: MixnetMessageBroadcastReceiver,
|
||||
mixnet_sender: MixnetMessageInputSender,
|
||||
our_nym_address: Recipient,
|
||||
auth_recipient: Recipient,
|
||||
auth_version: AuthenticatorVersion,
|
||||
ip_addr: IpAddr,
|
||||
) -> Self {
|
||||
Self::new_type(
|
||||
data_path,
|
||||
mixnet_listener,
|
||||
mixnet_sender,
|
||||
our_nym_address,
|
||||
auth_recipient,
|
||||
auth_version,
|
||||
DEFAULT_PRIVATE_ENTRY_WIREGUARD_KEY_FILENAME,
|
||||
DEFAULT_PUBLIC_ENTRY_WIREGUARD_KEY_FILENAME,
|
||||
ip_addr,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_exit(
|
||||
data_path: &Option<PathBuf>,
|
||||
mixnet_listener: MixnetMessageBroadcastReceiver,
|
||||
mixnet_sender: MixnetMessageInputSender,
|
||||
our_nym_address: Recipient,
|
||||
auth_recipient: Recipient,
|
||||
auth_version: AuthenticatorVersion,
|
||||
ip_addr: IpAddr,
|
||||
) -> Self {
|
||||
Self::new_type(
|
||||
data_path,
|
||||
mixnet_listener,
|
||||
mixnet_sender,
|
||||
our_nym_address,
|
||||
auth_recipient,
|
||||
auth_version,
|
||||
DEFAULT_PRIVATE_EXIT_WIREGUARD_KEY_FILENAME,
|
||||
DEFAULT_PUBLIC_EXIT_WIREGUARD_KEY_FILENAME,
|
||||
ip_addr,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn send_and_wait_for_response(
|
||||
&mut self,
|
||||
message: &ClientMessage,
|
||||
@@ -365,4 +301,91 @@ impl AuthenticatorClient {
|
||||
|
||||
Ok(gateway_data)
|
||||
}
|
||||
|
||||
pub async fn query_bandwidth(&mut self) -> Result<Option<i64>> {
|
||||
let query_message = match self.auth_version {
|
||||
AuthenticatorVersion::V1 => return Err(Error::UnsupportedAuthenticatorVersion),
|
||||
AuthenticatorVersion::V2 => ClientMessage::Query(Box::new(QueryMessageImpl {
|
||||
pub_key: PeerPublicKey::new(self.keypair.public_key().to_bytes().into()),
|
||||
version: AuthenticatorVersion::V2,
|
||||
})),
|
||||
AuthenticatorVersion::V3 => ClientMessage::Query(Box::new(QueryMessageImpl {
|
||||
pub_key: PeerPublicKey::new(self.keypair.public_key().to_bytes().into()),
|
||||
version: AuthenticatorVersion::V3,
|
||||
})),
|
||||
AuthenticatorVersion::V4 => ClientMessage::Query(Box::new(QueryMessageImpl {
|
||||
pub_key: PeerPublicKey::new(self.keypair.public_key().to_bytes().into()),
|
||||
version: AuthenticatorVersion::V4,
|
||||
})),
|
||||
AuthenticatorVersion::V5 => ClientMessage::Query(Box::new(QueryMessageImpl {
|
||||
pub_key: PeerPublicKey::new(self.keypair.public_key().to_bytes().into()),
|
||||
version: AuthenticatorVersion::V5,
|
||||
})),
|
||||
AuthenticatorVersion::UNKNOWN => return Err(Error::UnsupportedAuthenticatorVersion),
|
||||
};
|
||||
let response = self.send_and_wait_for_response(&query_message).await?;
|
||||
|
||||
let available_bandwidth = match response {
|
||||
AuthenticatorResponse::RemainingBandwidth(remaining_bandwidth_response) => {
|
||||
if let Some(available_bandwidth) =
|
||||
remaining_bandwidth_response.available_bandwidth()
|
||||
{
|
||||
available_bandwidth
|
||||
} else {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::InvalidGatewayAuthResponse),
|
||||
};
|
||||
|
||||
let remaining_pretty = if available_bandwidth > 1024 * 1024 {
|
||||
format!("{:.2} MB", available_bandwidth as f64 / 1024.0 / 1024.0)
|
||||
} else {
|
||||
format!("{} KB", available_bandwidth / 1024)
|
||||
};
|
||||
tracing::debug!(
|
||||
"Remaining wireguard bandwidth with gateway {} for today: {}",
|
||||
self.auth_recipient.gateway(),
|
||||
remaining_pretty
|
||||
);
|
||||
if available_bandwidth < 1024 * 1024 {
|
||||
tracing::warn!(
|
||||
"Remaining bandwidth is under 1 MB. The wireguard mode will get suspended after that until tomorrow, UTC time. The client might shutdown with timeout soon
|
||||
"
|
||||
);
|
||||
}
|
||||
Ok(Some(available_bandwidth))
|
||||
}
|
||||
|
||||
pub async fn top_up(&mut self, credential: CredentialSpendingData) -> Result<i64> {
|
||||
let top_up_message = match self.auth_version {
|
||||
AuthenticatorVersion::V3 => ClientMessage::TopUp(Box::new(v3::topup::TopUpMessage {
|
||||
pub_key: PeerPublicKey::new(self.keypair.public_key().to_bytes().into()),
|
||||
credential,
|
||||
})),
|
||||
// NOTE: looks like a bug here using v3. But we're leaving it as is since it's working
|
||||
// and V4 is deprecated in favour of V5
|
||||
AuthenticatorVersion::V4 => ClientMessage::TopUp(Box::new(v4::topup::TopUpMessage {
|
||||
pub_key: PeerPublicKey::new(self.keypair.public_key().to_bytes().into()),
|
||||
credential,
|
||||
})),
|
||||
AuthenticatorVersion::V5 => ClientMessage::TopUp(Box::new(v5::topup::TopUpMessage {
|
||||
pub_key: PeerPublicKey::new(self.keypair.public_key().to_bytes().into()),
|
||||
credential,
|
||||
})),
|
||||
AuthenticatorVersion::V1 | AuthenticatorVersion::V2 | AuthenticatorVersion::UNKNOWN => {
|
||||
return Err(Error::UnsupportedAuthenticatorVersion);
|
||||
}
|
||||
};
|
||||
let response = self.send_and_wait_for_response(&top_up_message).await?;
|
||||
|
||||
let remaining_bandwidth = match response {
|
||||
AuthenticatorResponse::TopUpBandwidth(top_up_bandwidth_response) => {
|
||||
top_up_bandwidth_response.available_bandwidth()
|
||||
}
|
||||
_ => return Err(Error::InvalidGatewayAuthResponse),
|
||||
};
|
||||
|
||||
Ok(remaining_bandwidth)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,24 +5,31 @@ use nym_credential_storage::persistent_storage::PersistentStorage;
|
||||
use nym_registration_common::NymNode;
|
||||
use nym_sdk::{
|
||||
mixnet::{
|
||||
CredentialStorage, GatewaysDetailsStore, KeyStore, MixnetClient, MixnetClientBuilder,
|
||||
MixnetClientStorage, OnDiskPersistent, ReplyStorageBackend, StoragePaths,
|
||||
x25519::KeyPair, CredentialStorage, GatewaysDetailsStore, KeyStore, MixnetClient,
|
||||
MixnetClientBuilder, MixnetClientStorage, OnDiskPersistent, ReplyStorageBackend,
|
||||
StoragePaths,
|
||||
},
|
||||
DebugConfig, NymNetworkDetails, RememberMe, TopologyProvider, UserAgent,
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::{os::fd::RawFd, sync::Arc};
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
use std::os::fd::RawFd;
|
||||
use std::{path::PathBuf, sync::Arc, time::Duration};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::error::RegistrationClientError;
|
||||
|
||||
const VPN_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(15);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NymNodeWithKeys {
|
||||
pub node: NymNode,
|
||||
pub keys: Arc<KeyPair>,
|
||||
}
|
||||
|
||||
pub struct BuilderConfig {
|
||||
pub entry_node: NymNode,
|
||||
pub exit_node: NymNode,
|
||||
pub entry_node: NymNodeWithKeys,
|
||||
pub exit_node: NymNodeWithKeys,
|
||||
pub data_path: Option<PathBuf>,
|
||||
pub mixnet_client_config: MixnetClientConfig,
|
||||
pub two_hops: bool,
|
||||
@@ -104,7 +111,7 @@ impl BuilderConfig {
|
||||
|
||||
let builder = builder
|
||||
.with_user_agent(self.user_agent)
|
||||
.request_gateway(self.entry_node.identity.to_string())
|
||||
.request_gateway(self.entry_node.node.identity.to_string())
|
||||
.network_details(self.network_env)
|
||||
.debug_config(debug_config)
|
||||
.credentials_mode(true)
|
||||
|
||||
@@ -32,10 +32,9 @@ impl RegistrationClientBuilder {
|
||||
pub async fn build(self) -> Result<RegistrationClient, RegistrationClientError> {
|
||||
let storage = self.config.setup_storage().await?;
|
||||
let config = RegistrationClientConfig {
|
||||
entry: self.config.entry_node,
|
||||
exit: self.config.exit_node,
|
||||
entry: self.config.entry_node.clone(),
|
||||
exit: self.config.exit_node.clone(),
|
||||
two_hops: self.config.two_hops,
|
||||
data_path: self.config.data_path.clone(),
|
||||
};
|
||||
let cancel_token = self.config.cancel_token.clone();
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_registration_common::NymNode;
|
||||
use std::path::PathBuf;
|
||||
use crate::builder::config::NymNodeWithKeys;
|
||||
|
||||
pub struct RegistrationClientConfig {
|
||||
pub(crate) entry: NymNode,
|
||||
pub(crate) exit: NymNode,
|
||||
pub(crate) entry: NymNodeWithKeys,
|
||||
pub(crate) exit: NymNodeWithKeys,
|
||||
pub(crate) two_hops: bool,
|
||||
pub(crate) data_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@ mod config;
|
||||
mod error;
|
||||
mod types;
|
||||
|
||||
pub use builder::config::{BuilderConfig as RegistrationClientBuilderConfig, MixnetClientConfig};
|
||||
pub use builder::config::{
|
||||
BuilderConfig as RegistrationClientBuilderConfig, MixnetClientConfig,
|
||||
NymNodeWithKeys as RegistrationNymNode,
|
||||
};
|
||||
pub use builder::RegistrationClientBuilder;
|
||||
pub use error::RegistrationClientError;
|
||||
pub use types::{MixnetRegistrationResult, RegistrationResult, WireguardRegistrationResult};
|
||||
@@ -32,13 +35,13 @@ pub struct RegistrationClient {
|
||||
|
||||
impl RegistrationClient {
|
||||
async fn register_mix_exit(self) -> Result<RegistrationResult, RegistrationClientError> {
|
||||
let entry_mixnet_gateway_ip = self.config.entry.ip_address;
|
||||
let entry_mixnet_gateway_ip = self.config.entry.node.ip_address;
|
||||
|
||||
let exit_mixnet_gateway_ip = self.config.exit.ip_address;
|
||||
let exit_mixnet_gateway_ip = self.config.exit.node.ip_address;
|
||||
|
||||
let ipr_address = self.config.exit.ipr_address.ok_or(
|
||||
let ipr_address = self.config.exit.node.ipr_address.ok_or(
|
||||
RegistrationClientError::NoIpPacketRouterAddress {
|
||||
node_id: self.config.exit.identity.to_base58_string(),
|
||||
node_id: self.config.exit.node.identity.to_base58_string(),
|
||||
},
|
||||
)?;
|
||||
let mut ipr_client =
|
||||
@@ -63,21 +66,21 @@ impl RegistrationClient {
|
||||
}
|
||||
|
||||
async fn register_wg(self) -> Result<RegistrationResult, RegistrationClientError> {
|
||||
let entry_auth_address = self.config.entry.authenticator_address.ok_or(
|
||||
let entry_auth_address = self.config.entry.node.authenticator_address.ok_or(
|
||||
RegistrationClientError::AuthenticationNotPossible {
|
||||
node_id: self.config.entry.identity.to_base58_string(),
|
||||
node_id: self.config.entry.node.identity.to_base58_string(),
|
||||
},
|
||||
)?;
|
||||
|
||||
let exit_auth_address = self.config.exit.authenticator_address.ok_or(
|
||||
let exit_auth_address = self.config.exit.node.authenticator_address.ok_or(
|
||||
RegistrationClientError::AuthenticationNotPossible {
|
||||
node_id: self.config.exit.identity.to_base58_string(),
|
||||
node_id: self.config.exit.node.identity.to_base58_string(),
|
||||
},
|
||||
)?;
|
||||
|
||||
let entry_version = self.config.entry.version;
|
||||
let entry_version = self.config.entry.node.version;
|
||||
tracing::debug!("Entry gateway version: {entry_version}");
|
||||
let exit_version = self.config.exit.version;
|
||||
let exit_version = self.config.exit.node.version;
|
||||
tracing::debug!("Exit gateway version: {exit_version}");
|
||||
|
||||
// Start the auth client mixnet listener, which will listen for incoming messages from the
|
||||
@@ -85,24 +88,24 @@ impl RegistrationClient {
|
||||
let mixnet_listener =
|
||||
AuthClientMixnetListener::new(self.mixnet_client, self.cancel_token.clone()).start();
|
||||
|
||||
let mut entry_auth_client = AuthenticatorClient::new_entry(
|
||||
&self.config.data_path,
|
||||
let mut entry_auth_client = AuthenticatorClient::new(
|
||||
mixnet_listener.subscribe(),
|
||||
mixnet_listener.mixnet_sender(),
|
||||
self.mixnet_client_address,
|
||||
entry_auth_address,
|
||||
entry_version,
|
||||
self.config.entry.ip_address,
|
||||
self.config.entry.keys,
|
||||
self.config.entry.node.ip_address,
|
||||
);
|
||||
|
||||
let mut exit_auth_client = AuthenticatorClient::new_exit(
|
||||
&self.config.data_path,
|
||||
let mut exit_auth_client = AuthenticatorClient::new(
|
||||
mixnet_listener.subscribe(),
|
||||
mixnet_listener.mixnet_sender(),
|
||||
self.mixnet_client_address,
|
||||
exit_auth_address,
|
||||
exit_version,
|
||||
self.config.exit.ip_address,
|
||||
self.config.exit.keys,
|
||||
self.config.exit.node.ip_address,
|
||||
);
|
||||
|
||||
let entry_fut = entry_auth_client
|
||||
@@ -115,7 +118,7 @@ impl RegistrationClient {
|
||||
let entry =
|
||||
entry.map_err(
|
||||
|source| RegistrationClientError::EntryGatewayRegisterWireguard {
|
||||
gateway_id: self.config.entry.identity.to_base58_string(),
|
||||
gateway_id: self.config.entry.node.identity.to_base58_string(),
|
||||
authenticator_address: Box::new(entry_auth_address),
|
||||
source: Box::new(source),
|
||||
},
|
||||
@@ -123,7 +126,7 @@ impl RegistrationClient {
|
||||
let exit =
|
||||
exit.map_err(
|
||||
|source| RegistrationClientError::ExitGatewayRegisterWireguard {
|
||||
gateway_id: self.config.exit.identity.to_base58_string(),
|
||||
gateway_id: self.config.exit.node.identity.to_base58_string(),
|
||||
authenticator_address: Box::new(exit_auth_address),
|
||||
source: Box::new(source),
|
||||
},
|
||||
|
||||
@@ -63,7 +63,7 @@ pub use nym_credential_storage::{
|
||||
ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage,
|
||||
models::StoredIssuedTicketbook, storage::Storage as CredentialStorage,
|
||||
};
|
||||
pub use nym_crypto::asymmetric::ed25519;
|
||||
pub use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
pub use nym_network_defaults::NymNetworkDetails;
|
||||
pub use nym_socks5_client_core::config::Socks5;
|
||||
pub use nym_sphinx::{
|
||||
|
||||
Reference in New Issue
Block a user