Compare commits
15 Commits
gear
...
bogdan/testing
| Author | SHA1 | Date | |
|---|---|---|---|
| 697d55248d | |||
| 570cc36385 | |||
| ee64762b87 | |||
| f4528bb521 | |||
| f4630e0b8a | |||
| 65f948d012 | |||
| d16a288b6d | |||
| 72c40d8576 | |||
| 34e1709b75 | |||
| 257df97e3a | |||
| 870570d5c3 | |||
| 0000baa343 | |||
| 6a307d59b4 | |||
| a4808635f9 | |||
| 29965782a2 |
Generated
+3
-1
@@ -4576,7 +4576,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-gateway"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -5843,7 +5843,9 @@ dependencies = [
|
||||
"dashmap",
|
||||
"hmac 0.12.1",
|
||||
"log",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
"nym-network-defaults",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -171,3 +171,25 @@ impl fmt::Display for GatewayIpPacketRouterDetails {
|
||||
writeln!(f, "\taddress: {}", self.address)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GatewayWireguardDetails {
|
||||
pub enabled: bool,
|
||||
|
||||
pub announced_port: u16,
|
||||
pub private_network_prefix: u8,
|
||||
}
|
||||
|
||||
impl fmt::Display for GatewayWireguardDetails {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "wireguard:")?;
|
||||
writeln!(f, "\tenabled: {}", self.enabled)?;
|
||||
|
||||
writeln!(f, "\tannounced_port: {}", self.announced_port)?;
|
||||
writeln!(
|
||||
f,
|
||||
"\tprivate_network_prefix: {}",
|
||||
self.private_network_prefix
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ log = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
nym-config = { path = "../config" }
|
||||
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
|
||||
# feature-specific dependencies:
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
pub struct Config {
|
||||
/// Socket address this node will use for binding its wireguard interface.
|
||||
/// default: `0.0.0.0:51822`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Private IP address of the wireguard gateway.
|
||||
/// default: `10.1.0.1`
|
||||
pub private_ip: IpAddr,
|
||||
|
||||
/// 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,
|
||||
}
|
||||
@@ -1,15 +1,51 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use dashmap::DashMap;
|
||||
use nym_crypto::asymmetric::encryption::KeyPair;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod public_key;
|
||||
pub mod registration;
|
||||
|
||||
pub use config::Config;
|
||||
pub use error::Error;
|
||||
pub use public_key::PeerPublicKey;
|
||||
pub use registration::{
|
||||
ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, Nonce,
|
||||
ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, GatewayClientRegistry,
|
||||
InitMessage, Nonce,
|
||||
};
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
pub use registration::HmacSha256;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WireguardGatewayData {
|
||||
config: Config,
|
||||
keypair: Arc<KeyPair>,
|
||||
client_registry: Arc<GatewayClientRegistry>,
|
||||
}
|
||||
|
||||
impl WireguardGatewayData {
|
||||
pub fn new(config: Config, keypair: Arc<KeyPair>) -> Self {
|
||||
WireguardGatewayData {
|
||||
config,
|
||||
keypair,
|
||||
client_registry: Arc::new(DashMap::default()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn config(&self) -> Config {
|
||||
self.config
|
||||
}
|
||||
|
||||
pub fn keypair(&self) -> &Arc<KeyPair> {
|
||||
&self.keypair
|
||||
}
|
||||
|
||||
pub fn client_registry(&self) -> &Arc<GatewayClientRegistry> {
|
||||
&self.client_registry
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ impl PeerPublicKey {
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> PublicKey {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PeerPublicKey {
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::{fmt, ops::Deref, str::FromStr};
|
||||
#[cfg(feature = "verify")]
|
||||
use hmac::{Hmac, Mac};
|
||||
#[cfg(feature = "verify")]
|
||||
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
|
||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||
#[cfg(feature = "verify")]
|
||||
use sha2::Sha256;
|
||||
|
||||
@@ -87,7 +87,7 @@ impl GatewayClient {
|
||||
#[cfg(feature = "verify")]
|
||||
pub fn new(
|
||||
local_secret: &PrivateKey,
|
||||
remote_public: PublicKey,
|
||||
remote_public: x25519_dalek::PublicKey,
|
||||
private_ip: IpAddr,
|
||||
nonce: u64,
|
||||
) -> Self {
|
||||
@@ -96,8 +96,6 @@ impl GatewayClient {
|
||||
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
|
||||
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
|
||||
|
||||
let remote_public = x25519_dalek::PublicKey::from(remote_public.to_bytes());
|
||||
|
||||
let dh = static_secret.diffie_hellman(&remote_public);
|
||||
|
||||
// TODO: change that to use our nym_crypto::hmac module instead
|
||||
|
||||
+15
-18
@@ -3,40 +3,37 @@
|
||||
// #![warn(clippy::expect_used)]
|
||||
// #![warn(clippy::unwrap_used)]
|
||||
|
||||
pub mod setup;
|
||||
|
||||
/// Start wireguard device
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn start_wireguard(
|
||||
mut task_client: nym_task::TaskClient,
|
||||
_gateway_client_registry: std::sync::Arc<
|
||||
nym_wireguard_types::registration::GatewayClientRegistry,
|
||||
>,
|
||||
wireguard_data: std::sync::Arc<nym_wireguard_types::WireguardGatewayData>,
|
||||
) -> Result<defguard_wireguard_rs::WGApi, Box<dyn std::error::Error + Send + Sync + 'static>> {
|
||||
use crate::setup::{peer_allowed_ips, peer_static_public_key, PRIVATE_KEY};
|
||||
use base64::{prelude::BASE64_STANDARD, Engine};
|
||||
use defguard_wireguard_rs::{
|
||||
host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration, WGApi, WireguardInterfaceApi,
|
||||
};
|
||||
use nym_network_defaults::{WG_PORT, WG_TUN_DEVICE_ADDRESS};
|
||||
|
||||
let mut peers = vec![];
|
||||
for peer_client in wireguard_data.client_registry().iter() {
|
||||
let mut peer = Peer::new(Key::new(peer_client.pub_key.to_bytes()));
|
||||
let peer_ip_mask = IpAddrMask::new(peer_client.private_ip, 32);
|
||||
peer.set_allowed_ips(vec![peer_ip_mask]);
|
||||
peers.push(peer);
|
||||
}
|
||||
|
||||
let ifname = String::from("wg0");
|
||||
let wgapi = WGApi::new(ifname.clone(), false)?;
|
||||
wgapi.create_interface()?;
|
||||
let interface_config = InterfaceConfiguration {
|
||||
name: ifname.clone(),
|
||||
prvkey: PRIVATE_KEY.to_string(),
|
||||
address: WG_TUN_DEVICE_ADDRESS.to_string(),
|
||||
port: WG_PORT as u32,
|
||||
peers: vec![],
|
||||
prvkey: BASE64_STANDARD.encode(wireguard_data.keypair().private_key().to_bytes()),
|
||||
address: wireguard_data.config().private_ip.to_string(),
|
||||
port: wireguard_data.config().announced_port as u32,
|
||||
peers,
|
||||
};
|
||||
wgapi.configure_interface(&interface_config)?;
|
||||
let peer = peer_static_public_key();
|
||||
let mut peer = Peer::new(Key::new(peer.to_bytes()));
|
||||
let peer_ip = peer_allowed_ips();
|
||||
let peer_ip_mask = IpAddrMask::new(peer_ip.network_address(), peer_ip.netmask());
|
||||
peer.set_allowed_ips(vec![peer_ip_mask]);
|
||||
wgapi.configure_peer(&peer)?;
|
||||
wgapi.configure_peer_routing(&[peer.clone()])?;
|
||||
// wgapi.configure_peer_routing(&peers)?;
|
||||
|
||||
tokio::spawn(async move { task_client.recv().await });
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use log::info;
|
||||
|
||||
// The wireguard UDP listener
|
||||
pub const WG_ADDRESS: &str = "0.0.0.0";
|
||||
|
||||
// The private key of the listener
|
||||
// Corresponding public key: "WM8s8bYegwMa0TJ+xIwhk+dImk2IpDUKslDBCZPizlE="
|
||||
pub(crate) const PRIVATE_KEY: &str = "AEqXrLFT4qjYq3wmX0456iv94uM6nDj5ugp6Jedcflg=";
|
||||
|
||||
// The AllowedIPs for the connected peer, which is one a single IP and the same as the IP that the
|
||||
// peer has configured on their side.
|
||||
const ALLOWED_IPS: &str = "10.1.0.2";
|
||||
|
||||
fn decode_base64_key(base64_key: &str) -> [u8; 32] {
|
||||
general_purpose::STANDARD
|
||||
.decode(base64_key)
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn server_static_private_key() -> x25519_dalek::StaticSecret {
|
||||
// TODO: this is a temporary solution for development
|
||||
let static_private_bytes: [u8; 32] = decode_base64_key(PRIVATE_KEY);
|
||||
let static_private = x25519_dalek::StaticSecret::from(static_private_bytes);
|
||||
let static_public = x25519_dalek::PublicKey::from(&static_private);
|
||||
info!(
|
||||
"wg public key: {}",
|
||||
general_purpose::STANDARD.encode(static_public)
|
||||
);
|
||||
static_private
|
||||
}
|
||||
|
||||
pub fn peer_static_public_key() -> x25519_dalek::PublicKey {
|
||||
// A single static public key is used during development
|
||||
|
||||
// Read from NYM_PEER_PUBLIC_KEY env variable
|
||||
let peer = std::env::var("NYM_PEER_PUBLIC_KEY").expect("NYM_PEER_PUBLIC_KEY must be set");
|
||||
|
||||
let peer_static_public_bytes: [u8; 32] = decode_base64_key(&peer);
|
||||
let peer_static_public = x25519_dalek::PublicKey::from(peer_static_public_bytes);
|
||||
info!(
|
||||
"Adding wg peer public key: {}",
|
||||
general_purpose::STANDARD.encode(peer_static_public)
|
||||
);
|
||||
peer_static_public
|
||||
}
|
||||
|
||||
pub fn peer_allowed_ips() -> ip_network::IpNetwork {
|
||||
let key: IpAddr = ALLOWED_IPS.parse().unwrap();
|
||||
let cidr = 32u8;
|
||||
ip_network::IpNetwork::new_truncate(key, cidr).unwrap()
|
||||
}
|
||||
@@ -148,8 +148,8 @@ Options:
|
||||
Specifies whether the wireguard service is enabled on this node [env: NYMNODE_WG_ENABLED=] [possible values: true, false]
|
||||
--wireguard-bind-address <WIREGUARD_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its wireguard interface. default: `0.0.0.0:51822` [env: NYMNODE_WG_BIND_ADDRESS=]
|
||||
--wireguard-private-network-ip <WIREGUARD_PRIVATE_NETWORK_IP>
|
||||
Ip address of the private wireguard network. default: `10.1.0.0` [env: NYMNODE_WG_IP_NETWORK=]
|
||||
--wireguard-private-gw-ip <WIREGUARD_PRIVATE_IP>
|
||||
Private IP address of the wireguard gateway. default: `10.1.0.1` [env: NYMNODE_WG_IP=]
|
||||
--wireguard-announced-port <WIREGUARD_ANNOUNCED_PORT>
|
||||
Port announced to external clients wishing to connect to the wireguard interface. Useful in the instances where the node is behind a proxy [env: NYMNODE_WG_ANNOUNCED_PORT=]
|
||||
--wireguard-private-network-prefix <WIREGUARD_PRIVATE_NETWORK_PREFIX>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-gateway"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.36"
|
||||
version = "1.1.37"
|
||||
authors = [
|
||||
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
|
||||
"Jędrzej Stuczyński <andrew@nymtech.net>",
|
||||
|
||||
@@ -84,13 +84,13 @@ fn try_upgrade_v1_1_29_config(id: &str) -> Result<bool, GatewayError> {
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_31_config(id: &str) -> Result<bool, GatewayError> {
|
||||
// explicitly load it as v1.1.30 (which is incompatible with the current, i.e. 1.1.31+)
|
||||
// explicitly load it as v1.1.35 (which is incompatible with the current, i.e. 1.1.36+)
|
||||
let Ok(old_config) = ConfigV1_1_31::read_from_default_path(id) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the gateway is using <= v1.1.30 config template.");
|
||||
info!("It seems the gateway is using <= v1.1.35 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated: Config = old_config.into();
|
||||
|
||||
@@ -11,7 +11,7 @@ use nym_config::{
|
||||
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
|
||||
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
|
||||
};
|
||||
use nym_network_defaults::{mainnet, DEFAULT_NYM_NODE_HTTP_PORT, WG_PORT};
|
||||
use nym_network_defaults::{mainnet, DEFAULT_NYM_NODE_HTTP_PORT};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
@@ -20,7 +20,7 @@ use std::time::Duration;
|
||||
use url::Url;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
pub use crate::config::persistence::paths::{GatewayPaths, WireguardPaths};
|
||||
pub use crate::config::persistence::paths::GatewayPaths;
|
||||
|
||||
pub mod old_config_v1_1_20;
|
||||
pub mod old_config_v1_1_28;
|
||||
@@ -85,10 +85,6 @@ pub struct Config {
|
||||
|
||||
pub gateway: Gateway,
|
||||
|
||||
// currently not really used for anything useful
|
||||
#[serde(default)]
|
||||
pub wireguard: Wireguard,
|
||||
|
||||
pub storage_paths: GatewayPaths,
|
||||
|
||||
pub network_requester: NetworkRequester,
|
||||
@@ -121,7 +117,6 @@ impl Config {
|
||||
},
|
||||
http: Default::default(),
|
||||
gateway: default_gateway,
|
||||
wireguard: Default::default(),
|
||||
storage_paths: GatewayPaths::new_default(id.as_ref()),
|
||||
network_requester: Default::default(),
|
||||
ip_packet_router: Default::default(),
|
||||
@@ -135,7 +130,6 @@ impl Config {
|
||||
host: impl Into<Host>,
|
||||
http: impl Into<Http>,
|
||||
gateway: impl Into<Gateway>,
|
||||
wireguard: impl Into<Wireguard>,
|
||||
storage_paths: impl Into<GatewayPaths>,
|
||||
network_requester: impl Into<NetworkRequester>,
|
||||
ip_packet_router: impl Into<IpPacketRouter>,
|
||||
@@ -147,7 +141,6 @@ impl Config {
|
||||
host: host.into(),
|
||||
http: http.into(),
|
||||
gateway: gateway.into(),
|
||||
wireguard: wireguard.into(),
|
||||
storage_paths: storage_paths.into(),
|
||||
network_requester: network_requester.into(),
|
||||
ip_packet_router: ip_packet_router.into(),
|
||||
@@ -262,8 +255,6 @@ impl Config {
|
||||
|
||||
let http_port = self.http.bind_address.port();
|
||||
self.http.bind_address = SocketAddr::new(listening_address, http_port);
|
||||
let wg_port = self.wireguard.bind_address.port();
|
||||
self.wireguard.bind_address = SocketAddr::new(listening_address, wg_port);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -347,40 +338,6 @@ impl Default for Http {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Wireguard {
|
||||
/// Specifies whether the wireguard service is enabled on this node.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Socket address this node will use for binding its wireguard interface.
|
||||
/// default: `0.0.0.0:51822`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// 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,
|
||||
|
||||
/// Paths for wireguard keys, client registries, etc.
|
||||
pub storage_paths: WireguardPaths,
|
||||
}
|
||||
|
||||
impl Default for Wireguard {
|
||||
fn default() -> Self {
|
||||
Wireguard {
|
||||
enabled: false,
|
||||
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), WG_PORT),
|
||||
announced_port: WG_PORT,
|
||||
private_network_prefix: 16,
|
||||
storage_paths: WireguardPaths {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we only really care about the mnemonic being zeroized
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Zeroize, ZeroizeOnDrop)]
|
||||
pub struct Gateway {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::config::persistence::paths::{GatewayPaths, WireguardPaths};
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_config::{
|
||||
must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR,
|
||||
};
|
||||
@@ -14,8 +12,9 @@ use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
use super::persistence::paths::KeysPaths;
|
||||
use super::{Config, Debug, Gateway, Host, Http, NetworkRequester, Wireguard};
|
||||
use super::{Host, Http};
|
||||
use crate::config::persistence::paths::KeysPaths;
|
||||
use crate::config::{Config, Debug, Gateway, GatewayPaths, LoggingSettings, NetworkRequester};
|
||||
|
||||
const DEFAULT_GATEWAYS_DIR: &str = "gateways";
|
||||
|
||||
@@ -125,15 +124,6 @@ impl From<ConfigV1_1_31> for Config {
|
||||
nyxd_urls: value.gateway.nyxd_urls,
|
||||
cosmos_mnemonic: value.gateway.cosmos_mnemonic,
|
||||
},
|
||||
wireguard: Wireguard {
|
||||
enabled: value.wireguard.enabled,
|
||||
bind_address: value.wireguard.bind_address,
|
||||
announced_port: value.wireguard.announced_port,
|
||||
private_network_prefix: Default::default(),
|
||||
storage_paths: WireguardPaths {
|
||||
// no fields (yet)
|
||||
},
|
||||
},
|
||||
storage_paths: GatewayPaths {
|
||||
keys: KeysPaths {
|
||||
private_identity_key_file: value.storage_paths.keys.private_identity_key_file,
|
||||
|
||||
@@ -169,15 +169,3 @@ impl KeysPaths {
|
||||
&self.public_sphinx_key_file
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WireguardPaths {
|
||||
// pub keys:
|
||||
}
|
||||
|
||||
impl WireguardPaths {
|
||||
pub fn new_empty() -> Self {
|
||||
WireguardPaths {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,17 @@ pub enum GatewayError {
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"failed to load config file for wireguard (gateway-id: '{id}') using path '{}'. detailed message: {source}",
|
||||
path.display()
|
||||
)]
|
||||
WireguardConfigLoadFailure {
|
||||
id: String,
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"failed to save config file for id {id} using path '{}'. detailed message: {source}", path.display()
|
||||
)]
|
||||
@@ -167,6 +178,17 @@ pub enum GatewayError {
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
#[error("failed to remove wireguard interface: {0}")]
|
||||
WireguardInterfaceError(#[from] defguard_wireguard_rs::error::WireguardInterfaceError),
|
||||
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
#[error("wireguard not set")]
|
||||
WireguardNotSet,
|
||||
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
#[error("failed to catch an interrupt: {source}")]
|
||||
StdError {
|
||||
#[source]
|
||||
source: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<ClientCoreError> for GatewayError {
|
||||
|
||||
+8
-34
@@ -4,7 +4,6 @@
|
||||
use crate::config::Config;
|
||||
use crate::error::GatewayError;
|
||||
use crate::helpers::load_public_key;
|
||||
use ipnetwork::IpNetwork;
|
||||
use log::{debug, error, warn};
|
||||
use nym_bin_common::bin_info_owned;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
@@ -12,30 +11,19 @@ use nym_network_requester::RequestFilter;
|
||||
use nym_node_http_api::api::api_requests;
|
||||
use nym_node_http_api::api::api_requests::v1::network_requester::exit_policy::models::UsedExitPolicy;
|
||||
use nym_node_http_api::api::api_requests::SignedHostInformation;
|
||||
use nym_node_http_api::router::WireguardAppState;
|
||||
use nym_node_http_api::NymNodeHttpError;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_task::TaskClient;
|
||||
use nym_wireguard_types::registration::GatewayClientRegistry;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use nym_wireguard_types::WireguardGatewayData;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn load_gateway_details(
|
||||
config: &Config,
|
||||
) -> Result<api_requests::v1::gateway::models::Gateway, GatewayError> {
|
||||
let wireguard = if config.wireguard.enabled {
|
||||
Some(api_requests::v1::gateway::models::Wireguard {
|
||||
port: config.wireguard.announced_port,
|
||||
public_key: "placeholder key value".to_string(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(api_requests::v1::gateway::models::Gateway {
|
||||
enforces_zk_nyms: config.gateway.only_coconut_credentials,
|
||||
client_interfaces: api_requests::v1::gateway::models::ClientInterfaces {
|
||||
wireguard,
|
||||
wireguard: None,
|
||||
mixnet_websockets: Some(api_requests::v1::gateway::models::WebSockets {
|
||||
ws_port: config.gateway.clients_port,
|
||||
wss_port: config.gateway.clients_wss_port,
|
||||
@@ -154,7 +142,7 @@ pub(crate) struct HttpApiBuilder<'a> {
|
||||
// TODO: this should be a wg specific key and not re-used sphinx
|
||||
sphinx_keypair: Arc<encryption::KeyPair>,
|
||||
|
||||
client_registry: Option<Arc<GatewayClientRegistry>>,
|
||||
wireguard_data: Option<Arc<WireguardGatewayData>>,
|
||||
}
|
||||
|
||||
impl<'a> HttpApiBuilder<'a> {
|
||||
@@ -170,7 +158,7 @@ impl<'a> HttpApiBuilder<'a> {
|
||||
exit_policy: None,
|
||||
identity_keypair,
|
||||
sphinx_keypair,
|
||||
client_registry: None,
|
||||
wireguard_data: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,11 +223,11 @@ impl<'a> HttpApiBuilder<'a> {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub(crate) fn with_wireguard_client_registry(
|
||||
pub(crate) fn with_wireguard_data(
|
||||
mut self,
|
||||
client_registry: Arc<GatewayClientRegistry>,
|
||||
wireguard_data: Option<Arc<WireguardGatewayData>>,
|
||||
) -> Self {
|
||||
self.client_registry = Some(client_registry);
|
||||
self.wireguard_data = wireguard_data;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -281,22 +269,8 @@ impl<'a> HttpApiBuilder<'a> {
|
||||
)?);
|
||||
}
|
||||
|
||||
let wireguard_private_network = IpNetwork::new(
|
||||
IpAddr::from(Ipv4Addr::new(10, 1, 0, 0)),
|
||||
self.gateway_config.wireguard.private_network_prefix,
|
||||
)?;
|
||||
let wg_state = self.client_registry.and_then(|client_registry| {
|
||||
WireguardAppState::new(
|
||||
client_registry,
|
||||
Default::default(),
|
||||
self.gateway_config.wireguard.bind_address.port(),
|
||||
wireguard_private_network,
|
||||
)
|
||||
.ok()
|
||||
});
|
||||
|
||||
let bind_address = self.gateway_config.http.bind_address;
|
||||
let router = nym_node_http_api::NymNodeRouter::new(config, None, wg_state);
|
||||
let router = nym_node_http_api::NymNodeRouter::new(config, None, None);
|
||||
|
||||
tokio::spawn(async move {
|
||||
let server = match router.build_server(&bind_address).await {
|
||||
|
||||
+23
-15
@@ -16,7 +16,6 @@ use crate::node::client_handling::websocket::connection_handler::coconut::Coconu
|
||||
use crate::node::helpers::{initialise_main_storage, load_network_requester_config};
|
||||
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
|
||||
use crate::node::statistics::collector::GatewayStatisticsCollector;
|
||||
use dashmap::DashMap;
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
use log::*;
|
||||
use nym_crypto::asymmetric::{encryption, identity};
|
||||
@@ -28,7 +27,7 @@ use nym_task::{TaskClient, TaskHandle, TaskManager};
|
||||
use nym_types::gateway::GatewayNodeDetailsResponse;
|
||||
use nym_validator_client::nyxd::{Coin, CosmWasmClient};
|
||||
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient};
|
||||
use nym_wireguard_types::registration::GatewayClientRegistry;
|
||||
use nym_wireguard_types::WireguardGatewayData;
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::net::SocketAddr;
|
||||
@@ -126,9 +125,10 @@ pub struct Gateway<St = PersistentStorage> {
|
||||
|
||||
/// x25519 keypair used for Diffie-Hellman. Currently only used for sphinx key derivation.
|
||||
sphinx_keypair: Arc<encryption::KeyPair>,
|
||||
|
||||
storage: St,
|
||||
|
||||
client_registry: Arc<GatewayClientRegistry>,
|
||||
wireguard_data: Option<Arc<WireguardGatewayData>>,
|
||||
|
||||
run_http_server: bool,
|
||||
task_client: Option<TaskClient>,
|
||||
@@ -149,7 +149,7 @@ impl<St> Gateway<St> {
|
||||
config,
|
||||
network_requester_opts,
|
||||
ip_packet_router_opts,
|
||||
client_registry: Arc::new(DashMap::new()),
|
||||
wireguard_data: None,
|
||||
run_http_server: true,
|
||||
task_client: None,
|
||||
})
|
||||
@@ -170,7 +170,7 @@ impl<St> Gateway<St> {
|
||||
identity_keypair,
|
||||
sphinx_keypair,
|
||||
storage,
|
||||
client_registry: Arc::new(DashMap::new()),
|
||||
wireguard_data: None,
|
||||
run_http_server: true,
|
||||
task_client: None,
|
||||
}
|
||||
@@ -184,12 +184,14 @@ impl<St> Gateway<St> {
|
||||
self.task_client = Some(task_client)
|
||||
}
|
||||
|
||||
pub fn set_wireguard_client_registry(&mut self, client_registry: Arc<GatewayClientRegistry>) {
|
||||
pub fn set_wireguard_data(&mut self, wireguard_data: Arc<WireguardGatewayData>) {
|
||||
// sanity check:
|
||||
if Arc::strong_count(&self.client_registry) != 1 {
|
||||
panic!("the client registry is already being used elsewhere")
|
||||
if let Some(wg_data) = self.wireguard_data.as_ref() {
|
||||
if Arc::strong_count(wg_data) != 1 {
|
||||
panic!("the client registry is already being used elsewhere")
|
||||
}
|
||||
}
|
||||
self.client_registry = client_registry
|
||||
self.wireguard_data = Some(wireguard_data)
|
||||
}
|
||||
|
||||
pub async fn node_details(&self) -> Result<GatewayNodeDetailsResponse, GatewayError> {
|
||||
@@ -230,7 +232,11 @@ impl<St> Gateway<St> {
|
||||
&self,
|
||||
shutdown: TaskClient,
|
||||
) -> Result<defguard_wireguard_rs::WGApi, Box<dyn std::error::Error + Send + Sync>> {
|
||||
nym_wireguard::start_wireguard(shutdown, Arc::clone(&self.client_registry)).await
|
||||
if let Some(wireguard_data) = self.wireguard_data.as_ref() {
|
||||
nym_wireguard::start_wireguard(shutdown, Arc::clone(wireguard_data)).await
|
||||
} else {
|
||||
Err(Box::new(GatewayError::WireguardNotSet))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wireguard", not(target_os = "linux")))]
|
||||
@@ -555,7 +561,7 @@ impl<St> Gateway<St> {
|
||||
self.identity_keypair.as_ref(),
|
||||
self.sphinx_keypair.clone(),
|
||||
)
|
||||
.with_wireguard_client_registry(self.client_registry.clone())
|
||||
.with_wireguard_data(self.wireguard_data.clone())
|
||||
.with_maybe_network_requester(self.network_requester_opts.as_ref().map(|o| &o.config))
|
||||
.with_maybe_network_request_filter(nr_request_filter)
|
||||
.with_maybe_ip_packet_router(self.ip_packet_router_opts.as_ref().map(|o| &o.config))
|
||||
@@ -565,7 +571,10 @@ impl<St> Gateway<St> {
|
||||
// Once this is a bit more mature, make this a commandline flag instead of a compile time
|
||||
// flag
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
let wg_api = self.start_wireguard(shutdown.fork("wireguard")).await.ok();
|
||||
let wg_api = self
|
||||
.start_wireguard(shutdown.fork("wireguard"))
|
||||
.await
|
||||
.map_err(|source| GatewayError::StdError { source })?;
|
||||
|
||||
#[cfg(all(feature = "wireguard", not(target_os = "linux")))]
|
||||
self.start_wireguard(shutdown.fork("wireguard")).await;
|
||||
@@ -577,9 +586,8 @@ impl<St> Gateway<St> {
|
||||
return Err(GatewayError::ShutdownFailure { source });
|
||||
}
|
||||
#[cfg(all(feature = "wireguard", target_os = "linux"))]
|
||||
if let Some(wg_api) = wg_api {
|
||||
defguard_wireguard_rs::WireguardInterfaceApi::remove_interface(&wg_api)?;
|
||||
}
|
||||
defguard_wireguard_rs::WireguardInterfaceApi::remove_interface(&wg_api)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,3 +60,6 @@ nym-ip-packet-router = { path = "../service-providers/ip-packet-router" }
|
||||
[build-dependencies]
|
||||
# temporary bonding information v1 (to grab and parse nym-mixnode and nym-gateway package versions)
|
||||
cargo_metadata = "0.18.1"
|
||||
|
||||
[features]
|
||||
wireguard = ["nym-gateway/wireguard"]
|
||||
|
||||
+6
-5
@@ -10,7 +10,6 @@ use crate::router::types::RequestError;
|
||||
use axum::extract::{Path, Query, State};
|
||||
use axum::http::StatusCode;
|
||||
use axum::Json;
|
||||
use nym_crypto::asymmetric::encryption::PublicKey;
|
||||
use nym_node_requests::api::v1::gateway::client_interfaces::wireguard::models::{
|
||||
ClientMessage, ClientRegistrationResponse, GatewayClient, InitMessage, Nonce, PeerPublicKey,
|
||||
};
|
||||
@@ -31,7 +30,10 @@ async fn process_final_message(
|
||||
}
|
||||
};
|
||||
|
||||
if client.verify(&state.private_key, preshared_nonce).is_ok() {
|
||||
if client
|
||||
.verify(&state.keypair.private_key(), preshared_nonce)
|
||||
.is_ok()
|
||||
{
|
||||
state.registration_in_progress.remove(&client.pub_key());
|
||||
state.client_registry.insert(client.pub_key(), client);
|
||||
|
||||
@@ -86,8 +88,7 @@ pub(crate) async fn register_client(
|
||||
|
||||
match payload {
|
||||
ClientMessage::Initial(init) => {
|
||||
let remote_public = PublicKey::from_bytes(init.pub_key().as_bytes())
|
||||
.map_err(|_| RequestError::new_status(StatusCode::BAD_REQUEST))?;
|
||||
let remote_public = init.pub_key().inner();
|
||||
let nonce = process_init_message(init, state).await;
|
||||
let mut private_ip_ref = state
|
||||
.free_private_network_ips
|
||||
@@ -101,7 +102,7 @@ pub(crate) async fn register_client(
|
||||
// mark it as used, even though it's not final
|
||||
*private_ip_ref = false;
|
||||
let gateway_data = GatewayClient::new(
|
||||
&state.private_key,
|
||||
&state.keypair.private_key(),
|
||||
remote_public,
|
||||
*private_ip_ref.key(),
|
||||
nonce,
|
||||
|
||||
+7
-9
@@ -8,11 +8,11 @@ use crate::error::NymNodeHttpError;
|
||||
use axum::routing::{get, post};
|
||||
use axum::Router;
|
||||
use ipnetwork::IpNetwork;
|
||||
use nym_crypto::asymmetric::encryption::PrivateKey;
|
||||
use nym_crypto::asymmetric::x25519::KeyPair;
|
||||
use nym_node_requests::routes::api::v1::gateway::client_interfaces::wireguard;
|
||||
use nym_wireguard::setup;
|
||||
use nym_wireguard_types::registration::PrivateIPs;
|
||||
use nym_wireguard_types::registration::{GatewayClientRegistry, PendingRegistrations};
|
||||
use nym_wireguard_types::WireguardGatewayData;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(crate) mod client_registry;
|
||||
@@ -27,17 +27,15 @@ pub struct WireguardAppState {
|
||||
|
||||
impl WireguardAppState {
|
||||
pub fn new(
|
||||
client_registry: Arc<GatewayClientRegistry>,
|
||||
wireguard_gateway_data: &WireguardGatewayData,
|
||||
registration_in_progress: Arc<PendingRegistrations>,
|
||||
binding_port: u16,
|
||||
private_ip_network: IpNetwork,
|
||||
) -> Result<Self, NymNodeHttpError> {
|
||||
Ok(WireguardAppState {
|
||||
inner: Some(WireguardAppStateInner {
|
||||
private_key: Arc::new(PrivateKey::from_bytes(
|
||||
setup::server_static_private_key().as_ref(),
|
||||
)?),
|
||||
client_registry,
|
||||
keypair: wireguard_gateway_data.keypair().clone(),
|
||||
client_registry: wireguard_gateway_data.client_registry().clone(),
|
||||
registration_in_progress,
|
||||
binding_port,
|
||||
free_private_network_ips: Arc::new(
|
||||
@@ -83,7 +81,7 @@ macro_rules! get_state {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct WireguardAppStateInner {
|
||||
private_key: Arc<PrivateKey>,
|
||||
keypair: Arc<KeyPair>,
|
||||
client_registry: Arc<GatewayClientRegistry>,
|
||||
registration_in_progress: Arc<PendingRegistrations>,
|
||||
binding_port: u16,
|
||||
@@ -168,7 +166,7 @@ mod test {
|
||||
let state = WireguardAppState {
|
||||
inner: Some(WireguardAppStateInner {
|
||||
client_registry: Arc::clone(&client_registry),
|
||||
private_key: Arc::new(gateway_private_key),
|
||||
keypair: Arc::new(gateway_private_key),
|
||||
registration_in_progress: Arc::clone(®istration_in_progress),
|
||||
binding_port: 8080,
|
||||
free_private_network_ips,
|
||||
|
||||
@@ -18,8 +18,8 @@ use nym_mixnode::MixnodeError;
|
||||
use nym_network_requester::{CustomGatewayDetails, GatewayDetails};
|
||||
use nym_node::config;
|
||||
use nym_node::config::mixnode::DEFAULT_VERLOC_PORT;
|
||||
use nym_node::config::Config;
|
||||
use nym_node::config::{default_config_filepath, ConfigBuilder, NodeMode};
|
||||
use nym_node::config::{Config, DEFAULT_WIREGUARD_NETWORK_IP};
|
||||
use nym_node::error::{EntryGatewayError, ExitGatewayError, NymNodeError};
|
||||
use nym_node_http_api::api::api_requests::v1::node::models::NodeDescription;
|
||||
use rand::rngs::OsRng;
|
||||
@@ -400,15 +400,6 @@ async fn migrate_gateway(mut args: Args) -> Result<(), NymNodeError> {
|
||||
},
|
||||
..config::MixnodeConfig::new_default()
|
||||
}))
|
||||
.with_wireguard(args.wireguard.override_config_section(config::Wireguard {
|
||||
enabled: cfg.wireguard.enabled,
|
||||
bind_address: cfg.wireguard.bind_address,
|
||||
private_network_ip: DEFAULT_WIREGUARD_NETWORK_IP,
|
||||
announced_port: cfg.wireguard.announced_port,
|
||||
private_network_prefix: cfg.wireguard.private_network_prefix,
|
||||
// this is fine as currently the paths stored inside gateway itself are empty
|
||||
storage_paths: config::persistence::WireguardPaths::new(&data_dir),
|
||||
}))
|
||||
.with_entry_gateway(args.entry_gateway.override_config_section(
|
||||
config::EntryGatewayConfig {
|
||||
storage_paths: config::persistence::EntryGatewayPaths::new(&data_dir),
|
||||
@@ -606,6 +597,8 @@ async fn migrate_gateway(mut args: Args) -> Result<(), NymNodeError> {
|
||||
.await?;
|
||||
}
|
||||
|
||||
crate::node::WireguardData::initialise(&config.wireguard)?;
|
||||
|
||||
save_node_description(
|
||||
&config.storage_paths.description,
|
||||
&NodeDescription::default(),
|
||||
|
||||
@@ -253,13 +253,13 @@ pub(crate) struct WireguardArgs {
|
||||
)]
|
||||
pub(crate) wireguard_bind_address: Option<SocketAddr>,
|
||||
|
||||
/// Ip address of the private wireguard network.
|
||||
/// default: `10.1.0.0`
|
||||
/// Private IP address of the wireguard gateway.
|
||||
/// default: `10.1.0.1`
|
||||
#[clap(
|
||||
long,
|
||||
env = NYMNODE_WG_IP_NETWORK_ARG,
|
||||
env = NYMNODE_WG_IP_ARG,
|
||||
)]
|
||||
pub(crate) wireguard_private_network_ip: Option<IpAddr>,
|
||||
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.
|
||||
@@ -300,8 +300,8 @@ impl WireguardArgs {
|
||||
section.announced_port = announced_port
|
||||
}
|
||||
|
||||
if let Some(private_network_ip) = self.wireguard_private_network_ip {
|
||||
section.private_network_ip = private_network_ip
|
||||
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 {
|
||||
|
||||
@@ -13,6 +13,8 @@ use serde::{Deserialize, Serialize};
|
||||
use std::path::Path;
|
||||
use url::Url;
|
||||
|
||||
use super::LocalWireguardOpts;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ExitGatewayConfig {
|
||||
@@ -136,6 +138,7 @@ pub struct EphemeralConfig {
|
||||
pub gateway: nym_gateway::config::Config,
|
||||
pub nr_opts: LocalNetworkRequesterOpts,
|
||||
pub ipr_opts: LocalIpPacketRouterOpts,
|
||||
pub wg_opts: LocalWireguardOpts,
|
||||
}
|
||||
|
||||
fn base_client_config(config: &Config) -> nym_client_core_config_types::Client {
|
||||
@@ -241,6 +244,18 @@ pub fn ephemeral_exit_gateway_config(
|
||||
let ipr_enabled = config.exit_gateway.ip_packet_router.debug.enabled;
|
||||
let nr_enabled = config.exit_gateway.network_requester.debug.enabled;
|
||||
|
||||
let wg_opts = LocalWireguardOpts {
|
||||
config: super::Wireguard {
|
||||
enabled: config.wireguard.enabled,
|
||||
bind_address: config.wireguard.bind_address,
|
||||
private_ip: config.wireguard.private_ip,
|
||||
announced_port: config.wireguard.announced_port,
|
||||
private_network_prefix: config.wireguard.private_network_prefix,
|
||||
storage_paths: config.wireguard.storage_paths.clone(),
|
||||
},
|
||||
custom_mixnet_path: None,
|
||||
};
|
||||
|
||||
let mut gateway = ephemeral_gateway_config(config, mnemonic)?;
|
||||
gateway.ip_packet_router.enabled = ipr_enabled;
|
||||
gateway.network_requester.enabled = nr_enabled;
|
||||
@@ -253,6 +268,7 @@ pub fn ephemeral_exit_gateway_config(
|
||||
Ok(EphemeralConfig {
|
||||
nr_opts,
|
||||
ipr_opts,
|
||||
wg_opts,
|
||||
gateway,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -57,19 +57,10 @@ pub fn ephemeral_gateway_config(
|
||||
cosmos_mnemonic: mnemonic.clone(),
|
||||
};
|
||||
|
||||
let wireguard = nym_gateway::config::Wireguard {
|
||||
enabled: config.wireguard.enabled,
|
||||
bind_address: config.wireguard.bind_address,
|
||||
announced_port: config.wireguard.announced_port,
|
||||
private_network_prefix: config.wireguard.private_network_prefix,
|
||||
storage_paths: nym_gateway::config::WireguardPaths::new_empty(),
|
||||
};
|
||||
|
||||
Ok(nym_gateway::config::Config::externally_loaded(
|
||||
host,
|
||||
http,
|
||||
gateway,
|
||||
wireguard,
|
||||
nym_gateway::config::GatewayPaths::new_empty(),
|
||||
nym_gateway::config::NetworkRequester { enabled: false },
|
||||
nym_gateway::config::IpPacketRouter { enabled: false },
|
||||
|
||||
@@ -40,7 +40,7 @@ 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_NETWORK_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(10, 1, 0, 0));
|
||||
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;
|
||||
@@ -500,9 +500,9 @@ pub struct Wireguard {
|
||||
/// default: `0.0.0.0:51822`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Ip address of the private wireguard network.
|
||||
/// default: `10.1.0.0`
|
||||
pub private_network_ip: IpAddr,
|
||||
/// Private IP address of the wireguard gateway.
|
||||
/// default: `10.1.0.1`
|
||||
pub private_ip: IpAddr,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
@@ -524,10 +524,28 @@ impl Wireguard {
|
||||
IpAddr::V4(Ipv4Addr::UNSPECIFIED),
|
||||
DEFAULT_WIREGUARD_PORT,
|
||||
),
|
||||
private_network_ip: DEFAULT_WIREGUARD_NETWORK_IP,
|
||||
private_ip: DEFAULT_WIREGUARD_IP,
|
||||
announced_port: DEFAULT_WIREGUARD_PORT,
|
||||
private_network_prefix: DEFAULT_WIREGUARD_PREFIX,
|
||||
storage_paths: persistence::WireguardPaths::new(data_dir),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<nym_wireguard_types::Config> for Wireguard {
|
||||
fn into(self) -> nym_wireguard_types::Config {
|
||||
nym_wireguard_types::Config {
|
||||
bind_address: self.bind_address,
|
||||
private_ip: self.private_ip,
|
||||
announced_port: self.announced_port,
|
||||
private_network_prefix: self.private_network_prefix,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocalWireguardOpts {
|
||||
pub config: Wireguard,
|
||||
|
||||
pub custom_mixnet_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ pub const DEFAULT_IPR_ACK_KEY_FILENAME: &str = "aes128ctr_ipr_ack";
|
||||
pub const DEFAULT_IPR_REPLY_SURB_DB_FILENAME: &str = "ipr_persistent_reply_store.sqlite";
|
||||
pub const DEFAULT_IPR_GATEWAYS_DB_FILENAME: &str = "ipr_gateways_info_store.sqlite";
|
||||
|
||||
// Wireguard
|
||||
pub const DEFAULT_X25519_WG_DH_KEY_FILENAME: &str = "x25519_wg_dh";
|
||||
pub const DEFAULT_X25519_WG_PUBLIC_DH_KEY_FILENAME: &str = "x25519_wg_dh.pub";
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NymNodePaths {
|
||||
@@ -366,11 +370,23 @@ impl ExitGatewayPaths {
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WireguardPaths {
|
||||
// pub keys:
|
||||
pub private_diffie_hellman_key_file: PathBuf,
|
||||
pub public_diffie_hellman_key_file: PathBuf,
|
||||
}
|
||||
|
||||
impl WireguardPaths {
|
||||
pub fn new<P: AsRef<Path>>(_data_dir: P) -> Self {
|
||||
WireguardPaths {}
|
||||
pub fn new<P: AsRef<Path>>(data_dir: P) -> Self {
|
||||
let data_dir = data_dir.as_ref();
|
||||
WireguardPaths {
|
||||
private_diffie_hellman_key_file: data_dir.join(DEFAULT_X25519_WG_DH_KEY_FILENAME),
|
||||
public_diffie_hellman_key_file: data_dir.join(DEFAULT_X25519_WG_PUBLIC_DH_KEY_FILENAME),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn x25519_wireguard_storage_paths(&self) -> nym_pemstore::KeyPairPath {
|
||||
nym_pemstore::KeyPairPath::new(
|
||||
&self.private_diffie_hellman_key_file,
|
||||
&self.public_diffie_hellman_key_file,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,9 +115,9 @@ enabled = {{ wireguard.enabled }}
|
||||
# default: `0.0.0.0:51822`
|
||||
bind_address = '{{ wireguard.bind_address }}'
|
||||
|
||||
# Ip address of the private wireguard network.
|
||||
# default: `10.1.0.0`
|
||||
private_network_ip = '{{ wireguard.private_network_ip }}'
|
||||
# Private IP address of the wireguard gateway.
|
||||
# default: `10.1.0.1`
|
||||
private_ip = '{{ wireguard.private_ip }}'
|
||||
|
||||
# Port announced to external clients wishing to connect to the wireguard interface.
|
||||
# Useful in the instances where the node is behind a proxy.
|
||||
@@ -127,9 +127,12 @@ announced_port = {{ wireguard.announced_port }}
|
||||
# The maximum value for IPv4 is 32 and for IPv6 is 128
|
||||
private_network_prefix = {{ wireguard.private_network_prefix }}
|
||||
|
||||
# Paths for wireguard keys, client registries, etc.
|
||||
[wireguard.storage_paths]
|
||||
# currently empty
|
||||
# Path to file containing wireguard x25519 diffie hellman private key.
|
||||
private_diffie_hellman_key_file = '{{ wireguard.storage_paths.private_diffie_hellman_key_file }}'
|
||||
|
||||
# Path to file containing wireguard x25519 diffie hellman public key.
|
||||
public_diffie_hellman_key_file = '{{ wireguard.storage_paths.public_diffie_hellman_key_file }}'
|
||||
|
||||
|
||||
##### mixnode mode nym-node config options #####
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ 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_NETWORK_ARG: &str = "NYMNODE_WG_IP_NETWORK";
|
||||
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";
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ pub(crate) struct DisplayDetails {
|
||||
pub(crate) ed25519_identity_key: String,
|
||||
pub(crate) x25519_sphinx_key: String,
|
||||
pub(crate) x25519_noise_key: String,
|
||||
pub(crate) x25519_wireguard_key: String,
|
||||
|
||||
pub(crate) exit_network_requester_address: String,
|
||||
pub(crate) exit_ip_packet_router_address: String,
|
||||
@@ -139,6 +140,12 @@ pub(crate) fn load_x25519_noise_keypair(
|
||||
Ok(load_keypair(paths, "x25519-noise")?)
|
||||
}
|
||||
|
||||
pub(crate) fn load_x25519_wireguard_keypair(
|
||||
paths: KeyPairPath,
|
||||
) -> Result<x25519::KeyPair, NymNodeError> {
|
||||
Ok(load_keypair(paths, "x25519-wireguard")?)
|
||||
}
|
||||
|
||||
pub(crate) fn load_x25519_sphinx_public_key<P: AsRef<Path>>(
|
||||
path: P,
|
||||
) -> Result<x25519::PublicKey, NymNodeError> {
|
||||
|
||||
+69
-10
@@ -20,7 +20,9 @@ use nym_network_requester::{
|
||||
use nym_node::config::entry_gateway::ephemeral_entry_gateway_config;
|
||||
use nym_node::config::exit_gateway::ephemeral_exit_gateway_config;
|
||||
use nym_node::config::mixnode::ephemeral_mixnode_config;
|
||||
use nym_node::config::{Config, EntryGatewayConfig, ExitGatewayConfig, MixnodeConfig, NodeMode};
|
||||
use nym_node::config::{
|
||||
Config, EntryGatewayConfig, ExitGatewayConfig, MixnodeConfig, NodeMode, Wireguard,
|
||||
};
|
||||
use nym_node::error::{EntryGatewayError, ExitGatewayError, MixnodeError, NymNodeError};
|
||||
use nym_node_http_api::api::api_requests;
|
||||
use nym_node_http_api::api::api_requests::v1::node::models::NodeDescription;
|
||||
@@ -31,7 +33,7 @@ use nym_node_http_api::{NymNodeHTTPServer, NymNodeRouter};
|
||||
use nym_sphinx_acknowledgements::AckKey;
|
||||
use nym_sphinx_addressing::Recipient;
|
||||
use nym_task::{TaskClient, TaskManager};
|
||||
use nym_wireguard_types::registration::GatewayClientRegistry;
|
||||
use nym_wireguard_types::WireguardGatewayData;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use std::path::Path;
|
||||
@@ -39,6 +41,8 @@ use std::sync::Arc;
|
||||
use tracing::{debug, error, info, trace};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use self::helpers::load_x25519_wireguard_keypair;
|
||||
|
||||
pub mod bonding_information;
|
||||
pub mod description;
|
||||
pub mod helpers;
|
||||
@@ -63,7 +67,7 @@ impl MixnodeData {
|
||||
pub struct EntryGatewayData {
|
||||
mnemonic: Zeroizing<bip39::Mnemonic>,
|
||||
client_storage: nym_gateway::node::PersistentStorage,
|
||||
client_registry: Arc<GatewayClientRegistry>,
|
||||
wireguard_data: WireguardGatewayData,
|
||||
}
|
||||
|
||||
impl EntryGatewayData {
|
||||
@@ -81,7 +85,10 @@ impl EntryGatewayData {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn new(config: &EntryGatewayConfig) -> Result<EntryGatewayData, EntryGatewayError> {
|
||||
async fn new(
|
||||
config: &EntryGatewayConfig,
|
||||
wireguard_data: WireguardGatewayData,
|
||||
) -> Result<EntryGatewayData, EntryGatewayError> {
|
||||
Ok(EntryGatewayData {
|
||||
mnemonic: config.storage_paths.load_mnemonic_from_file()?,
|
||||
client_storage: nym_gateway::node::PersistentStorage::init(
|
||||
@@ -90,7 +97,7 @@ impl EntryGatewayData {
|
||||
)
|
||||
.await
|
||||
.map_err(nym_gateway::GatewayError::from)?,
|
||||
client_registry: Arc::new(Default::default()),
|
||||
wireguard_data: wireguard_data.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -244,6 +251,33 @@ impl ExitGatewayData {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WireguardData {
|
||||
x25519_wireguard_keys: Arc<x25519::KeyPair>,
|
||||
}
|
||||
|
||||
impl WireguardData {
|
||||
pub(crate) fn new(config: &Wireguard) -> Result<Self, NymNodeError> {
|
||||
Ok(WireguardData {
|
||||
x25519_wireguard_keys: Arc::new(load_x25519_wireguard_keypair(
|
||||
config.storage_paths.x25519_wireguard_storage_paths(),
|
||||
)?),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn initialise(config: &Wireguard) -> Result<(), ExitGatewayError> {
|
||||
let mut rng = OsRng;
|
||||
let x25519_keys = x25519::KeyPair::new(&mut rng);
|
||||
|
||||
store_keypair(
|
||||
&x25519_keys,
|
||||
config.storage_paths.x25519_wireguard_storage_paths(),
|
||||
"wg-x25519-dh",
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct NymNode {
|
||||
config: Config,
|
||||
description: NodeDescription,
|
||||
@@ -259,6 +293,8 @@ pub(crate) struct NymNode {
|
||||
#[allow(dead_code)]
|
||||
exit_gateway: ExitGatewayData,
|
||||
|
||||
wireguard: WireguardData,
|
||||
|
||||
ed25519_identity_keys: Arc<ed25519::KeyPair>,
|
||||
x25519_sphinx_keys: Arc<x25519::KeyPair>,
|
||||
|
||||
@@ -314,10 +350,18 @@ impl NymNode {
|
||||
ExitGatewayData::initialise(&config.exit_gateway, *ed25519_identity_keys.public_key())
|
||||
.await?;
|
||||
|
||||
// wireguard initialisation
|
||||
WireguardData::initialise(&config.wireguard)?;
|
||||
|
||||
config.save()
|
||||
}
|
||||
|
||||
pub(crate) async fn new(config: Config) -> Result<Self, NymNodeError> {
|
||||
let wireguard_data = WireguardData::new(&config.wireguard)?;
|
||||
let wireguard_gateway_data = WireguardGatewayData::new(
|
||||
config.wireguard.clone().into(),
|
||||
wireguard_data.x25519_wireguard_keys.clone(),
|
||||
);
|
||||
Ok(NymNode {
|
||||
ed25519_identity_keys: Arc::new(load_ed25519_identity_keypair(
|
||||
config.storage_paths.keys.ed25519_identity_storage_paths(),
|
||||
@@ -331,8 +375,10 @@ impl NymNode {
|
||||
description: load_node_description(&config.storage_paths.description)?,
|
||||
verloc_stats: Default::default(),
|
||||
mixnode: MixnodeData::new(&config.mixnode)?,
|
||||
entry_gateway: EntryGatewayData::new(&config.entry_gateway).await?,
|
||||
entry_gateway: EntryGatewayData::new(&config.entry_gateway, wireguard_gateway_data)
|
||||
.await?,
|
||||
exit_gateway: ExitGatewayData::new(&config.exit_gateway)?,
|
||||
wireguard: wireguard_data,
|
||||
config,
|
||||
})
|
||||
}
|
||||
@@ -353,6 +399,10 @@ impl NymNode {
|
||||
)
|
||||
}
|
||||
|
||||
fn x25519_wireguard_key(&self) -> &x25519::PublicKey {
|
||||
self.wireguard.x25519_wireguard_keys.public_key()
|
||||
}
|
||||
|
||||
pub(crate) fn display_details(&self) -> DisplayDetails {
|
||||
DisplayDetails {
|
||||
current_mode: self.config.mode,
|
||||
@@ -360,6 +410,7 @@ impl NymNode {
|
||||
ed25519_identity_key: self.ed25519_identity_key().to_base58_string(),
|
||||
x25519_sphinx_key: self.x25519_sphinx_key().to_base58_string(),
|
||||
x25519_noise_key: self.x25519_noise_key().to_base58_string(),
|
||||
x25519_wireguard_key: self.x25519_wireguard_key().to_base58_string(),
|
||||
exit_network_requester_address: self.exit_network_requester_address().to_string(),
|
||||
exit_ip_packet_router_address: self.exit_ip_packet_router_address().to_string(),
|
||||
}
|
||||
@@ -409,6 +460,10 @@ impl NymNode {
|
||||
|
||||
let config =
|
||||
ephemeral_entry_gateway_config(self.config.clone(), &self.entry_gateway.mnemonic)?;
|
||||
let wireguard_data = Arc::new(WireguardGatewayData::new(
|
||||
self.config.wireguard.clone().into(),
|
||||
self.wireguard.x25519_wireguard_keys.clone(),
|
||||
));
|
||||
let mut entry_gateway = Gateway::new_loaded(
|
||||
config,
|
||||
None,
|
||||
@@ -419,7 +474,7 @@ impl NymNode {
|
||||
);
|
||||
entry_gateway.disable_http_server();
|
||||
entry_gateway.set_task_client(task_client);
|
||||
entry_gateway.set_wireguard_client_registry(self.entry_gateway.client_registry.clone());
|
||||
entry_gateway.set_wireguard_data(wireguard_data);
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Err(err) = entry_gateway.run().await {
|
||||
@@ -434,6 +489,10 @@ impl NymNode {
|
||||
|
||||
let config =
|
||||
ephemeral_exit_gateway_config(self.config.clone(), &self.entry_gateway.mnemonic)?;
|
||||
let wireguard_data = Arc::new(WireguardGatewayData::new(
|
||||
self.config.wireguard.clone().into(),
|
||||
self.wireguard.x25519_wireguard_keys.clone(),
|
||||
));
|
||||
|
||||
let mut exit_gateway = Gateway::new_loaded(
|
||||
config.gateway,
|
||||
@@ -445,7 +504,7 @@ impl NymNode {
|
||||
);
|
||||
exit_gateway.disable_http_server();
|
||||
exit_gateway.set_task_client(task_client);
|
||||
exit_gateway.set_wireguard_client_registry(self.entry_gateway.client_registry.clone());
|
||||
exit_gateway.set_wireguard_data(wireguard_data);
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Err(err) = exit_gateway.run().await {
|
||||
@@ -517,12 +576,12 @@ impl NymNode {
|
||||
};
|
||||
|
||||
let wireguard_private_network = IpNetwork::new(
|
||||
self.config.wireguard.private_network_ip,
|
||||
self.config.wireguard.private_ip,
|
||||
self.config.wireguard.private_network_prefix,
|
||||
)?;
|
||||
|
||||
let wg_state = WireguardAppState::new(
|
||||
self.entry_gateway.client_registry.clone(),
|
||||
&self.entry_gateway.wireguard_data,
|
||||
Default::default(),
|
||||
self.config.wireguard.bind_address.port(),
|
||||
wireguard_private_network,
|
||||
|
||||
Reference in New Issue
Block a user