IPv6 support for wireguard (#5059)
* Add ipv6 in configs * Make v4 latest * Fix linux * IPv6 prefix in config * Fix template of private ip * Fix clippy * Fix v6 cidr * Move from 2001:db8::/32 to fc00::/7 addresses * Fix version number on conversion
This commit is contained in:
committed by
GitHub
parent
bfd7240dcd
commit
44ae29b06d
Generated
+1
@@ -4622,6 +4622,7 @@ dependencies = [
|
||||
"hmac",
|
||||
"nym-credentials-interface",
|
||||
"nym-crypto",
|
||||
"nym-network-defaults",
|
||||
"nym-service-provider-requests-common",
|
||||
"nym-sphinx",
|
||||
"nym-wireguard-types",
|
||||
|
||||
@@ -17,6 +17,7 @@ thiserror = { workspace = true }
|
||||
|
||||
nym-credentials-interface = { path = "../credentials-interface" }
|
||||
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
nym-service-provider-requests-common = { path = "../service-provider-requests-common" }
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
nym-wireguard-types = { path = "../wireguard-types" }
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
pub mod v1;
|
||||
pub mod v2;
|
||||
pub mod v3;
|
||||
pub mod v4;
|
||||
|
||||
mod error;
|
||||
|
||||
pub use error::Error;
|
||||
pub use v3 as latest;
|
||||
pub use v4 as latest;
|
||||
|
||||
pub const CURRENT_VERSION: u8 = 3;
|
||||
pub const CURRENT_VERSION: u8 = 4;
|
||||
|
||||
fn make_bincode_serializer() -> impl bincode::Options {
|
||||
use bincode::Options;
|
||||
|
||||
@@ -9,7 +9,7 @@ impl From<v2::request::AuthenticatorRequest> for v3::request::AuthenticatorReque
|
||||
fn from(authenticator_request: v2::request::AuthenticatorRequest) -> Self {
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
version: 2,
|
||||
version: 3,
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
},
|
||||
data: authenticator_request.data.into(),
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
||||
|
||||
use crate::{v3, v4};
|
||||
|
||||
impl From<v3::request::AuthenticatorRequest> for v4::request::AuthenticatorRequest {
|
||||
fn from(authenticator_request: v3::request::AuthenticatorRequest) -> Self {
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
version: 4,
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
},
|
||||
data: authenticator_request.data.into(),
|
||||
reply_to: authenticator_request.reply_to,
|
||||
request_id: authenticator_request.request_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v3::request::AuthenticatorRequestData> for v4::request::AuthenticatorRequestData {
|
||||
fn from(authenticator_request_data: v3::request::AuthenticatorRequestData) -> Self {
|
||||
match authenticator_request_data {
|
||||
v3::request::AuthenticatorRequestData::Initial(init_msg) => {
|
||||
v4::request::AuthenticatorRequestData::Initial(init_msg.into())
|
||||
}
|
||||
v3::request::AuthenticatorRequestData::Final(gw_client) => {
|
||||
v4::request::AuthenticatorRequestData::Final(gw_client.into())
|
||||
}
|
||||
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => {
|
||||
v4::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
|
||||
}
|
||||
v3::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
|
||||
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v3::registration::InitMessage> for v4::registration::InitMessage {
|
||||
fn from(init_msg: v3::registration::InitMessage) -> Self {
|
||||
Self {
|
||||
pub_key: init_msg.pub_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<v3::registration::FinalMessage>> for Box<v4::registration::FinalMessage> {
|
||||
fn from(gw_client: Box<v3::registration::FinalMessage>) -> Self {
|
||||
Box::new(v4::registration::FinalMessage {
|
||||
gateway_client: gw_client.gateway_client.into(),
|
||||
credential: gw_client.credential,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<v3::topup::TopUpMessage>> for Box<v4::topup::TopUpMessage> {
|
||||
fn from(top_up_message: Box<v3::topup::TopUpMessage>) -> Self {
|
||||
Box::new(v4::topup::TopUpMessage {
|
||||
pub_key: top_up_message.pub_key,
|
||||
credential: top_up_message.credential,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v3::registration::GatewayClient> for v4::registration::GatewayClient {
|
||||
fn from(gw_client: v3::registration::GatewayClient) -> Self {
|
||||
Self {
|
||||
pub_key: gw_client.pub_key,
|
||||
private_ips: gw_client.private_ip.into(),
|
||||
mac: gw_client.mac.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4::registration::GatewayClient> for v3::registration::GatewayClient {
|
||||
fn from(gw_client: v4::registration::GatewayClient) -> Self {
|
||||
Self {
|
||||
pub_key: gw_client.pub_key,
|
||||
private_ip: gw_client.private_ips.ipv4.into(),
|
||||
mac: gw_client.mac.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v3::registration::ClientMac> for v4::registration::ClientMac {
|
||||
fn from(mac: v3::registration::ClientMac) -> Self {
|
||||
Self::new(mac.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4::registration::ClientMac> for v3::registration::ClientMac {
|
||||
fn from(mac: v4::registration::ClientMac) -> Self {
|
||||
Self::new(mac.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<v4::response::AuthenticatorResponse> for v3::response::AuthenticatorResponse {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(
|
||||
authenticator_response: v4::response::AuthenticatorResponse,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
data: authenticator_response.data.try_into()?,
|
||||
reply_to: authenticator_response.reply_to,
|
||||
protocol: authenticator_response.protocol,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<v4::response::AuthenticatorResponseData> for v3::response::AuthenticatorResponseData {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(
|
||||
authenticator_response_data: v4::response::AuthenticatorResponseData,
|
||||
) -> Result<Self, Self::Error> {
|
||||
match authenticator_response_data {
|
||||
v4::response::AuthenticatorResponseData::PendingRegistration(
|
||||
pending_registration_response,
|
||||
) => Ok(
|
||||
v3::response::AuthenticatorResponseData::PendingRegistration(
|
||||
pending_registration_response.into(),
|
||||
),
|
||||
),
|
||||
v4::response::AuthenticatorResponseData::Registered(registered_response) => Ok(
|
||||
v3::response::AuthenticatorResponseData::Registered(registered_response.into()),
|
||||
),
|
||||
v4::response::AuthenticatorResponseData::RemainingBandwidth(
|
||||
remaining_bandwidth_response,
|
||||
) => Ok(v3::response::AuthenticatorResponseData::RemainingBandwidth(
|
||||
remaining_bandwidth_response.into(),
|
||||
)),
|
||||
v4::response::AuthenticatorResponseData::TopUpBandwidth(_) => {
|
||||
Err(Self::Error::Conversion(
|
||||
"a v3 request couldn't produce a v4 only type of response".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4::response::PendingRegistrationResponse> for v3::response::PendingRegistrationResponse {
|
||||
fn from(value: v4::response::PendingRegistrationResponse) -> Self {
|
||||
Self {
|
||||
request_id: value.request_id,
|
||||
reply_to: value.reply_to,
|
||||
reply: value.reply.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4::response::RegisteredResponse> for v3::response::RegisteredResponse {
|
||||
fn from(value: v4::response::RegisteredResponse) -> Self {
|
||||
Self {
|
||||
request_id: value.request_id,
|
||||
reply_to: value.reply_to,
|
||||
reply: value.reply.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4::response::RemainingBandwidthResponse> for v3::response::RemainingBandwidthResponse {
|
||||
fn from(value: v4::response::RemainingBandwidthResponse) -> Self {
|
||||
Self {
|
||||
request_id: value.request_id,
|
||||
reply_to: value.reply_to,
|
||||
reply: value.reply.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4::registration::RegistrationData> for v3::registration::RegistrationData {
|
||||
fn from(value: v4::registration::RegistrationData) -> Self {
|
||||
Self {
|
||||
nonce: value.nonce,
|
||||
gateway_data: value.gateway_data.into(),
|
||||
wg_port: value.wg_port,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4::registration::RegistredData> for v3::registration::RegistredData {
|
||||
fn from(value: v4::registration::RegistredData) -> Self {
|
||||
Self {
|
||||
pub_key: value.pub_key,
|
||||
private_ip: value.private_ips.ipv4.into(),
|
||||
wg_port: value.wg_port,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4::registration::RemainingBandwidthData> for v3::registration::RemainingBandwidthData {
|
||||
fn from(value: v4::registration::RemainingBandwidthData) -> Self {
|
||||
Self {
|
||||
available_bandwidth: value.available_bandwidth,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod conversion;
|
||||
pub mod registration;
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
pub mod topup;
|
||||
|
||||
pub const VERSION: u8 = 4;
|
||||
@@ -0,0 +1,258 @@
|
||||
// -2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::Error;
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use nym_credentials_interface::CredentialSpendingData;
|
||||
use nym_network_defaults::constants::{WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6};
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use std::time::SystemTime;
|
||||
use std::{fmt, ops::Deref, str::FromStr};
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
use hmac::{Hmac, Mac};
|
||||
#[cfg(feature = "verify")]
|
||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||
#[cfg(feature = "verify")]
|
||||
use sha2::Sha256;
|
||||
|
||||
pub type PendingRegistrations = HashMap<PeerPublicKey, RegistrationData>;
|
||||
pub type PrivateIPs = HashMap<IpPair, Taken>;
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
pub type HmacSha256 = Hmac<Sha256>;
|
||||
|
||||
pub type Nonce = u64;
|
||||
pub type Taken = Option<SystemTime>;
|
||||
|
||||
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct IpPair {
|
||||
pub ipv4: Ipv4Addr,
|
||||
pub ipv6: Ipv6Addr,
|
||||
}
|
||||
|
||||
impl IpPair {
|
||||
pub fn new(ipv4: Ipv4Addr, ipv6: Ipv6Addr) -> Self {
|
||||
IpPair { ipv4, ipv6 }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for IpPair {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "({}, {})", self.ipv4, self.ipv6)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IpAddr> for IpPair {
|
||||
fn from(value: IpAddr) -> Self {
|
||||
let transformed_ipv4 = WG_TUN_DEVICE_IP_ADDRESS_V4;
|
||||
let transformed_ipv6 = WG_TUN_DEVICE_IP_ADDRESS_V6;
|
||||
let (ipv4, ipv6) = match value {
|
||||
std::net::IpAddr::V4(ipv4_addr) => (ipv4_addr, transformed_ipv6),
|
||||
std::net::IpAddr::V6(ipv6_addr) => (transformed_ipv4, ipv6_addr),
|
||||
};
|
||||
IpPair::new(ipv4, ipv6)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct InitMessage {
|
||||
/// Base64 encoded x25519 public key
|
||||
pub pub_key: PeerPublicKey,
|
||||
}
|
||||
|
||||
impl InitMessage {
|
||||
pub fn new(pub_key: PeerPublicKey) -> Self {
|
||||
InitMessage { pub_key }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct FinalMessage {
|
||||
/// Gateway client data
|
||||
pub gateway_client: GatewayClient,
|
||||
|
||||
/// Ecash credential
|
||||
pub credential: Option<CredentialSpendingData>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct RegistrationData {
|
||||
pub nonce: u64,
|
||||
pub gateway_data: GatewayClient,
|
||||
pub wg_port: u16,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct RegistredData {
|
||||
pub pub_key: PeerPublicKey,
|
||||
pub private_ips: IpPair,
|
||||
pub wg_port: u16,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct RemainingBandwidthData {
|
||||
pub available_bandwidth: i64,
|
||||
}
|
||||
|
||||
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
|
||||
/// Gateway/Nym node can then verify pub_key payload using the same process
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct GatewayClient {
|
||||
/// Base64 encoded x25519 public key
|
||||
pub pub_key: PeerPublicKey,
|
||||
|
||||
/// Assigned private IPs (v4 and v6)
|
||||
pub private_ips: IpPair,
|
||||
|
||||
/// Sha256 hmac on the data (alongside the prior nonce)
|
||||
pub mac: ClientMac,
|
||||
}
|
||||
|
||||
impl GatewayClient {
|
||||
#[cfg(feature = "verify")]
|
||||
pub fn new(
|
||||
local_secret: &PrivateKey,
|
||||
remote_public: x25519_dalek::PublicKey,
|
||||
private_ips: IpPair,
|
||||
nonce: u64,
|
||||
) -> Self {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
||||
|
||||
let dh = static_secret.diffie_hellman(&remote_public);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
||||
.expect("x25519 shared secret is always 32 bytes long");
|
||||
|
||||
mac.update(local_public.as_bytes());
|
||||
mac.update(private_ips.to_string().as_bytes());
|
||||
mac.update(&nonce.to_le_bytes());
|
||||
|
||||
GatewayClient {
|
||||
pub_key: PeerPublicKey::new(local_public),
|
||||
private_ips,
|
||||
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
|
||||
}
|
||||
}
|
||||
|
||||
// Reusable secret should be gateways Wireguard PK
|
||||
// Client should perform this step when generating its payload, using its own WG PK
|
||||
#[cfg(feature = "verify")]
|
||||
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
|
||||
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
|
||||
#[allow(clippy::expect_used)]
|
||||
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
|
||||
|
||||
let dh = static_secret.diffie_hellman(&self.pub_key);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
#[allow(clippy::expect_used)]
|
||||
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
|
||||
.expect("x25519 shared secret is always 32 bytes long");
|
||||
|
||||
mac.update(self.pub_key.as_bytes());
|
||||
mac.update(self.private_ips.to_string().as_bytes());
|
||||
mac.update(&nonce.to_le_bytes());
|
||||
|
||||
mac.verify_slice(&self.mac)
|
||||
.map_err(|source| Error::FailedClientMacVerification {
|
||||
client: self.pub_key.to_string(),
|
||||
source,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pub_key(&self) -> PeerPublicKey {
|
||||
self.pub_key
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
|
||||
// TODO2: rely on our internal crypto/hmac
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClientMac(Vec<u8>);
|
||||
|
||||
impl fmt::Display for ClientMac {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", general_purpose::STANDARD.encode(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientMac {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(mac: Vec<u8>) -> Self {
|
||||
ClientMac(mac)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ClientMac {
|
||||
type Target = Vec<u8>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for ClientMac {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mac_bytes: Vec<u8> =
|
||||
general_purpose::STANDARD
|
||||
.decode(s)
|
||||
.map_err(|source| Error::MalformedClientMac {
|
||||
mac: s.to_string(),
|
||||
source,
|
||||
})?;
|
||||
|
||||
Ok(ClientMac(mac_bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ClientMac {
|
||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let encoded_key = general_purpose::STANDARD.encode(self.0.clone());
|
||||
serializer.serialize_str(&encoded_key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ClientMac {
|
||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
let encoded_key = String::deserialize(deserializer)?;
|
||||
ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use nym_crypto::asymmetric::encryption;
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "verify")]
|
||||
fn client_request_roundtrip() {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
|
||||
let client_key_pair = encryption::KeyPair::new(&mut rng);
|
||||
|
||||
let nonce = 1234567890;
|
||||
|
||||
let client = GatewayClient::new(
|
||||
client_key_pair.private_key(),
|
||||
x25519_dalek::PublicKey::from(gateway_key_pair.public_key().to_bytes()),
|
||||
IpPair::new("10.0.0.42".parse().unwrap(), "fc00::42".parse().unwrap()),
|
||||
nonce,
|
||||
);
|
||||
assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::{
|
||||
registration::{FinalMessage, InitMessage},
|
||||
topup::TopUpMessage,
|
||||
};
|
||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
fn generate_random() -> u64 {
|
||||
use rand::RngCore;
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
rng.next_u64()
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorRequest {
|
||||
pub protocol: Protocol,
|
||||
pub data: AuthenticatorRequestData,
|
||||
pub reply_to: Recipient,
|
||||
pub request_id: u64,
|
||||
}
|
||||
|
||||
impl AuthenticatorRequest {
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
version: VERSION,
|
||||
},
|
||||
data: AuthenticatorRequestData::Initial(init_message),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_final_request(final_message: FinalMessage, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
version: VERSION,
|
||||
},
|
||||
data: AuthenticatorRequestData::Final(Box::new(final_message)),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
version: VERSION,
|
||||
},
|
||||
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_topup_request(top_up_message: TopUpMessage, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
version: VERSION,
|
||||
},
|
||||
data: AuthenticatorRequestData::TopUpBandwidth(Box::new(top_up_message)),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorRequestData {
|
||||
Initial(InitMessage),
|
||||
Final(Box<FinalMessage>),
|
||||
QueryBandwidth(PeerPublicKey),
|
||||
TopUpBandwidth(Box<TopUpMessage>),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn check_first_bytes_protocol() {
|
||||
let version = 4;
|
||||
let data = AuthenticatorRequest {
|
||||
protocol: Protocol { version, service_provider_type: ServiceProviderType::Authenticator },
|
||||
data: AuthenticatorRequestData::Initial(InitMessage::new(
|
||||
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
|
||||
)),
|
||||
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
|
||||
request_id: 1,
|
||||
};
|
||||
let bytes = *data.to_bytes().unwrap().first_chunk::<2>().unwrap();
|
||||
assert_eq!(bytes, [version, ServiceProviderType::Authenticator as u8]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
|
||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorResponse {
|
||||
pub protocol: Protocol,
|
||||
pub data: AuthenticatorResponseData,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
|
||||
impl AuthenticatorResponse {
|
||||
pub fn new_pending_registration_success(
|
||||
registration_data: RegistrationData,
|
||||
request_id: u64,
|
||||
reply_to: Recipient,
|
||||
) -> Self {
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
version: VERSION,
|
||||
},
|
||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
||||
reply: registration_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_registered(
|
||||
registred_data: RegistredData,
|
||||
reply_to: Recipient,
|
||||
request_id: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
version: VERSION,
|
||||
},
|
||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
||||
reply: registred_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_remaining_bandwidth(
|
||||
remaining_bandwidth_data: Option<RemainingBandwidthData>,
|
||||
reply_to: Recipient,
|
||||
request_id: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
version: VERSION,
|
||||
},
|
||||
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
|
||||
reply: remaining_bandwidth_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_topup_bandwidth(
|
||||
remaining_bandwidth_data: RemainingBandwidthData,
|
||||
reply_to: Recipient,
|
||||
request_id: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
protocol: Protocol {
|
||||
service_provider_type: ServiceProviderType::Authenticator,
|
||||
version: VERSION,
|
||||
},
|
||||
data: AuthenticatorResponseData::TopUpBandwidth(TopUpBandwidthResponse {
|
||||
reply: remaining_bandwidth_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recipient(&self) -> Recipient {
|
||||
self.reply_to
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<u64> {
|
||||
match &self.data {
|
||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::TopUpBandwidth(response) => Some(response.request_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorResponseData {
|
||||
PendingRegistration(PendingRegistrationResponse),
|
||||
Registered(RegisteredResponse),
|
||||
RemainingBandwidth(RemainingBandwidthResponse),
|
||||
TopUpBandwidth(TopUpBandwidthResponse),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PendingRegistrationResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RegistrationData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RegisteredResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RegistredData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RemainingBandwidthResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: Option<RemainingBandwidthData>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct TopUpBandwidthResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RemainingBandwidthData,
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_credentials_interface::CredentialSpendingData;
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct TopUpMessage {
|
||||
/// Base64 encoded x25519 public key
|
||||
pub pub_key: PeerPublicKey,
|
||||
|
||||
/// Ecash credential
|
||||
pub credential: CredentialSpendingData,
|
||||
}
|
||||
@@ -248,7 +248,7 @@ mod tests {
|
||||
data: IpPacketRequestData::StaticConnect(
|
||||
StaticConnectRequest {
|
||||
request_id: 123,
|
||||
ips: IpPair::new(Ipv4Addr::from_str("10.0.0.1").unwrap(), Ipv6Addr::from_str("2001:db8:a160::1").unwrap()),
|
||||
ips: IpPair::new(Ipv4Addr::from_str("10.0.0.1").unwrap(), Ipv6Addr::from_str("fc00::1").unwrap()),
|
||||
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
|
||||
reply_to_hops: None,
|
||||
reply_to_avg_mix_delays: None,
|
||||
|
||||
@@ -429,7 +429,7 @@ mod tests {
|
||||
SignedStaticConnectRequest {
|
||||
request: StaticConnectRequest {
|
||||
request_id: 123,
|
||||
ips: IpPair::new(Ipv4Addr::from_str("10.0.0.1").unwrap(), Ipv6Addr::from_str("2001:db8:a160::1").unwrap()),
|
||||
ips: IpPair::new(Ipv4Addr::from_str("10.0.0.1").unwrap(), Ipv6Addr::from_str("fc00::1").unwrap()),
|
||||
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
|
||||
reply_to_hops: None,
|
||||
reply_to_avg_mix_delays: None,
|
||||
|
||||
@@ -45,13 +45,15 @@ pub mod nyx {
|
||||
}
|
||||
|
||||
pub mod wireguard {
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
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";
|
||||
pub const WG_TUN_DEVICE_IP_ADDRESS_V4: Ipv4Addr = Ipv4Addr::new(10, 1, 0, 1);
|
||||
pub const WG_TUN_DEVICE_NETMASK_V4: u8 = 16;
|
||||
pub const WG_TUN_DEVICE_IP_ADDRESS_V6: Ipv6Addr = Ipv6Addr::new(0xfc01, 0, 0, 0, 0, 0, 0, 0x1); // fc01::1
|
||||
pub const WG_TUN_DEVICE_NETMASK_V6: u8 = 112;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
pub struct Config {
|
||||
@@ -9,15 +9,23 @@ pub struct Config {
|
||||
/// default: `0.0.0.0:51822`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Private IP address of the wireguard gateway.
|
||||
/// Private IPv4 address of the wireguard gateway.
|
||||
/// default: `10.1.0.1`
|
||||
pub private_ip: IpAddr,
|
||||
pub private_ipv4: Ipv4Addr,
|
||||
|
||||
/// Private IPv6 address of the wireguard gateway.
|
||||
/// default: `fc01::1`
|
||||
pub private_ipv6: Ipv6Addr,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
pub announced_port: u16,
|
||||
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard.
|
||||
/// The maximum value for IPv4 is 32 and for IPv6 is 128
|
||||
pub private_network_prefix: u8,
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard using IPv4.
|
||||
/// The maximum value for IPv4 is 32
|
||||
pub private_network_prefix_v4: u8,
|
||||
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard using IPv6.
|
||||
/// The maximum value for IPv6 is 128
|
||||
pub private_network_prefix_v6: u8,
|
||||
}
|
||||
|
||||
+29
-11
@@ -10,13 +10,13 @@ use defguard_wireguard_rs::WGApi;
|
||||
#[cfg(target_os = "linux")]
|
||||
use defguard_wireguard_rs::{host::Peer, key::Key, net::IpAddrMask};
|
||||
use nym_crypto::asymmetric::encryption::KeyPair;
|
||||
#[cfg(target_os = "linux")]
|
||||
use nym_network_defaults::constants::WG_TUN_BASE_NAME;
|
||||
use nym_wireguard_types::Config;
|
||||
use peer_controller::PeerControlRequest;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc::{self, Receiver, Sender};
|
||||
|
||||
const WG_TUN_NAME: &str = "nymwg";
|
||||
|
||||
pub(crate) mod error;
|
||||
pub mod peer_controller;
|
||||
pub mod peer_handle;
|
||||
@@ -93,7 +93,7 @@ pub async fn start_wireguard<St: nym_gateway_storage::Storage + Clone + 'static>
|
||||
use std::collections::HashMap;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
let ifname = String::from(WG_TUN_NAME);
|
||||
let ifname = String::from(WG_TUN_BASE_NAME);
|
||||
let wg_api = defguard_wireguard_rs::WGApi::new(ifname.clone(), false)?;
|
||||
let mut peer_bandwidth_managers = HashMap::with_capacity(all_peers.len());
|
||||
let peers = all_peers
|
||||
@@ -124,23 +124,41 @@ pub async fn start_wireguard<St: nym_gateway_storage::Storage + Clone + 'static>
|
||||
let interface_config = InterfaceConfiguration {
|
||||
name: ifname.clone(),
|
||||
prvkey: BASE64_STANDARD.encode(wireguard_data.inner.keypair().private_key().to_bytes()),
|
||||
address: wireguard_data.inner.config().private_ip.to_string(),
|
||||
address: wireguard_data.inner.config().private_ipv4.to_string(),
|
||||
port: wireguard_data.inner.config().announced_port as u32,
|
||||
peers,
|
||||
mtu: None,
|
||||
};
|
||||
wg_api.configure_interface(&interface_config)?;
|
||||
std::process::Command::new("ip")
|
||||
.args([
|
||||
"-6",
|
||||
"addr",
|
||||
"add",
|
||||
&format!(
|
||||
"{}/{}",
|
||||
wireguard_data.inner.config().private_ipv6,
|
||||
wireguard_data.inner.config().private_network_prefix_v6
|
||||
),
|
||||
"dev",
|
||||
(&ifname),
|
||||
])
|
||||
.output()?;
|
||||
|
||||
// Use a dummy peer to create routing rule for the entire network space
|
||||
let mut catch_all_peer = Peer::new(Key::new([0; 32]));
|
||||
let network = IpNetwork::new_truncate(
|
||||
wireguard_data.inner.config().private_ip,
|
||||
wireguard_data.inner.config().private_network_prefix,
|
||||
let network_v4 = IpNetwork::new_truncate(
|
||||
wireguard_data.inner.config().private_ipv4,
|
||||
wireguard_data.inner.config().private_network_prefix_v4,
|
||||
)?;
|
||||
catch_all_peer.set_allowed_ips(vec![IpAddrMask::new(
|
||||
network.network_address(),
|
||||
network.netmask(),
|
||||
)]);
|
||||
let network_v6 = IpNetwork::new_truncate(
|
||||
wireguard_data.inner.config().private_ipv6,
|
||||
wireguard_data.inner.config().private_network_prefix_v6,
|
||||
)?;
|
||||
catch_all_peer.set_allowed_ips(vec![
|
||||
IpAddrMask::new(network_v4.network_address(), network_v4.netmask()),
|
||||
IpAddrMask::new(network_v6.network_address(), network_v6.netmask()),
|
||||
]);
|
||||
wg_api.configure_peer_routing(&[catch_all_peer])?;
|
||||
|
||||
let host = wg_api.read_interface_data()?;
|
||||
|
||||
@@ -389,7 +389,7 @@ ip addr show nymtun0
|
||||
link/none
|
||||
inet 10.0.0.1/16 scope global nymtun0
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:a160::1/112 scope global
|
||||
inet6 fc00::1/112 scope global
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 fe80::ad08:d167:5700:8c7c/64 scope link stable-privacy
|
||||
valid_lft forever preferred_lft forever`
|
||||
|
||||
@@ -265,14 +265,6 @@ pub(crate) struct WireguardArgs {
|
||||
)]
|
||||
pub(crate) wireguard_bind_address: Option<SocketAddr>,
|
||||
|
||||
/// Private IP address of the wireguard gateway.
|
||||
/// default: `10.1.0.1`
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_WG_IP_ARG,
|
||||
)]
|
||||
pub(crate) wireguard_private_ip: Option<IpAddr>,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
#[clap(
|
||||
@@ -312,12 +304,8 @@ impl WireguardArgs {
|
||||
section.announced_port = announced_port
|
||||
}
|
||||
|
||||
if let Some(private_ip) = self.wireguard_private_ip {
|
||||
section.private_ip = private_ip
|
||||
}
|
||||
|
||||
if let Some(private_network_prefix) = self.wireguard_private_network_prefix {
|
||||
section.private_network_prefix = private_network_prefix
|
||||
section.private_network_prefix_v4 = private_network_prefix
|
||||
}
|
||||
|
||||
section
|
||||
|
||||
@@ -181,9 +181,11 @@ pub fn ephemeral_entry_gateway_config(
|
||||
config: super::Wireguard {
|
||||
enabled: config.wireguard.enabled,
|
||||
bind_address: config.wireguard.bind_address,
|
||||
private_ip: config.wireguard.private_ip,
|
||||
private_ipv4: config.wireguard.private_ipv4,
|
||||
private_ipv6: config.wireguard.private_ipv6,
|
||||
announced_port: config.wireguard.announced_port,
|
||||
private_network_prefix: config.wireguard.private_network_prefix,
|
||||
private_network_prefix_v4: config.wireguard.private_network_prefix_v4,
|
||||
private_network_prefix_v6: config.wireguard.private_network_prefix_v6,
|
||||
storage_paths: config.wireguard.storage_paths.clone(),
|
||||
},
|
||||
custom_mixnet_path: None,
|
||||
|
||||
@@ -278,9 +278,11 @@ pub fn ephemeral_exit_gateway_config(
|
||||
config: super::Wireguard {
|
||||
enabled: config.wireguard.enabled,
|
||||
bind_address: config.wireguard.bind_address,
|
||||
private_ip: config.wireguard.private_ip,
|
||||
private_ipv4: config.wireguard.private_ipv4,
|
||||
private_ipv6: config.wireguard.private_ipv6,
|
||||
announced_port: config.wireguard.announced_port,
|
||||
private_network_prefix: config.wireguard.private_network_prefix,
|
||||
private_network_prefix_v4: config.wireguard.private_network_prefix_v4,
|
||||
private_network_prefix_v6: config.wireguard.private_network_prefix_v6,
|
||||
storage_paths: config.wireguard.storage_paths.clone(),
|
||||
},
|
||||
custom_mixnet_path: None,
|
||||
|
||||
+30
-20
@@ -10,7 +10,9 @@ use clap::ValueEnum;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_config::defaults::{
|
||||
mainnet, var_names, DEFAULT_MIX_LISTENING_PORT, DEFAULT_NYM_NODE_HTTP_PORT, WG_PORT,
|
||||
WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6,
|
||||
};
|
||||
use nym_config::defaults::{WG_TUN_DEVICE_NETMASK_V4, WG_TUN_DEVICE_NETMASK_V6};
|
||||
use nym_config::helpers::inaddr_any;
|
||||
use nym_config::serde_helpers::de_maybe_port;
|
||||
use nym_config::serde_helpers::de_maybe_stringified;
|
||||
@@ -21,7 +23,7 @@ use nym_config::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::env;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use tracing::{debug, error};
|
||||
@@ -43,9 +45,6 @@ pub use crate::config::mixnode::MixnodeConfig;
|
||||
|
||||
const DEFAULT_NYMNODES_DIR: &str = "nym-nodes";
|
||||
|
||||
pub const DEFAULT_WIREGUARD_PORT: u16 = WG_PORT;
|
||||
pub const DEFAULT_WIREGUARD_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(10, 1, 0, 1));
|
||||
pub const DEFAULT_WIREGUARD_PREFIX: u8 = 16;
|
||||
pub const DEFAULT_HTTP_PORT: u16 = DEFAULT_NYM_NODE_HTTP_PORT;
|
||||
pub const DEFAULT_MIXNET_PORT: u16 = DEFAULT_MIX_LISTENING_PORT;
|
||||
|
||||
@@ -518,17 +517,25 @@ pub struct Wireguard {
|
||||
/// default: `0.0.0.0:51822`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Private IP address of the wireguard gateway.
|
||||
/// Private IPv4 address of the wireguard gateway.
|
||||
/// default: `10.1.0.1`
|
||||
pub private_ip: IpAddr,
|
||||
pub private_ipv4: Ipv4Addr,
|
||||
|
||||
/// Private IPv6 address of the wireguard gateway.
|
||||
/// default: `fc01::1`
|
||||
pub private_ipv6: Ipv6Addr,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
pub announced_port: u16,
|
||||
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard.
|
||||
/// The maximum value for IPv4 is 32 and for IPv6 is 128
|
||||
pub private_network_prefix: u8,
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard using IPv4.
|
||||
/// The maximum value for IPv4 is 32
|
||||
pub private_network_prefix_v4: u8,
|
||||
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard using IPv6.
|
||||
/// The maximum value for IPv6 is 128
|
||||
pub private_network_prefix_v6: u8,
|
||||
|
||||
/// Paths for wireguard keys, client registries, etc.
|
||||
pub storage_paths: persistence::WireguardPaths,
|
||||
@@ -538,13 +545,12 @@ impl Wireguard {
|
||||
pub fn new_default<P: AsRef<Path>>(data_dir: P) -> Self {
|
||||
Wireguard {
|
||||
enabled: false,
|
||||
bind_address: SocketAddr::new(
|
||||
IpAddr::V4(Ipv4Addr::UNSPECIFIED),
|
||||
DEFAULT_WIREGUARD_PORT,
|
||||
),
|
||||
private_ip: DEFAULT_WIREGUARD_IP,
|
||||
announced_port: DEFAULT_WIREGUARD_PORT,
|
||||
private_network_prefix: DEFAULT_WIREGUARD_PREFIX,
|
||||
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), WG_PORT),
|
||||
private_ipv4: WG_TUN_DEVICE_IP_ADDRESS_V4,
|
||||
private_ipv6: WG_TUN_DEVICE_IP_ADDRESS_V6,
|
||||
announced_port: WG_PORT,
|
||||
private_network_prefix_v4: WG_TUN_DEVICE_NETMASK_V4,
|
||||
private_network_prefix_v6: WG_TUN_DEVICE_NETMASK_V6,
|
||||
storage_paths: persistence::WireguardPaths::new(data_dir),
|
||||
}
|
||||
}
|
||||
@@ -554,9 +560,11 @@ impl From<Wireguard> for nym_wireguard_types::Config {
|
||||
fn from(value: Wireguard) -> Self {
|
||||
nym_wireguard_types::Config {
|
||||
bind_address: value.bind_address,
|
||||
private_ip: value.private_ip,
|
||||
private_ipv4: value.private_ipv4,
|
||||
private_ipv6: value.private_ipv6,
|
||||
announced_port: value.announced_port,
|
||||
private_network_prefix: value.private_network_prefix,
|
||||
private_network_prefix_v4: value.private_network_prefix_v4,
|
||||
private_network_prefix_v6: value.private_network_prefix_v6,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -565,9 +573,11 @@ impl From<Wireguard> for nym_authenticator::config::Authenticator {
|
||||
fn from(value: Wireguard) -> Self {
|
||||
nym_authenticator::config::Authenticator {
|
||||
bind_address: value.bind_address,
|
||||
private_ip: value.private_ip,
|
||||
private_ipv4: value.private_ipv4,
|
||||
private_ipv6: value.private_ipv6,
|
||||
announced_port: value.announced_port,
|
||||
private_network_prefix: value.private_network_prefix,
|
||||
private_network_prefix_v4: value.private_network_prefix_v4,
|
||||
private_network_prefix_v6: value.private_network_prefix_v6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ mod old_config_v1;
|
||||
mod old_config_v2;
|
||||
mod old_config_v3;
|
||||
mod old_config_v4;
|
||||
mod old_config_v5;
|
||||
|
||||
pub use old_config_v1::try_upgrade_config_v1;
|
||||
pub use old_config_v2::try_upgrade_config_v2;
|
||||
pub use old_config_v3::try_upgrade_config_v3;
|
||||
pub use old_config_v4::try_upgrade_config_v4;
|
||||
pub use old_config_v5::try_upgrade_config_v5;
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::{config::*, error::KeyIOFailure};
|
||||
use entry_gateway::{Debug as EntryGatewayConfigDebug, ZkNymTicketHandlerDebug};
|
||||
use exit_gateway::{
|
||||
Debug as ExitGatewayConfigDebug, IpPacketRouter, IpPacketRouterDebug, NetworkRequester,
|
||||
NetworkRequesterDebug,
|
||||
};
|
||||
use mixnode::{Verloc, VerlocDebug};
|
||||
use nym_client_core_config_types::{
|
||||
disk_persistence::{ClientKeysPaths, CommonClientPaths},
|
||||
DebugConfig as ClientDebugConfig,
|
||||
@@ -22,6 +16,7 @@ use nym_network_requester::{
|
||||
};
|
||||
use nym_pemstore::{store_key, store_keypair};
|
||||
use nym_sphinx_acknowledgements::AckKey;
|
||||
use old_configs::old_config_v5::*;
|
||||
use persistence::*;
|
||||
use rand::rngs::OsRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -93,12 +88,12 @@ pub enum NodeModeV4 {
|
||||
ExitGateway,
|
||||
}
|
||||
|
||||
impl From<NodeModeV4> for NodeMode {
|
||||
impl From<NodeModeV4> for NodeModeV5 {
|
||||
fn from(config: NodeModeV4) -> Self {
|
||||
match config {
|
||||
NodeModeV4::Mixnode => NodeMode::Mixnode,
|
||||
NodeModeV4::EntryGateway => NodeMode::EntryGateway,
|
||||
NodeModeV4::ExitGateway => NodeMode::ExitGateway,
|
||||
NodeModeV4::Mixnode => NodeModeV5::Mixnode,
|
||||
NodeModeV4::EntryGateway => NodeModeV5::EntryGateway,
|
||||
NodeModeV4::ExitGateway => NodeModeV5::ExitGateway,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1068,7 +1063,7 @@ pub async fn initialise(
|
||||
pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
path: P,
|
||||
prev_config: Option<ConfigV4>,
|
||||
) -> Result<Config, NymNodeError> {
|
||||
) -> Result<ConfigV5, NymNodeError> {
|
||||
tracing::debug!("Updating from 1.1.5");
|
||||
let old_cfg = if let Some(prev_config) = prev_config {
|
||||
prev_config
|
||||
@@ -1094,21 +1089,21 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
.ok_or(NymNodeError::DataDirDerivationFailure)?,
|
||||
);
|
||||
|
||||
let cfg = Config {
|
||||
let cfg = ConfigV5 {
|
||||
save_path: old_cfg.save_path,
|
||||
id: old_cfg.id,
|
||||
mode: old_cfg.mode.into(),
|
||||
host: Host {
|
||||
host: HostV5 {
|
||||
public_ips: old_cfg.host.public_ips,
|
||||
hostname: old_cfg.host.hostname,
|
||||
location: old_cfg.host.location,
|
||||
},
|
||||
mixnet: Mixnet {
|
||||
mixnet: MixnetV5 {
|
||||
bind_address: old_cfg.mixnet.bind_address,
|
||||
announce_port: old_cfg.mixnet.announce_port,
|
||||
nym_api_urls: old_cfg.mixnet.nym_api_urls,
|
||||
nyxd_urls: old_cfg.mixnet.nyxd_urls,
|
||||
debug: MixnetDebug {
|
||||
debug: MixnetDebugV5 {
|
||||
packet_forwarding_initial_backoff: old_cfg
|
||||
.mixnet
|
||||
.debug
|
||||
@@ -1122,8 +1117,8 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
unsafe_disable_noise: old_cfg.mixnet.debug.unsafe_disable_noise,
|
||||
},
|
||||
},
|
||||
storage_paths: NymNodePaths {
|
||||
keys: KeysPaths {
|
||||
storage_paths: NymNodePathsV5 {
|
||||
keys: KeysPathsV5 {
|
||||
private_ed25519_identity_key_file: old_cfg
|
||||
.storage_paths
|
||||
.keys
|
||||
@@ -1151,7 +1146,7 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
},
|
||||
description: old_cfg.storage_paths.description,
|
||||
},
|
||||
http: Http {
|
||||
http: HttpV5 {
|
||||
bind_address: old_cfg.http.bind_address,
|
||||
landing_page_assets_path: old_cfg.http.landing_page_assets_path,
|
||||
access_token: old_cfg.http.access_token,
|
||||
@@ -1159,13 +1154,13 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
expose_system_hardware: old_cfg.http.expose_system_hardware,
|
||||
expose_crypto_hardware: old_cfg.http.expose_crypto_hardware,
|
||||
},
|
||||
wireguard: Wireguard {
|
||||
wireguard: WireguardV5 {
|
||||
enabled: old_cfg.wireguard.enabled,
|
||||
bind_address: old_cfg.wireguard.bind_address,
|
||||
private_ip: old_cfg.wireguard.private_ip,
|
||||
announced_port: old_cfg.wireguard.announced_port,
|
||||
private_network_prefix: old_cfg.wireguard.private_network_prefix,
|
||||
storage_paths: WireguardPaths {
|
||||
storage_paths: WireguardPathsV5 {
|
||||
private_diffie_hellman_key_file: old_cfg
|
||||
.wireguard
|
||||
.storage_paths
|
||||
@@ -1176,12 +1171,12 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
.public_diffie_hellman_key_file,
|
||||
},
|
||||
},
|
||||
mixnode: MixnodeConfig {
|
||||
storage_paths: MixnodePaths {},
|
||||
verloc: Verloc {
|
||||
mixnode: MixnodeConfigV5 {
|
||||
storage_paths: MixnodePathsV5 {},
|
||||
verloc: VerlocV5 {
|
||||
bind_address: old_cfg.mixnode.verloc.bind_address,
|
||||
announce_port: old_cfg.mixnode.verloc.announce_port,
|
||||
debug: VerlocDebug {
|
||||
debug: VerlocDebugV5 {
|
||||
packets_per_node: old_cfg.mixnode.verloc.debug.packets_per_node,
|
||||
connection_timeout: old_cfg.mixnode.verloc.debug.connection_timeout,
|
||||
packet_timeout: old_cfg.mixnode.verloc.debug.packet_timeout,
|
||||
@@ -1191,17 +1186,17 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
retry_timeout: old_cfg.mixnode.verloc.debug.retry_timeout,
|
||||
},
|
||||
},
|
||||
debug: mixnode::Debug {
|
||||
debug: DebugV5 {
|
||||
node_stats_logging_delay: old_cfg.mixnode.debug.node_stats_logging_delay,
|
||||
node_stats_updating_delay: old_cfg.mixnode.debug.node_stats_updating_delay,
|
||||
},
|
||||
},
|
||||
entry_gateway: EntryGatewayConfig {
|
||||
storage_paths: EntryGatewayPaths {
|
||||
entry_gateway: EntryGatewayConfigV5 {
|
||||
storage_paths: EntryGatewayPathsV5 {
|
||||
clients_storage: old_cfg.entry_gateway.storage_paths.clients_storage,
|
||||
stats_storage: entry_gateway_paths.stats_storage,
|
||||
cosmos_mnemonic: old_cfg.entry_gateway.storage_paths.cosmos_mnemonic,
|
||||
authenticator: AuthenticatorPaths {
|
||||
authenticator: AuthenticatorPathsV5 {
|
||||
private_ed25519_identity_key_file: old_cfg
|
||||
.entry_gateway
|
||||
.storage_paths
|
||||
@@ -1243,9 +1238,9 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
bind_address: old_cfg.entry_gateway.bind_address,
|
||||
announce_ws_port: old_cfg.entry_gateway.announce_ws_port,
|
||||
announce_wss_port: old_cfg.entry_gateway.announce_wss_port,
|
||||
debug: EntryGatewayConfigDebug {
|
||||
debug: EntryGatewayConfigDebugV5 {
|
||||
message_retrieval_limit: old_cfg.entry_gateway.debug.message_retrieval_limit,
|
||||
zk_nym_tickets: ZkNymTicketHandlerDebug {
|
||||
zk_nym_tickets: ZkNymTicketHandlerDebugV5 {
|
||||
revocation_bandwidth_penalty: old_cfg
|
||||
.entry_gateway
|
||||
.debug
|
||||
@@ -1270,11 +1265,11 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
},
|
||||
},
|
||||
},
|
||||
exit_gateway: ExitGatewayConfig {
|
||||
storage_paths: ExitGatewayPaths {
|
||||
exit_gateway: ExitGatewayConfigV5 {
|
||||
storage_paths: ExitGatewayPathsV5 {
|
||||
clients_storage: old_cfg.exit_gateway.storage_paths.clients_storage,
|
||||
stats_storage: exit_gateway_paths.stats_storage,
|
||||
network_requester: NetworkRequesterPaths {
|
||||
network_requester: NetworkRequesterPathsV5 {
|
||||
private_ed25519_identity_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
@@ -1311,7 +1306,7 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
.network_requester
|
||||
.gateway_registrations,
|
||||
},
|
||||
ip_packet_router: IpPacketRouterPaths {
|
||||
ip_packet_router: IpPacketRouterPathsV5 {
|
||||
private_ed25519_identity_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
@@ -1348,7 +1343,7 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
.ip_packet_router
|
||||
.gateway_registrations,
|
||||
},
|
||||
authenticator: AuthenticatorPaths {
|
||||
authenticator: AuthenticatorPathsV5 {
|
||||
private_ed25519_identity_key_file: old_cfg
|
||||
.exit_gateway
|
||||
.storage_paths
|
||||
@@ -1388,8 +1383,8 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
},
|
||||
open_proxy: old_cfg.exit_gateway.open_proxy,
|
||||
upstream_exit_policy_url: old_cfg.exit_gateway.upstream_exit_policy_url,
|
||||
network_requester: NetworkRequester {
|
||||
debug: NetworkRequesterDebug {
|
||||
network_requester: NetworkRequesterV5 {
|
||||
debug: NetworkRequesterDebugV5 {
|
||||
enabled: old_cfg.exit_gateway.network_requester.debug.enabled,
|
||||
disable_poisson_rate: old_cfg
|
||||
.exit_gateway
|
||||
@@ -1399,8 +1394,8 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
client_debug: old_cfg.exit_gateway.network_requester.debug.client_debug,
|
||||
},
|
||||
},
|
||||
ip_packet_router: IpPacketRouter {
|
||||
debug: IpPacketRouterDebug {
|
||||
ip_packet_router: IpPacketRouterV5 {
|
||||
debug: IpPacketRouterDebugV5 {
|
||||
enabled: old_cfg.exit_gateway.ip_packet_router.debug.enabled,
|
||||
disable_poisson_rate: old_cfg
|
||||
.exit_gateway
|
||||
@@ -1410,12 +1405,18 @@ pub async fn try_upgrade_config_v4<P: AsRef<Path>>(
|
||||
client_debug: old_cfg.exit_gateway.ip_packet_router.debug.client_debug,
|
||||
},
|
||||
},
|
||||
debug: ExitGatewayConfigDebug {
|
||||
debug: ExitGatewayDebugV5 {
|
||||
message_retrieval_limit: old_cfg.exit_gateway.debug.message_retrieval_limit,
|
||||
},
|
||||
},
|
||||
authenticator: Default::default(),
|
||||
logging: LoggingSettings {},
|
||||
authenticator: AuthenticatorV5 {
|
||||
debug: AuthenticatorDebugV5 {
|
||||
enabled: old_cfg.authenticator.debug.enabled,
|
||||
disable_poisson_rate: old_cfg.authenticator.debug.disable_poisson_rate,
|
||||
client_debug: old_cfg.authenticator.debug.client_debug,
|
||||
},
|
||||
},
|
||||
logging: LoggingSettingsV5 {},
|
||||
};
|
||||
|
||||
Ok(cfg)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -123,15 +123,23 @@ bind_address = '{{ wireguard.bind_address }}'
|
||||
|
||||
# Private IP address of the wireguard gateway.
|
||||
# default: `10.1.0.1`
|
||||
private_ip = '{{ wireguard.private_ip }}'
|
||||
private_ipv4 = '{{ wireguard.private_ipv4 }}'
|
||||
|
||||
# Private IP address of the wireguard gateway.
|
||||
# default: `fc01::1`
|
||||
private_ipv6 = '{{ wireguard.private_ipv6 }}'
|
||||
|
||||
# Port announced to external clients wishing to connect to the wireguard interface.
|
||||
# Useful in the instances where the node is behind a proxy.
|
||||
announced_port = {{ wireguard.announced_port }}
|
||||
|
||||
# The prefix denoting the maximum number of the clients that can be connected via Wireguard.
|
||||
# The maximum value for IPv4 is 32 and for IPv6 is 128
|
||||
private_network_prefix = {{ wireguard.private_network_prefix }}
|
||||
# The prefix denoting the maximum number of the clients that can be connected via Wireguard using IPv4.
|
||||
# The maximum value for IPv4 is 32
|
||||
private_network_prefix_v4 = {{ wireguard.private_network_prefix_v4 }}
|
||||
|
||||
# The prefix denoting the maximum number of the clients that can be connected via Wireguard using IPv6.
|
||||
# The maximum value for IPv6 is 128
|
||||
private_network_prefix_v6 = {{ wireguard.private_network_prefix_v6 }}
|
||||
|
||||
[wireguard.storage_paths]
|
||||
# Path to file containing wireguard x25519 diffie hellman private key.
|
||||
|
||||
@@ -11,7 +11,8 @@ async fn try_upgrade_config(path: &Path) -> Result<(), NymNodeError> {
|
||||
let cfg = try_upgrade_config_v1(path, None).await.ok();
|
||||
let cfg = try_upgrade_config_v2(path, cfg).await.ok();
|
||||
let cfg = try_upgrade_config_v3(path, cfg).await.ok();
|
||||
match try_upgrade_config_v4(path, cfg).await {
|
||||
let cfg = try_upgrade_config_v4(path, cfg).await.ok();
|
||||
match try_upgrade_config_v5(path, cfg).await {
|
||||
Ok(cfg) => cfg.save(),
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to finish upgrade - {e}");
|
||||
|
||||
@@ -43,7 +43,6 @@ pub mod vars {
|
||||
// wireguard:
|
||||
pub const NYMNODE_WG_ENABLED_ARG: &str = "NYMNODE_WG_ENABLED";
|
||||
pub const NYMNODE_WG_BIND_ADDRESS_ARG: &str = "NYMNODE_WG_BIND_ADDRESS";
|
||||
pub const NYMNODE_WG_IP_ARG: &str = "NYMNODE_WG_IP";
|
||||
pub const NYMNODE_WG_ANNOUNCED_PORT_ARG: &str = "NYMNODE_WG_ANNOUNCED_PORT";
|
||||
pub const NYMNODE_WG_PRIVATE_NETWORK_PREFIX_ARG: &str = "NYMNODE_WG_PRIVATE_NETWORK_PREFIX";
|
||||
|
||||
|
||||
@@ -143,17 +143,17 @@ impl<S: Storage + Clone + 'static> Authenticator<S> {
|
||||
let used_private_network_ips =
|
||||
std::collections::BTreeSet::from_iter(self.used_private_network_ips.iter());
|
||||
let private_ip_network = IpNetwork::new(
|
||||
self.config.authenticator.private_ip,
|
||||
self.config.authenticator.private_network_prefix,
|
||||
self.config.authenticator.private_ipv4.into(),
|
||||
self.config.authenticator.private_network_prefix_v4,
|
||||
)?;
|
||||
let now = SystemTime::now();
|
||||
let free_private_network_ips = private_ip_network
|
||||
.iter()
|
||||
.map(|ip| {
|
||||
.map(|ip: IpAddr| {
|
||||
if used_private_network_ips.contains(&ip) {
|
||||
(ip, Some(now))
|
||||
(ip.into(), Some(now))
|
||||
} else {
|
||||
(ip, None)
|
||||
(ip.into(), None)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -6,14 +6,14 @@ use crate::cli::{override_config, OverrideConfig};
|
||||
use crate::cli::{try_load_current_config, version_check};
|
||||
use clap::{Args, Subcommand};
|
||||
use nym_authenticator_requests::latest::{
|
||||
registration::{ClientMac, FinalMessage, GatewayClient, InitMessage},
|
||||
registration::{ClientMac, FinalMessage, GatewayClient, InitMessage, IpPair},
|
||||
request::{AuthenticatorRequest, AuthenticatorRequestData},
|
||||
};
|
||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||
use nym_sdk::mixnet::{MixnetMessageSender, Recipient, TransmissionLane};
|
||||
use nym_task::TaskHandle;
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use std::net::IpAddr;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
@@ -55,7 +55,8 @@ pub(crate) struct Initial {
|
||||
#[derive(Args, Clone, Debug)]
|
||||
pub(crate) struct Final {
|
||||
pub_key: String,
|
||||
private_ip: String,
|
||||
private_ipv4: String,
|
||||
private_ipv6: String,
|
||||
mac: String,
|
||||
}
|
||||
|
||||
@@ -75,7 +76,10 @@ impl TryFrom<RequestType> for AuthenticatorRequestData {
|
||||
RequestType::Final(req) => AuthenticatorRequestData::Final(Box::new(FinalMessage {
|
||||
gateway_client: GatewayClient {
|
||||
pub_key: PeerPublicKey::from_str(&req.pub_key)?,
|
||||
private_ip: IpAddr::from_str(&req.private_ip)?,
|
||||
private_ips: IpPair::new(
|
||||
Ipv4Addr::from_str(&req.private_ipv4)?,
|
||||
Ipv6Addr::from_str(&req.private_ipv6)?,
|
||||
),
|
||||
mac: ClientMac::from_str(&req.mac)?,
|
||||
},
|
||||
credential: None,
|
||||
|
||||
@@ -8,13 +8,16 @@ use nym_config::{
|
||||
must_get_home, save_formatted_config_to_file, NymConfigTemplate, OptionalSet,
|
||||
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
|
||||
};
|
||||
use nym_network_defaults::WG_PORT;
|
||||
use nym_network_defaults::{
|
||||
WG_PORT, WG_TUN_DEVICE_IP_ADDRESS_V4, WG_TUN_DEVICE_IP_ADDRESS_V6, WG_TUN_DEVICE_NETMASK_V4,
|
||||
WG_TUN_DEVICE_NETMASK_V6,
|
||||
};
|
||||
use nym_service_providers_common::DEFAULT_SERVICE_PROVIDERS_DIR;
|
||||
pub use persistence::AuthenticatorPaths;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
io,
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
@@ -192,24 +195,34 @@ pub struct Authenticator {
|
||||
|
||||
/// Private IP address of the wireguard gateway.
|
||||
/// default: `10.1.0.1`
|
||||
pub private_ip: IpAddr,
|
||||
pub private_ipv4: Ipv4Addr,
|
||||
|
||||
/// Private IP address of the wireguard gateway.
|
||||
/// default: `fc01::1`
|
||||
pub private_ipv6: Ipv6Addr,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
pub announced_port: u16,
|
||||
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard.
|
||||
/// The maximum value for IPv4 is 32 and for IPv6 is 128
|
||||
pub private_network_prefix: u8,
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard using IPv4.
|
||||
/// The maximum value for IPv4 is 32
|
||||
pub private_network_prefix_v4: u8,
|
||||
|
||||
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard using IPv6.
|
||||
/// The maximum value for IPv6 is 128
|
||||
pub private_network_prefix_v6: u8,
|
||||
}
|
||||
|
||||
impl Default for Authenticator {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 51822),
|
||||
private_ip: IpAddr::V4(Ipv4Addr::new(10, 1, 0, 1)),
|
||||
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), WG_PORT),
|
||||
private_ipv4: WG_TUN_DEVICE_IP_ADDRESS_V4,
|
||||
private_ipv6: WG_TUN_DEVICE_IP_ADDRESS_V6,
|
||||
announced_port: WG_PORT,
|
||||
private_network_prefix: 16,
|
||||
private_network_prefix_v4: WG_TUN_DEVICE_NETMASK_V4,
|
||||
private_network_prefix_v6: WG_TUN_DEVICE_NETMASK_V6,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,9 +231,11 @@ impl From<Authenticator> for nym_wireguard_types::Config {
|
||||
fn from(value: Authenticator) -> Self {
|
||||
nym_wireguard_types::Config {
|
||||
bind_address: value.bind_address,
|
||||
private_ip: value.private_ip,
|
||||
private_ipv4: value.private_ipv4,
|
||||
private_ipv6: value.private_ipv6,
|
||||
announced_port: value.announced_port,
|
||||
private_network_prefix: value.private_network_prefix,
|
||||
private_network_prefix_v4: value.private_network_prefix_v4,
|
||||
private_network_prefix_v6: value.private_network_prefix_v6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,15 @@ use defguard_wireguard_rs::net::IpAddrMask;
|
||||
use defguard_wireguard_rs::{host::Peer, key::Key};
|
||||
use futures::StreamExt;
|
||||
use nym_authenticator_requests::{
|
||||
v1, v2,
|
||||
v3::{
|
||||
self,
|
||||
latest::{
|
||||
registration::{
|
||||
FinalMessage, GatewayClient, InitMessage, PendingRegistrations, PrivateIPs,
|
||||
FinalMessage, GatewayClient, InitMessage, IpPair, PendingRegistrations, PrivateIPs,
|
||||
RegistrationData, RegistredData, RemainingBandwidthData,
|
||||
},
|
||||
request::{AuthenticatorRequest, AuthenticatorRequestData},
|
||||
response::AuthenticatorResponse,
|
||||
},
|
||||
CURRENT_VERSION,
|
||||
v1, v2, v3, v4, CURRENT_VERSION,
|
||||
};
|
||||
use nym_credential_verification::{
|
||||
bandwidth_storage_manager::BandwidthStorageManager, ecash::EcashManager,
|
||||
@@ -116,10 +114,10 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
|
||||
for reg in registred_values {
|
||||
let ip = registred_and_free
|
||||
.free_private_network_ips
|
||||
.get_mut(®.gateway_data.private_ip)
|
||||
.get_mut(®.gateway_data.private_ips)
|
||||
.ok_or(AuthenticatorError::InternalDataCorruption(format!(
|
||||
"IP {} should be present",
|
||||
reg.gateway_data.private_ip
|
||||
"IPs {} should be present",
|
||||
reg.gateway_data.private_ips
|
||||
)))?;
|
||||
|
||||
let Some(timestamp) = ip else {
|
||||
@@ -173,15 +171,29 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
|
||||
|
||||
let peer = self.peer_manager.query_peer(remote_public).await?;
|
||||
if let Some(peer) = peer {
|
||||
let Some(allowed_ip) = peer.allowed_ips.first() else {
|
||||
let private_ipv4 = peer
|
||||
.allowed_ips
|
||||
.iter()
|
||||
.find_map(|ip_mask| match ip_mask.ip {
|
||||
std::net::IpAddr::V4(ipv4_addr) => Some(ipv4_addr),
|
||||
_ => None,
|
||||
});
|
||||
let private_ipv6 = peer
|
||||
.allowed_ips
|
||||
.iter()
|
||||
.find_map(|ip_mask| match ip_mask.ip {
|
||||
std::net::IpAddr::V6(ipv6_addr) => Some(ipv6_addr),
|
||||
_ => None,
|
||||
});
|
||||
let (Some(allowed_ipv4), Some(allowed_ipv6)) = (private_ipv4, private_ipv6) else {
|
||||
return Err(AuthenticatorError::InternalError(
|
||||
"private ip list should not be empty".to_string(),
|
||||
"there should be one private IP pair in the list".to_string(),
|
||||
));
|
||||
};
|
||||
return Ok(AuthenticatorResponse::new_registered(
|
||||
RegistredData {
|
||||
pub_key: PeerPublicKey::new(self.keypair().public_key().to_bytes().into()),
|
||||
private_ip: allowed_ip.ip,
|
||||
private_ips: IpPair::new(allowed_ipv4, allowed_ipv6),
|
||||
wg_port: self.config.authenticator.announced_port,
|
||||
},
|
||||
reply_to,
|
||||
@@ -241,8 +253,14 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
|
||||
}
|
||||
|
||||
let mut peer = Peer::new(Key::new(final_message.gateway_client.pub_key.to_bytes()));
|
||||
peer.allowed_ips
|
||||
.push(IpAddrMask::new(final_message.gateway_client.private_ip, 32));
|
||||
peer.allowed_ips.push(IpAddrMask::new(
|
||||
final_message.gateway_client.private_ips.ipv4.into(),
|
||||
32,
|
||||
));
|
||||
peer.allowed_ips.push(IpAddrMask::new(
|
||||
final_message.gateway_client.private_ips.ipv6.into(),
|
||||
128,
|
||||
));
|
||||
|
||||
// If gateway does ecash verification and client sends a credential, we do the additional
|
||||
// credential verification. Later this will become mandatory.
|
||||
@@ -284,7 +302,7 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
|
||||
Ok(AuthenticatorResponse::new_registered(
|
||||
RegistredData {
|
||||
pub_key: registration_data.gateway_data.pub_key,
|
||||
private_ip: registration_data.gateway_data.private_ip,
|
||||
private_ips: registration_data.gateway_data.private_ips,
|
||||
wg_port: registration_data.wg_port,
|
||||
},
|
||||
reply_to,
|
||||
@@ -507,6 +525,7 @@ fn deserialize_request(reconstructed: &ReconstructedMessage) -> Result<Authentic
|
||||
[1, _] => v1::request::AuthenticatorRequest::from_reconstructed_message(reconstructed)
|
||||
.map_err(|err| AuthenticatorError::FailedToDeserializeTaggedPacket { source: err })
|
||||
.map(Into::<v2::request::AuthenticatorRequest>::into)
|
||||
.map(Into::<v3::request::AuthenticatorRequest>::into)
|
||||
.map(Into::into),
|
||||
[2, request_type] => {
|
||||
if request_type == ServiceProviderType::Authenticator as u8 {
|
||||
@@ -514,6 +533,7 @@ fn deserialize_request(reconstructed: &ReconstructedMessage) -> Result<Authentic
|
||||
.map_err(|err| AuthenticatorError::FailedToDeserializeTaggedPacket {
|
||||
source: err,
|
||||
})
|
||||
.map(Into::<v3::request::AuthenticatorRequest>::into)
|
||||
.map(Into::into)
|
||||
} else {
|
||||
Err(AuthenticatorError::InvalidPacketType(request_type))
|
||||
@@ -525,6 +545,17 @@ fn deserialize_request(reconstructed: &ReconstructedMessage) -> Result<Authentic
|
||||
.map_err(|err| AuthenticatorError::FailedToDeserializeTaggedPacket {
|
||||
source: err,
|
||||
})
|
||||
.map(Into::into)
|
||||
} else {
|
||||
Err(AuthenticatorError::InvalidPacketType(request_type))
|
||||
}
|
||||
}
|
||||
[4, request_type] => {
|
||||
if request_type == ServiceProviderType::Authenticator as u8 {
|
||||
v4::request::AuthenticatorRequest::from_reconstructed_message(reconstructed)
|
||||
.map_err(|err| AuthenticatorError::FailedToDeserializeTaggedPacket {
|
||||
source: err,
|
||||
})
|
||||
} else {
|
||||
Err(AuthenticatorError::InvalidPacketType(request_type))
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::time::Duration;
|
||||
pub const TUN_BASE_NAME: &str = "nymtun";
|
||||
pub const TUN_DEVICE_ADDRESS_V4: Ipv4Addr = Ipv4Addr::new(10, 0, 0, 1);
|
||||
pub const TUN_DEVICE_NETMASK_V4: Ipv4Addr = Ipv4Addr::new(255, 255, 0, 0);
|
||||
pub const TUN_DEVICE_ADDRESS_V6: Ipv6Addr = Ipv6Addr::new(0x2001, 0xdb8, 0xa160, 0, 0, 0, 0, 0x1); // 2001:db8:a160::1
|
||||
pub const TUN_DEVICE_ADDRESS_V6: Ipv6Addr = Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 0x1); // fc00::1
|
||||
|
||||
pub const TUN_DEVICE_NETMASK_V6: &str = "112";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user