Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0be860268f | |||
| 11d6ee2fdb | |||
| d704c428fc | |||
| bca070c1bd | |||
| 226c040a13 | |||
| 3d2914b3e5 | |||
| 9b02de3e75 | |||
| f3d8aba82c | |||
| 72a4a26c40 | |||
| 5d9b5a0d70 | |||
| c070e4bfee | |||
| 8d5a41a790 | |||
| 039b05cf7e | |||
| 37b10b59aa | |||
| a9ede22bbd | |||
| b656003306 |
@@ -9,15 +9,16 @@ on:
|
||||
- 'gateway/**'
|
||||
- 'integrations/**'
|
||||
- 'mixnode/**'
|
||||
- 'sdk/rust/**'
|
||||
- 'sdk/lib/**'
|
||||
- 'service-providers/**'
|
||||
- 'nym-network-monitor/**'
|
||||
- 'nym-api/**'
|
||||
- 'nym-node/**'
|
||||
- 'nym-outfox/**'
|
||||
- 'nym-data-observatory/**'
|
||||
- 'nym-network-monitor/**'
|
||||
- 'nym-node/**'
|
||||
- 'nym-node-status-api/**'
|
||||
- 'nym-outfox/**'
|
||||
- 'nym-validator-rewarder/**'
|
||||
- 'sdk/lib/**'
|
||||
- 'sdk/rust/**'
|
||||
- 'service-providers/**'
|
||||
- 'tools/**'
|
||||
- 'wasm/**'
|
||||
- 'Cargo.toml'
|
||||
|
||||
@@ -4,6 +4,11 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.14-crunch-patched] (2024-12-17)
|
||||
|
||||
- Fixes an issue to allow previously registred clients to connect to latest nym-nodes
|
||||
- Fixes compatibility issues between nym-nodes and older clients
|
||||
|
||||
## [2024.14-crunch] (2024-12-11)
|
||||
|
||||
- Merge/release/2024.14-crunch ([#5242])
|
||||
|
||||
Generated
+617
-291
File diff suppressed because it is too large
Load Diff
+27
-27
@@ -128,7 +128,7 @@ members = [
|
||||
"nym-node-status-api/nym-node-status-client",
|
||||
"nym-outfox",
|
||||
"nym-validator-rewarder",
|
||||
# "tools/echo-server",
|
||||
"tools/echo-server",
|
||||
"tools/internal/ssl-inject",
|
||||
# "tools/internal/sdk-version-bump",
|
||||
"tools/internal/testnet-manager",
|
||||
@@ -149,7 +149,7 @@ members = [
|
||||
"tools/internal/testnet-manager",
|
||||
"tools/internal/testnet-manager/dkg-bypass-contract",
|
||||
"common/verloc",
|
||||
"tools/internal/mixnet-connectivity-check", "tools/internal/mixnet-check-all-gateways",
|
||||
"tools/internal/mixnet-connectivity-check",
|
||||
]
|
||||
|
||||
default-members = [
|
||||
@@ -193,9 +193,9 @@ aes = "0.8.1"
|
||||
aes-gcm = "0.10.1"
|
||||
aes-gcm-siv = "0.11.1"
|
||||
aead = "0.5.2"
|
||||
anyhow = "1.0.90"
|
||||
anyhow = "1.0.95"
|
||||
argon2 = "0.5.0"
|
||||
async-trait = "0.1.83"
|
||||
async-trait = "0.1.84"
|
||||
axum-client-ip = "0.6.1"
|
||||
axum = "0.7.5"
|
||||
axum-extra = "0.9.4"
|
||||
@@ -204,7 +204,7 @@ bincode = "1.3.3"
|
||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||
bit-vec = "0.7.0" # can we unify those?
|
||||
bitvec = "1.0.0"
|
||||
blake3 = "1.5.4"
|
||||
blake3 = "1.5.5"
|
||||
bloomfilter = "1.0.14"
|
||||
bs58 = "0.5.1"
|
||||
bytecodec = "0.4.15"
|
||||
@@ -214,20 +214,20 @@ celes = "2.4.0"
|
||||
cfg-if = "1.0.0"
|
||||
chacha20 = "0.9.0"
|
||||
chacha20poly1305 = "0.10.1"
|
||||
chrono = "0.4.31"
|
||||
chrono = "0.4.39"
|
||||
cipher = "0.4.3"
|
||||
clap = "4.5.20"
|
||||
clap = "4.5.23"
|
||||
clap_complete = "4.5"
|
||||
clap_complete_fig = "4.5"
|
||||
colored = "2.0"
|
||||
comfy-table = "7.1.1"
|
||||
console = "0.15.8"
|
||||
comfy-table = "7.1.3"
|
||||
console = "0.15.10"
|
||||
console-subscriber = "0.1.1"
|
||||
console_error_panic_hook = "0.1"
|
||||
const-str = "0.5.6"
|
||||
const_format = "0.2.33"
|
||||
const_format = "0.2.34"
|
||||
criterion = "0.4"
|
||||
csv = "1.3.0"
|
||||
csv = "1.3.1"
|
||||
ctr = "0.9.1"
|
||||
cupid = "0.6.1"
|
||||
curve25519-dalek = "4.1"
|
||||
@@ -244,7 +244,7 @@ etherparse = "0.13.0"
|
||||
envy = "0.4"
|
||||
eyre = "0.6.9"
|
||||
fastrand = "2.1.1"
|
||||
flate2 = "1.0.34"
|
||||
flate2 = "1.0.35"
|
||||
futures = "0.3.28"
|
||||
futures-util = "0.3"
|
||||
generic-array = "0.14.7"
|
||||
@@ -264,7 +264,7 @@ humantime-serde = "1.1.1"
|
||||
human-repr = "1.1.0"
|
||||
hyper = "1.4.1"
|
||||
hyper-util = "0.1"
|
||||
indicatif = "0.17.8"
|
||||
indicatif = "0.17.9"
|
||||
inquire = "0.6.2"
|
||||
ip_network = "0.4.1"
|
||||
ipnetwork = "0.20"
|
||||
@@ -289,7 +289,7 @@ parking_lot = "0.12.3"
|
||||
pem = "0.8"
|
||||
petgraph = "0.6.5"
|
||||
pin-project = "1.1"
|
||||
pin-project-lite = "0.2.14"
|
||||
pin-project-lite = "0.2.15"
|
||||
pretty_env_logger = "0.4.0"
|
||||
publicsuffix = "2.2.3"
|
||||
quote = "1"
|
||||
@@ -307,11 +307,11 @@ rocket_cors = "0.6.0"
|
||||
rocket_okapi = "0.8.0"
|
||||
safer-ffi = "0.1.13"
|
||||
schemars = "0.8.21"
|
||||
semver = "1.0.23"
|
||||
serde = "1.0.211"
|
||||
semver = "1.0.24"
|
||||
serde = "1.0.217"
|
||||
serde_bytes = "0.11.15"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0.132"
|
||||
serde_json = "1.0.134"
|
||||
serde_json_path = "0.7.1"
|
||||
serde_repr = "0.1"
|
||||
serde_with = "3.9.0"
|
||||
@@ -326,22 +326,22 @@ subtle-encoding = "0.5"
|
||||
syn = "1"
|
||||
sysinfo = "0.30.13"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.42"
|
||||
tar = "0.4.43"
|
||||
tempfile = "3.14"
|
||||
thiserror = "1.0.64"
|
||||
time = "0.3.30"
|
||||
time = "0.3.37"
|
||||
tokio = "1.39"
|
||||
tokio-stream = "0.1.16"
|
||||
tokio-stream = "0.1.17"
|
||||
tokio-test = "0.4.4"
|
||||
tokio-tun = "0.11.5"
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tokio-util = "0.7.12"
|
||||
toml = "0.8.14"
|
||||
tokio-util = "0.7.13"
|
||||
toml = "0.8.19"
|
||||
tower = "0.4.13"
|
||||
tower-http = "0.5.2"
|
||||
tracing = "0.1.37"
|
||||
tracing = "0.1.41"
|
||||
tracing-opentelemetry = "0.19.0"
|
||||
tracing-subscriber = "0.3.16"
|
||||
tracing-subscriber = "0.3.19"
|
||||
tracing-tree = "0.2.2"
|
||||
tracing-log = "0.2"
|
||||
ts-rs = "10.0.0"
|
||||
@@ -353,7 +353,7 @@ utoipauto = "0.2"
|
||||
uuid = "*"
|
||||
vergen = { version = "=8.3.1", default-features = false }
|
||||
walkdir = "2"
|
||||
wasm-bindgen-test = "0.3.43"
|
||||
wasm-bindgen-test = "0.3.45"
|
||||
x25519-dalek = "2.0.0"
|
||||
zeroize = "1.6.0"
|
||||
|
||||
@@ -402,11 +402,11 @@ gloo-net = "0.5.0"
|
||||
# this is blocked until the upstream removes outdates `wasm_bindgen` feature usage
|
||||
# indexed_db_futures = "0.4.1"
|
||||
indexed_db_futures = { git = "https://github.com/TiemenSch/rust-indexed-db", branch = "update-uuid" }
|
||||
js-sys = "0.3.70"
|
||||
js-sys = "0.3.76"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
tsify = "0.4.5"
|
||||
wasm-bindgen = "0.2.99"
|
||||
wasm-bindgen-futures = "0.4.45"
|
||||
wasm-bindgen-futures = "0.4.49"
|
||||
wasmtimer = "0.2.0"
|
||||
web-sys = "0.3.72"
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr
|
||||
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
|
||||
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
|
||||
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||
* `nym-cli` - a tool for interacting with the network from the CLI.
|
||||
* `nym-cli` - a tool for interacting with the network from the CLI.
|
||||
<!-- coming soon
|
||||
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||
-->
|
||||
@@ -42,10 +42,10 @@ client ───► Gateway ──┘ mix │ mix ┌─►mix ───►
|
||||
|
||||
References for developers:
|
||||
|
||||
* [Dev Docs](https://nymtech.net/docs/developers)
|
||||
* [SDKs](https://nymtech.net/docs/developers/rust)
|
||||
* [Network Docs](https://nymtech.net/docs/network)
|
||||
* [Release Cycle - git flow](https://nymtech.net/docs/operators/release-cycle)
|
||||
* [Dev Docs](https://nym.com/docs/developers)
|
||||
* [SDKs](https://nym.com/docs/developers/rust)
|
||||
* [Network Docs](https://nym.com/docs/network)
|
||||
* [Release Cycle - git flow](https://nym.com/docs/operators/release-cycle)
|
||||
|
||||
### Developer chat
|
||||
|
||||
@@ -66,4 +66,4 @@ As a general approach, licensing is as follows this pattern:
|
||||
- libraries and components are Apache 2.0 or MIT
|
||||
- documentation is Apache 2.0 or CC0-1.0
|
||||
|
||||
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
|
||||
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nym.com/terms-and-conditions/operators/v1.0.0).
|
||||
|
||||
@@ -8,6 +8,13 @@ license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
nym-client-core-config-types = { path = "./config-types", features = [
|
||||
"disk-persistence",
|
||||
] }
|
||||
toml.workspace = true
|
||||
uneval = "0.2.4"
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
@@ -43,6 +50,7 @@ nym-gateway-requests = { path = "../gateway-requests" }
|
||||
nym-metrics = { path = "../nym-metrics" }
|
||||
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
nym-sphinx-params = { path = "../nymsphinx/params" }
|
||||
nym-statistics-common = { path = "../statistics" }
|
||||
nym-pemstore = { path = "../pemstore" }
|
||||
nym-topology = { path = "../topology", features = ["persistence"] }
|
||||
@@ -117,12 +125,15 @@ features = ["wasm-bindgen"]
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = { workspace = true }
|
||||
toml.workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["enable-cfg"]
|
||||
cli = ["clap", "comfy-table"]
|
||||
fs-credentials-storage = ["nym-credential-storage/persistent-storage"]
|
||||
fs-surb-storage = ["nym-client-core-surb-storage/fs-surb-storage"]
|
||||
fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"]
|
||||
wasm = ["nym-gateway-client/wasm"]
|
||||
metrics-server = []
|
||||
|
||||
enable-cfg = []
|
||||
@@ -0,0 +1,109 @@
|
||||
use nym_client_core_config_types::Config;
|
||||
|
||||
use std::io::{BufWriter, Write};
|
||||
|
||||
fn main() {
|
||||
write_conditional_default();
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
const DEFAULT_CONFIG_FILE_NAME: &str = "nymvpn-config.toml";
|
||||
|
||||
const CONFIG_INIT_FN_PREAMBLE: &[u8] = br#"
|
||||
pub fn new_bootstrapped<S1, S2>(id: S1, version: S2) -> Config
|
||||
where
|
||||
S1: Into<String>,
|
||||
S2: Into<String>,
|
||||
{
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
|
||||
|
||||
let mut cfg: Config = "#;
|
||||
|
||||
const CONFIG_INIT_FN_EPILOGUE: &[u8] = br#";
|
||||
cfg.client.id = id.into();
|
||||
cfg.client.version = version.into();
|
||||
cfg
|
||||
}"#;
|
||||
|
||||
// #[cfg(feature = "enable-cfg")]
|
||||
// const CUSTOM_BREAK: &[u8] = br#"
|
||||
// #[cfg(feature="enable-cfg")]
|
||||
// "#;
|
||||
|
||||
// #[cfg(not(feature = "enable-cfg"))]
|
||||
// const DEFAULT_BREAK: &[u8] = br#"
|
||||
// #[cfg(not(feature="enable-cfg"))]
|
||||
// "#;
|
||||
|
||||
// const CONFIG_INIT_FN_PREAMBLE: &[u8] = br#"
|
||||
// impl Default for BaseClientConfig {
|
||||
// fn default() -> Self {
|
||||
// use config_types::Keys;
|
||||
|
||||
// Self("#;
|
||||
|
||||
// const DEFAULT_CONFIG_EPILOGUE: &[u8] = br#"
|
||||
// )
|
||||
// }
|
||||
// }"#;
|
||||
|
||||
// #[cfg(feature = "enable-cfg")]
|
||||
// const CUSTOM_BREAK: &[u8] = br#"
|
||||
// #[cfg(feature="enable-cfg")]
|
||||
// "#;
|
||||
|
||||
// #[cfg(not(feature = "enable-cfg"))]
|
||||
// const DEFAULT_BREAK: &[u8] = br#"
|
||||
// #[cfg(not(feature="enable-cfg"))]
|
||||
// "#;
|
||||
|
||||
fn write_conditional_default() {
|
||||
// creating a string with the values from our default Config object
|
||||
let mut array_string = BufWriter::new(Vec::new());
|
||||
array_string.write(CONFIG_INIT_FN_PREAMBLE).unwrap();
|
||||
|
||||
#[cfg(feature = "enable-cfg")]
|
||||
write_custom_config(&mut array_string);
|
||||
|
||||
#[cfg(not(feature = "enable-cfg"))]
|
||||
{
|
||||
let default_config = Config::new("", "");
|
||||
uneval::write(default_config, &mut array_string).unwrap();
|
||||
}
|
||||
|
||||
array_string.write(CONFIG_INIT_FN_EPILOGUE).unwrap();
|
||||
|
||||
// write the string to a file. OUT_DIR environment variable is defined by cargo
|
||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||
let dest_path = std::path::Path::new(&out_dir).join("default.rs");
|
||||
|
||||
let out_str = String::from_utf8(array_string.into_inner().unwrap()).unwrap();
|
||||
std::fs::write(&dest_path, out_str).unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable-cfg")]
|
||||
pub(crate) fn write_custom_config(out: impl Write) {
|
||||
// allow the name of the file we draw hardcoded values from to be set by an
|
||||
// environment variable at compile time.
|
||||
let cfg_file_name = option_env!("NYMVPN_CONFIG_PATH").unwrap_or(DEFAULT_CONFIG_FILE_NAME);
|
||||
|
||||
// set reasons to rebuild
|
||||
println!("cargo:rerun-if-changed={cfg_file_name}");
|
||||
println!("cargo:rerun-if-env-changed=NYMVPN_CONFIG_PATH");
|
||||
|
||||
let path = std::path::PathBuf::from(cfg_file_name);
|
||||
let cfg_file_path = if path.is_absolute() {
|
||||
path
|
||||
} else {
|
||||
let workspace_path = std::env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
std::path::Path::new(&workspace_path).join(cfg_file_name)
|
||||
};
|
||||
|
||||
let config_str: String = std::fs::read_to_string(cfg_file_path).unwrap();
|
||||
let config: Config = toml::from_str(&config_str).unwrap();
|
||||
|
||||
uneval::write(config, out).unwrap();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
[client]
|
||||
version = ""
|
||||
id = ""
|
||||
disabled_credentials_mode = true
|
||||
nyxd_urls = ["https://rpc.nymtech.net/"]
|
||||
nym_api_urls = ["https://validator.nymtech.net/api/"]
|
||||
|
||||
[debug.traffic]
|
||||
average_packet_delay = "50ms"
|
||||
message_sending_average_delay = "20ms"
|
||||
disable_main_poisson_packet_distribution = false
|
||||
deterministic_route_selection = false
|
||||
primary_packet_size = "regular"
|
||||
packet_type = "mix"
|
||||
|
||||
[debug.cover_traffic]
|
||||
loop_cover_traffic_average_delay = "200ms"
|
||||
cover_traffic_primary_size_ratio = 0.7
|
||||
disable_loop_cover_traffic_stream = false
|
||||
|
||||
[debug.gateway_connection]
|
||||
gateway_response_timeout = "5m"
|
||||
|
||||
[debug.acknowledgements]
|
||||
average_ack_delay = "50ms"
|
||||
ack_wait_multiplier = 1.5
|
||||
ack_wait_addition = "1s 500ms"
|
||||
|
||||
[debug.topology]
|
||||
topology_refresh_rate = "5m"
|
||||
topology_resolution_timeout = "5s"
|
||||
disable_refreshing = false
|
||||
max_startup_gateway_waiting_period = "1h 10m"
|
||||
topology_structure = "NymApi"
|
||||
minimum_mixnode_performance = 50
|
||||
minimum_gateway_performance = 50
|
||||
use_extended_topology = false
|
||||
ignore_egress_epoch_role = false
|
||||
|
||||
[debug.reply_surbs]
|
||||
minimum_reply_surb_storage_threshold = 10
|
||||
maximum_reply_surb_storage_threshold = 200
|
||||
minimum_reply_surb_request_size = 10
|
||||
maximum_reply_surb_request_size = 100
|
||||
maximum_allowed_reply_surb_request_size = 500
|
||||
maximum_reply_surb_rerequest_waiting_period = "10s"
|
||||
maximum_reply_surb_drop_waiting_period = "5m"
|
||||
maximum_reply_surb_age = "12h"
|
||||
maximum_reply_key_age = "1day"
|
||||
|
||||
[debug.stats_reporting]
|
||||
enabled = true
|
||||
reporting_interval = "5m"
|
||||
@@ -7,3 +7,40 @@ pub use nym_client_core_config_types::old::{
|
||||
old_config_v1_1_33,
|
||||
};
|
||||
pub use nym_client_core_config_types::*;
|
||||
|
||||
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/default.rs"));
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn dump_default() {
|
||||
let cfg = Config::new("","");
|
||||
println!("{}", toml::to_string(&cfg).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bootstrapped_config() {
|
||||
#[cfg(not(feature = "enable-cfg"))]
|
||||
{
|
||||
let config = new_bootstrapped("id1", "v0.0.0");
|
||||
assert_eq!(config.client.id, "id1");
|
||||
assert_eq!(config.client.version, "v0.0.0");
|
||||
assert_eq!(config.client.disabled_credentials_mode, true);
|
||||
|
||||
assert_eq!(config.debug.topology.use_extended_topology, false);
|
||||
assert_eq!(config.debug.stats_reporting.enabled, true);
|
||||
}
|
||||
#[cfg(feature = "enable-cfg")]
|
||||
{
|
||||
let config = new_bootstrapped("id2", "v0.0.0-beta");
|
||||
assert_eq!(config.client.id, "id2");
|
||||
assert_eq!(config.client.version, "v0.0.0-beta");
|
||||
assert_eq!(config.client.disabled_credentials_mode, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ license.workspace = true
|
||||
[dependencies]
|
||||
bincode = { workspace = true }
|
||||
defguard_wireguard_rs = { workspace = true }
|
||||
log = { workspace = true }
|
||||
sqlx = { workspace = true, features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
ALTER TABLE message_store
|
||||
ADD COLUMN timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
@@ -2,9 +2,11 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::models::StoredMessage;
|
||||
use time::OffsetDateTime;
|
||||
use tracing::debug;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct InboxManager {
|
||||
pub struct InboxManager {
|
||||
connection_pool: sqlx::SqlitePool,
|
||||
/// Maximum number of messages that can be obtained from the database per operation.
|
||||
/// It is used to prevent out of memory errors in the case of client receiving a lot of data while
|
||||
@@ -71,44 +73,22 @@ impl InboxManager {
|
||||
// get 1 additional message to check whether there will be more to grab
|
||||
// next time
|
||||
let limit = self.retrieval_limit + 1;
|
||||
let mut res = if let Some(start_after) = start_after {
|
||||
sqlx::query_as!(
|
||||
StoredMessage,
|
||||
r#"
|
||||
SELECT
|
||||
id as "id!",
|
||||
client_address_bs58 as "client_address_bs58!",
|
||||
content as "content!"
|
||||
FROM message_store
|
||||
WHERE client_address_bs58 = ? AND id > ?
|
||||
ORDER BY id ASC
|
||||
LIMIT ?;
|
||||
"#,
|
||||
client_address_bs58,
|
||||
start_after,
|
||||
limit
|
||||
)
|
||||
.fetch_all(&self.connection_pool)
|
||||
.await?
|
||||
} else {
|
||||
sqlx::query_as!(
|
||||
StoredMessage,
|
||||
r#"
|
||||
SELECT
|
||||
id as "id!",
|
||||
client_address_bs58 as "client_address_bs58!",
|
||||
content as "content!"
|
||||
FROM message_store
|
||||
WHERE client_address_bs58 = ?
|
||||
ORDER BY id ASC
|
||||
LIMIT ?;
|
||||
"#,
|
||||
client_address_bs58,
|
||||
limit
|
||||
)
|
||||
.fetch_all(&self.connection_pool)
|
||||
.await?
|
||||
};
|
||||
let start_after = start_after.unwrap_or(-1);
|
||||
|
||||
let mut res: Vec<StoredMessage> = sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, client_address_bs58, content, timestamp
|
||||
FROM message_store
|
||||
WHERE client_address_bs58 = ? AND id > ?
|
||||
ORDER BY id ASC
|
||||
LIMIT ?;
|
||||
"#,
|
||||
)
|
||||
.bind(client_address_bs58)
|
||||
.bind(start_after)
|
||||
.bind(limit)
|
||||
.fetch_all(&self.connection_pool)
|
||||
.await?;
|
||||
|
||||
if res.len() > self.retrieval_limit as usize {
|
||||
res.truncate(self.retrieval_limit as usize);
|
||||
@@ -146,4 +126,13 @@ impl InboxManager {
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove_stale(&self, cutoff: OffsetDateTime) -> Result<(), sqlx::Error> {
|
||||
let affected = sqlx::query!("DELETE FROM message_store WHERE timestamp < ?", cutoff)
|
||||
.execute(&self.connection_pool)
|
||||
.await?
|
||||
.rows_affected();
|
||||
debug!("Removed {affected} stale messages");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use bandwidth::BandwidthManager;
|
||||
use clients::{ClientManager, ClientType};
|
||||
use inboxes::InboxManager;
|
||||
use models::{
|
||||
Client, PersistedBandwidth, PersistedSharedKeys, RedemptionProposal, StoredMessage,
|
||||
VerifiedTicket, WireguardPeer,
|
||||
@@ -31,6 +30,7 @@ mod tickets;
|
||||
mod wireguard_peers;
|
||||
|
||||
pub use error::GatewayStorageError;
|
||||
pub use inboxes::InboxManager;
|
||||
|
||||
// note that clone here is fine as upon cloning the same underlying pool will be used
|
||||
#[derive(Clone)]
|
||||
@@ -53,7 +53,7 @@ impl GatewayStorage {
|
||||
&self.shared_key_manager
|
||||
}
|
||||
|
||||
pub(crate) fn inbox_manager(&self) -> &InboxManager {
|
||||
pub fn inbox_manager(&self) -> &InboxManager {
|
||||
&self.inbox_manager
|
||||
}
|
||||
|
||||
|
||||
@@ -48,11 +48,13 @@ impl TryFrom<PersistedSharedKeys> for SharedGatewayKey {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromRow)]
|
||||
pub struct StoredMessage {
|
||||
pub id: i64,
|
||||
#[allow(dead_code)]
|
||||
pub client_address_bs58: String,
|
||||
pub content: Vec<u8>,
|
||||
pub timestamp: OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, FromRow)]
|
||||
|
||||
@@ -59,30 +59,30 @@ pub enum InvalidPacketSize {
|
||||
pub enum PacketSize {
|
||||
// for example instant messaging use case
|
||||
#[default]
|
||||
#[serde(rename = "regular")]
|
||||
#[serde(alias = "regular")]
|
||||
RegularPacket = 1,
|
||||
|
||||
// for sending SURB-ACKs
|
||||
#[serde(rename = "ack")]
|
||||
#[serde(alias = "ack")]
|
||||
AckPacket = 2,
|
||||
|
||||
// for example for streaming fast and furious in uncompressed 10bit 4K HDR quality
|
||||
#[serde(rename = "extended32")]
|
||||
#[serde(alias = "extended32")]
|
||||
ExtendedPacket32 = 3,
|
||||
|
||||
// for example for streaming fast and furious in heavily compressed lossy RealPlayer quality
|
||||
#[serde(rename = "extended8")]
|
||||
#[serde(alias = "extended8")]
|
||||
ExtendedPacket8 = 4,
|
||||
|
||||
// for example for streaming fast and furious in compressed XviD quality
|
||||
#[serde(rename = "extended16")]
|
||||
#[serde(alias = "extended16")]
|
||||
ExtendedPacket16 = 5,
|
||||
|
||||
#[serde(rename = "outfox_regular")]
|
||||
#[serde(alias = "outfox_regular")]
|
||||
OutfoxRegularPacket = 6,
|
||||
|
||||
// for sending SURB-ACKs
|
||||
#[serde(rename = "outfox_ack")]
|
||||
#[serde(alias = "outfox_ack")]
|
||||
OutfoxAckPacket = 7,
|
||||
}
|
||||
|
||||
|
||||
@@ -23,17 +23,17 @@ pub enum PacketType {
|
||||
/// Represents 'normal' packet sent through the network that should be delayed by an appropriate
|
||||
/// value at each hop.
|
||||
#[default]
|
||||
#[serde(rename = "mix")]
|
||||
#[serde(alias = "mix")]
|
||||
#[serde(alias = "sphinx")]
|
||||
Mix = 0,
|
||||
|
||||
/// Represents a packet that should be sent through the network as fast as possible.
|
||||
#[deprecated]
|
||||
#[serde(rename = "unsupported-mix-vpn")]
|
||||
#[serde(alias = "unsupported-mix-vpn")]
|
||||
Vpn = 1,
|
||||
|
||||
/// Abusing this to add Outfox support
|
||||
#[serde(rename = "outfox")]
|
||||
#[serde(alias = "outfox")]
|
||||
Outfox = 2,
|
||||
}
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@ edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.11.3"
|
||||
env_logger = "0.11.6"
|
||||
log.workspace = true
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This is v2 of the nym docs, condensed from various mdbooks projects that we had previously.
|
||||
|
||||
These docs are hosted at [nymtech.net/docs](www.nymtech.net/docs).
|
||||
These docs are hosted at [nym.com/docs](https://nym.com/docs).
|
||||
|
||||
## Doc projects
|
||||
`docs/pages/` contains several subdirs, each hosting a subsection of the docs:
|
||||
@@ -11,6 +11,7 @@ These docs are hosted at [nymtech.net/docs](www.nymtech.net/docs).
|
||||
* `operators` contains node setup and maintenance guides.
|
||||
|
||||
## Local development
|
||||
|
||||
### Dependencies
|
||||
Our `prebuild` script relies on the following:
|
||||
- `python`
|
||||
@@ -54,7 +55,7 @@ This is a monorepo and components that make up Nym as a system are licensed indi
|
||||
|
||||
As a general approach, licensing is as follows this pattern:
|
||||
|
||||
* <p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://nymtech.net/docs">Nym Documentation</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://nymtech.net">Nym Technologies</a> is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1"></a></p>
|
||||
* <p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://nym.com/docs">Nym Documentation</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://nym.com">Nym Technologies</a> is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1"></a></p>
|
||||
|
||||
* Nym applications and binaries are [GPL-3.0-only](https://www.gnu.org/licenses/)
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ export const LandingPage = () => {
|
||||
{square.description}
|
||||
</Typography>
|
||||
|
||||
<Typography sx={{ color: "#ff6600", fontWeight: 600 }}>
|
||||
<Typography sx={{ color: "#14E76F", fontWeight: 600 }}>
|
||||
Open
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -9,7 +9,7 @@ import Stack from "@mui/material/Stack";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import type { SetupMixFetchOps } from "@nymproject/mix-fetch-full-fat";
|
||||
|
||||
const defaultUrl = "https://nymtech.net/favicon.svg";
|
||||
const defaultUrl = "https://nym.com/favicon.svg";
|
||||
const args = { mode: "unsafe-ignore-cors" };
|
||||
|
||||
const mixFetchOptions: SetupMixFetchOps = {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { MyTab } from 'components/generic-tabs.tsx';
|
||||
import { Tabs } from 'nextra/components';
|
||||
|
||||
### VPS Hardware Specs
|
||||
|
||||
You will need to rent a VPS to run your node on. One key reason for this is that your node **must be able to send TCP data using both IPv4 and IPv6** (as other nodes you talk to may use either protocol). Therefore you will need a server with static IPv4 and IPv6!
|
||||
|
||||
Tor community created a very helpful table called [*Good Bad ISPs*](https://community.torproject.org/relay/community-resources/good-bad-isps/), you can use that one as a guideline for your choice of ISP for your VPS.
|
||||
|
||||
**Update:** Nym community started an ISP table called [*Where to host your nym node?*](../../community-counsel/isp-list.mdx), check it out and add your findings!
|
||||
|
||||
<div>
|
||||
<Tabs items={[
|
||||
<code>nym-node</code>,
|
||||
<code>validator</code>,
|
||||
]} defaultIndex="0">
|
||||
<MyTab>
|
||||
#### `nym-node`
|
||||
Before we conclude the testing with exact results, these are the rough specs:
|
||||
|
||||
| **Hardware** | **Minimum Specification** |
|
||||
| :--- | ---: |
|
||||
| CPU Cores | 4 |
|
||||
| Memory | 8 GB RAM |
|
||||
| Storage | 80 GB |
|
||||
| Connectivity | IPv4, IPv6, TCP/IP, UDP |
|
||||
| Bandwidth | > 1Tb |
|
||||
| Port speed | 1Gbps |
|
||||
|
||||
</MyTab>
|
||||
<MyTab>
|
||||
#### Nyx validator
|
||||
|
||||
The specification mentioned below is for running a full node alongside the nym-api. It is recommended to run `nym-api` and a full Nyx node on the same machine for optimum performance.
|
||||
|
||||
Bear in mind that credential signing is primarily CPU-bound, so choose the fastest CPU available to you.
|
||||
|
||||
##### Minimum Requirements
|
||||
|
||||
| Hardware | **Minimum Specification** |
|
||||
|----------|--------------------------------------------|
|
||||
| CPU | 8-cores, 2.8GHz base clock speed or higher |
|
||||
| RAM | 16GB DDR4+ |
|
||||
| Disk | 500 GiB+ NVMe SSD |
|
||||
|
||||
##### Recommended Requirements
|
||||
|
||||
| Hardware | **Minimum Specification** |
|
||||
|----------|---------------------------------------------|
|
||||
| CPU | 16-cores, 2.8GHz base clock speed or higher |
|
||||
| RAM | 32GB DDR4+ |
|
||||
| Disk | 1 TiB+ NVMe SSD |
|
||||
|
||||
</MyTab>
|
||||
</Tabs>
|
||||
</div>
|
||||
+1
-1
@@ -1 +1 @@
|
||||
804_560_131
|
||||
805_903_308
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1_020_023
|
||||
1_022_821
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
402_280_065
|
||||
402_951_654
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
| **Item** | **Description** | **Amount in NYM** |
|
||||
|:-------------------|:------------------------------------------------------|--------------------:|
|
||||
| Total Supply | Maximum amount of NYM token in existence | 1_000_000_000 |
|
||||
| Mixmining Reserve | Tokens releasing for operators rewards | 195_439_368 |
|
||||
| Mixmining Reserve | Tokens releasing for operators rewards | 194_096_191 |
|
||||
| Vesting Tokens | Tokens locked outside of cicrulation for future claim | 500 |
|
||||
| Circulating Supply | Amount of unlocked tokens | 804_560_131 |
|
||||
| Stake Saturation | Optimal size of node self-bond + delegation | 1_020_023 |
|
||||
| Circulating Supply | Amount of unlocked tokens | 805_903_308 |
|
||||
| Stake Saturation | Optimal size of node self-bond + delegation | 1_022_821 |
|
||||
|
||||
@@ -1 +1 @@
|
||||
Monday, December 23rd 2024, 11:36:26 UTC
|
||||
Wednesday, January 8th 2025, 15:01:28 UTC
|
||||
|
||||
@@ -2,5 +2,5 @@ import { Callout } from 'nextra/components'
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
Our documentation often refer to syntax annotated in `<>` brackets. We use this expression for variables that are unique to each user (like path, local moniker, versions etcetra).
|
||||
Any syntax in `<>` brackets needs to be substituted with your correct name or version, without the `<>` brackets. If you are unsure, please check our table of essential [parameters and variables](https://nymtech.net/docs/operators/variables.html).
|
||||
Any syntax in `<>` brackets needs to be substituted with your correct name or version, without the `<>` brackets. If you are unsure, please check our table of essential [parameters and variables](https://nym.com/docs/operators/variables).
|
||||
</Callout>
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# NymVPN alpha
|
||||
|
||||
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/897010658?h=1f55870fe6&badge=0&autopause=0&player_id=0&app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="NYMVPN alpha demo 37C3"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
|
||||
|
||||
```admonish tip title="web3summit testing"
|
||||
**If you testing NymVPN CLI on Web3 Summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/).**
|
||||
```
|
||||
|
||||
**NymVPN alpha** is a client that uses [Nym Mixnet](https://nymtech.net) to anonymise all of a user's internet traffic through either a 5-hop mixnet (for a full network privacy) or the faster 2-hop decentralised VPN (with some extra features).
|
||||
|
||||
|
||||
**You are invited to take part in the alpha testing** of this new application. Register for private testing round at [nymvpn.com](https://nymvpn.com/en), that will grant you access to the [download page](https://nymvpn.com/download). Visit [NymVPN Support & FAQ](https://nymvpn.com/en/support) or join the [NymVPN matrix channel](https://matrix.to/#/#NymVPN:nymtech.chat) if you have any questions, comments or blockers.
|
||||
|
||||
Checkout the [release page](https://github.com/nymtech/nym-vpn-client/releases) for available binaries.
|
||||
|
||||
*NOTE: NymVPN alpha is experimental software for testing purposes only.*
|
||||
|
||||
|
||||
## NymVPN Overview
|
||||
|
||||
To understand what's under the hood of NymVPN and the mixnet, we recommend interested developers to begin with [Nym network overview](https://nymtech.net/docs/architecture/network-overview.html) and the [Mixnet traffic flow](https://nymtech.net/docs/architecture/traffic-flow.html) pages.
|
||||
|
||||
The default setup of NymVPN is to run in 5-hop mode (mixnet):
|
||||
|
||||
```
|
||||
┌─►mix──┐ mix mix
|
||||
│ │
|
||||
Entry │ │ Exit
|
||||
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
|
||||
│ │
|
||||
│ │
|
||||
mix └─►mix──┘ mix
|
||||
```
|
||||
|
||||
Users can switch to 2-hop only mode, which is a faster but less private option. In this mode traffic is only sent between the two Gateways, and is not passed between Mix Nodes. It uses Mixnet Sphinx packets with shorter, fixed routes, which improve latency, but doesn't offer the same level of protection as the 5 hop mode.
|
||||
<!-- TO BE IMPLEMENTED:
|
||||
Users can switch to 2-hop only mode, which is a faster but less private option. In this mode traffic is only sent between the two Gateways, and is not passed between Mix Nodes. The client than use two wireguard tunnels with the entry and exit gateway, the Exit Gateway one being tunnelled itself through the entry gateway tunnel. NymVPN uses Mullvad libraries for wrapping `wireguard-go` and to setup local routing rules to route all traffic to the TUN virtual network device.
|
||||
-->
|
||||
@@ -1,142 +0,0 @@
|
||||
# NymVPN alpha CLI Guide
|
||||
|
||||
```admonish info
|
||||
NymVPN is an experimental software and it's for testing purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
1. Open Github [releases page](https://github.com/nymtech/nym-vpn-client) and download the CLI latest binary for your system
|
||||
|
||||
2. Verify sha hash of your downloaded binary with the one listed on the [releases page](https://github.com/nymtech/nym-vpn-client). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
|
||||
```sh
|
||||
echo "<SHA_STRING>" | shasum -a 256 -c
|
||||
|
||||
# choose a correct one according to your binary, this is just an example
|
||||
# echo "0e4abb461e86b2c168577e0294112a3bacd3a24bf8565b49783bfebd9b530e23 nym-vpn-cli_<!-- cmdrun scripts/nym_vpn_cli_version.sh -->_ubuntu-22.04_amd64.tar.gz" | shasum -a 256 -c
|
||||
```
|
||||
|
||||
3. Extract files:
|
||||
```sh
|
||||
tar -xvf <BINARY>.tar.gz
|
||||
# for example
|
||||
# tar -xvf nym-vpn-cli_<!-- cmdrun scripts/nym_vpn_cli_version.sh -->_ubuntu-22.04_x86_64.tar.gz
|
||||
```
|
||||
|
||||
4. Make executable:
|
||||
```sh
|
||||
# make sure you are in the right sub-directory
|
||||
chmod u+x ./nym-vpn-cli
|
||||
```
|
||||
|
||||
## Run NymVPN
|
||||
|
||||
**For NymVPN to work, all other VPNs must be switched off!** At this alpha stage of NymVPN, the network connection (wifi) must be reconnected after or in between the testing rounds.
|
||||
|
||||
Make sure your terminal is open in the same directory as your `nym-vpn-cli` binary.
|
||||
|
||||
1. Go to [nymvpn.com/en/alpha](https://nymvpn.com/en/alpha) to get the entire command with all the needed arguments' values and your wireguard private key for testing purposes
|
||||
2. Run it as root with `sudo` - the command will look like this with specified arguments:
|
||||
```sh
|
||||
sudo ./nym-vpn-cli -c ./sandbox.env --entry-gateway-id <ENTRY_GATEWAY_ID> --exit-router-address <EXIT_ROUTER_ADDRESS> --enable-wireguard --private-key <PRIVATE_KEY> --wg-ip <WIREGUARD_IP>
|
||||
```
|
||||
3. To choose different Gateways, visit [explorer.nymtech.net/network-components/gateways](https://explorer.nymtech.net/network-components/gateways) and copy-paste an identity key of your choice
|
||||
4. See all possibilities in [command explanation](#cli-commands-and-options) section below
|
||||
|
||||
In case of errors, see [troubleshooting section](troubleshooting.md).
|
||||
|
||||
### CLI Commands and Options
|
||||
|
||||
The basic syntax of `nym-vpn-cli` is:
|
||||
```sh
|
||||
sudo ./nym-vpn-cli <--exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY>>
|
||||
```
|
||||
* To choose different Gateways, visit [nymvpn.com/en/alpha/api/gateways](https://explorer.nymtech.net/network-components/gateways)
|
||||
* To see all possibilities run with `--help` flag:
|
||||
```sh
|
||||
./nym-vpn-cli --help
|
||||
```
|
||||
~~~admonish example collapsible=true title="Console output"
|
||||
```sh
|
||||
Usage: nym-vpn-cli [OPTIONS] <--exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY>>
|
||||
|
||||
Options:
|
||||
-c, --config-env-file <CONFIG_ENV_FILE>
|
||||
Path pointing to an env file describing the network
|
||||
--mixnet-client-path <MIXNET_CLIENT_PATH>
|
||||
Path to the data directory of a previously initialised mixnet client, where the keys reside
|
||||
--entry-gateway-id <ENTRY_GATEWAY_ID>
|
||||
Mixnet public ID of the entry gateway
|
||||
--entry-gateway-country <ENTRY_GATEWAY_COUNTRY>
|
||||
Auto-select entry gateway by country ISO
|
||||
--entry-gateway-low-latency
|
||||
Auto-select entry gateway by latency
|
||||
--exit-router-address <EXIT_ROUTER_ADDRESS>
|
||||
Mixnet recipient address
|
||||
--exit-gateway-id <EXIT_GATEWAY_ID>
|
||||
|
||||
--exit-gateway-country <EXIT_GATEWAY_COUNTRY>
|
||||
Mixnet recipient address
|
||||
--enable-wireguard
|
||||
Enable the wireguard traffic between the client and the entry gateway
|
||||
--private-key <PRIVATE_KEY>
|
||||
Associated private key
|
||||
--wg-ip <WG_IP>
|
||||
The IP address of the wireguard interface used for the first hop to the entry gateway
|
||||
--nym-ipv4 <NYM_IPV4>
|
||||
The IPv4 address of the nym TUN device that wraps IP packets in sphinx packets
|
||||
--nym-ipv6 <NYM_IPV6>
|
||||
The IPv6 address of the nym TUN device that wraps IP packets in sphinx packets
|
||||
--nym-mtu <NYM_MTU>
|
||||
The MTU of the nym TUN device that wraps IP packets in sphinx packets
|
||||
--disable-routing
|
||||
Disable routing all traffic through the nym TUN device. When the flag is set, the nym TUN device will be created, but to route traffic through it you will need to do it manually, e.g. ping -Itun0
|
||||
--enable-two-hop
|
||||
Enable two-hop mixnet traffic. This means that traffic jumps directly from entry gateway to exit gateway
|
||||
--enable-poisson-rate
|
||||
Enable Poisson process rate limiting of outbound traffic
|
||||
--disable-background-cover-traffic
|
||||
Disable constant rate background loop cover traffic
|
||||
-h, --help
|
||||
Print help
|
||||
-V, --version
|
||||
Print version
|
||||
```
|
||||
~~~
|
||||
|
||||
Here is a list of the options and their descriptions. Some are essential, some are more technical and not needed to be adjusted by users.
|
||||
|
||||
**Fundamental commands and arguments**
|
||||
|
||||
- `-c` is a path to the [Sandbox config](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) file saved as `sandbox.env`
|
||||
- `--entry-gateway-id`: paste one of the values labeled with a key `"identityKey"` (without `" "`) from [here](https://nymvpn.com/en/alpha/api/gateways)
|
||||
- `--exit-router-address`: paste one of the values labeled with a key `"address"` (without `" "`) from here [here](https://nymvpn.com/en/alpha/api/gateways)
|
||||
- `--enable-wireguard`: Enable the wireguard traffic between the client and the entry gateway. NymVPN uses Mullvad libraries for wrapping `wireguard-go` and to setup local routing rules to route all traffic to the TUN virtual network device
|
||||
- `--wg-ip`: The address of the wireguard interface, you can get it [here](https://nymvpn.com/en/alpha)
|
||||
- `--private-key`: get your private key for testing purposes [here](https://nymvpn.com/en/alpha)
|
||||
- `--enable-two-hop` is a faster setup where the traffic is routed from the client to Entry Gateway and directly to Exit Gateway (default is 5-hops)
|
||||
|
||||
**Advanced options**
|
||||
|
||||
- `--enable-poisson`: Enables process rate limiting of outbound traffic (disabled by default). It means that NymVPN client will send packets at a steady stream to the Entry Gateway. By default it's on average one sphinx packet per 20ms, but there is some randomness (poisson distribution). When there are no real data to fill the sphinx packets with, cover packets are generated instead.
|
||||
- `--ip` is the IP address of the TUN device. That is the IP address of the local private network that is set up between local client and the Exit Gateway.
|
||||
- `--mtu`: The MTU of the TUN device. That is the max IP packet size of the local private network that is set up between local client and the Exit Gateway.
|
||||
- `--disable-routing`: Disable routing all traffic through the VPN TUN device.
|
||||
|
||||
## Testnet environment
|
||||
|
||||
If you want to run NymVPN CLI in Nym Sandbox environment, there are a few adjustments to be done:
|
||||
|
||||
1. Create Sandbox environment config file by saving [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) as `sandbox.env` in the same directory as your NymVPN binaries by running:
|
||||
```sh
|
||||
curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env
|
||||
```
|
||||
|
||||
1. Check available Gateways at [nymvpn.com/en/alpha/api/gateways](https://nymvpn.com/en/alpha/api/gateways)
|
||||
|
||||
2. Run with a flag `-c`
|
||||
```sh
|
||||
sudo ./nym-vpn-cli -c <PATH_TO>/sandbox.env <--exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY>>
|
||||
```
|
||||
@@ -1,123 +0,0 @@
|
||||
# NymVPN alpha CLI: Guide for MacOS
|
||||
|
||||
```admonish info
|
||||
NymVPN is an experimental software and it's for testing purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
|
||||
```
|
||||
|
||||
## Preparation
|
||||
|
||||
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
1. Open Github [releases page](https://github.com/nymtech/nym-vpn-client) and download the binary for MacOS
|
||||
2. Verify sha hash of your downloaded binary with the one listed on the [releases page](https://github.com/nymtech/nym-vpn-client). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
|
||||
```sh
|
||||
echo "<SHA_STRING>" | shasum -a 256 -c
|
||||
|
||||
# choose a correct one according to your binary, this is just an example
|
||||
# echo "96623ccc69bc4cc0e4e3e18528b6dae6be69f645d0a592d926a3158ce2d0c269 nym-vpn-cli_<!-- cmdrun scripts/nym_vpn_cli_version.sh -->_macos_x86_64.zip" | shasum -a 256 -c
|
||||
```
|
||||
3. Extract files:
|
||||
```sh
|
||||
tar -xvf <BINARY>
|
||||
# for example
|
||||
# tar -xvf nym-vpn-cli_<!-- cmdrun scripts/nym_vpn_cli_version.sh -->_macos_aarch64.tar.gz
|
||||
```
|
||||
4. Make executable by running:
|
||||
```sh
|
||||
# possibly you may have to cd into a sub-directory
|
||||
chmod u+x ./nym-vpn-cli
|
||||
```
|
||||
5. Create Sandbox environment config file by saving [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) as `sandbox.env` in the same directory as your NymVPN binaries by running:
|
||||
```sh
|
||||
curl -L "https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env" -o sandbox.env
|
||||
```
|
||||
|
||||
## Run NymVPN
|
||||
|
||||
**For NymVPN to work, all other VPNs must be switched off!** At this alpha stage of NymVPN, the network connection (wifi) must be reconnected after or in between the testing rounds.
|
||||
|
||||
Make sure your terminal is open in the same directory as your `nym-vpn-cli` binary.
|
||||
|
||||
1. Go to [nymvpn.com/en/alpha](https://nymvpn.com/en/alpha) to get the entire command with all the needed arguments' values and your wireguard private key for testing purposes
|
||||
2. Run it as root with `sudo` - the command will look like this with specified arguments:
|
||||
```sh
|
||||
sudo ./nym-vpn-cli -c ./sandbox.env --entry-gateway-id <ENTRY_GATEWAY_ID> --exit-router-address <EXIT_ROUTER_ADDRESS> --enable-wireguard --private-key <PRIVATE_KEY> --wg-ip <WIREGUARD_IP>
|
||||
```
|
||||
3. To choose different Gateways, visit [nymvpn.com/en/alpha/api/gateways](https://nymvpn.com/en/alpha/api/gateways) and pick one
|
||||
4. See all possibilities in [command explanation](#cli-commands-and-options) section below
|
||||
|
||||
In case of errors, see [troubleshooting section](troubleshooting.md).
|
||||
|
||||
### CLI Commands and Options
|
||||
|
||||
The basic syntax of `nym-vpn-cli` is:
|
||||
```sh
|
||||
sudo ./nym-vpn-cli -c ./sandbox.env --entry-gateway-id <ENTRY_GATEWAY_ID> --exit-router-address <EXIT_ROUTER_ADDRESS> --enable-wireguard --private-key <PRIVATE_KEY> --wg-ip <WG_IP>
|
||||
```
|
||||
* To choose different Gateways, visit [nymvpn.com/en/alpha/api/gateways](https://nymvpn.com/en/alpha/api/gateways)
|
||||
* To see all possibilities run with `--help` flag:
|
||||
```sh
|
||||
./nym-vpn-cli --help
|
||||
```
|
||||
~~~admonish example collapsible=true title="Console output"
|
||||
```sh
|
||||
Usage: nym-vpn-cli [OPTIONS]
|
||||
|
||||
Options:
|
||||
-c, --config-env-file <CONFIG_ENV_FILE>
|
||||
Path pointing to an env file describing the network
|
||||
--mixnet-client-path <MIXNET_CLIENT_PATH>
|
||||
Path to the data directory of a previously initialised mixnet client, where the keys reside
|
||||
--entry-gateway-id <ENTRY_GATEWAY_ID>
|
||||
Mixnet public ID of the entry gateway
|
||||
--entry-gateway-country <ENTRY_GATEWAY_COUNTRY>
|
||||
Auto-select entry gateway by country ISO
|
||||
--exit-router-address <EXIT_ROUTER_ADDRESS>
|
||||
Mixnet recipient address
|
||||
--exit-gateway-id <EXIT_GATEWAY_ID>
|
||||
|
||||
--exit-router-country <EXIT_ROUTER_COUNTRY>
|
||||
Mixnet recipient address
|
||||
--enable-wireguard
|
||||
Enable the wireguard traffic between the client and the entry gateway
|
||||
--private-key <PRIVATE_KEY>
|
||||
Associated private key
|
||||
--wg-ip <WG_IP>
|
||||
The IP address of the wireguard interface used for the first hop to the entry gateway
|
||||
--nym-ip <NYM_IP>
|
||||
The IP address of the nym TUN device that wraps IP packets in sphinx packets
|
||||
--nym-mtu <NYM_MTU>
|
||||
The MTU of the nym TUN device that wraps IP packets in sphinx packets
|
||||
--disable-routing
|
||||
Disable routing all traffic through the nym TUN device. When the flag is set, the nym TUN device will be created, but to route traffic through it you will need to do it manually, e.g. ping -Itun0
|
||||
--enable-two-hop
|
||||
Enable two-hop mixnet traffic. This means that traffic jumps directly from entry gateway to exit gateway
|
||||
--enable-poisson-rate
|
||||
Enable Poisson process rate limiting of outbound traffic
|
||||
--disable-background-cover-traffic
|
||||
Disable constant rate background loop cover traffic
|
||||
-h, --help
|
||||
Print help
|
||||
-V, --version
|
||||
Print version
|
||||
```
|
||||
~~~
|
||||
|
||||
Here is a list of the options and their descriptions. Some are essential, some are more technical and not needed to be adjusted by users.
|
||||
|
||||
**Fundamental commands and arguments**
|
||||
|
||||
- `-c` is a path to the [Sandbox config](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) file saved as `sandbox.env`
|
||||
- `--entry-gateway-id`: paste one of the values labeled with a key `"identityKey"` (without `" "`) from [here](https://nymvpn.com/en/alpha/api/gateways)
|
||||
- `--exit-router-address`: paste one of the values labeled with a key `"address"` (without `" "`) from here [here](https://nymvpn.com/en/alpha/api/gateways)
|
||||
- `--enable-wireguard`: Enable the wireguard traffic between the client and the entry gateway. NymVPN uses Mullvad libraries for wrapping `wireguard-go` and to setup local routing rules to route all traffic to the TUN virtual network device
|
||||
- `--wg-ip`: The address of the wireguard interface, you can get it [here](https://nymvpn.com/en/alpha)
|
||||
- `--private-key`: get your private key for testing purposes [here](https://nymvpn.com/en/alpha)
|
||||
- `--enable-two-hop` is a faster setup where the traffic is routed from the client to Entry Gateway and directly to Exit Gateway (default is 5-hops)
|
||||
|
||||
**Advanced options**
|
||||
|
||||
- `--enable-poisson`: Enables process rate limiting of outbound traffic (disabled by default). It means that NymVPN client will send packets at a steady stream to the Entry Gateway. By default it's on average one sphinx packet per 20ms, but there is some randomness (poisson distribution). When there are no real data to fill the sphinx packets with, cover packets are generated instead.
|
||||
- `--ip` is the IP address of the TUN device. That is the IP address of the local private network that is set up between local client and the Exit Gateway.
|
||||
- `--mtu`: The MTU of the TUN device. That is the max IP packet size of the local private network that is set up between local client and the Exit Gateway.
|
||||
- `--disable-routing`: Disable routing all traffic through the VPN TUN device.
|
||||
@@ -1,240 +0,0 @@
|
||||
# NymVPN CLI Guide
|
||||
|
||||
```admonish tip title="web3summit testing"
|
||||
**If you testing NymVPN CLI on Web3 Summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/).**
|
||||
```
|
||||
|
||||
```admonish info
|
||||
To download NymVPN desktop version, visit [nymvpn.com/en/download](https://nymvpn.com/en/download).
|
||||
|
||||
NymVPN is an experimental software and it's for testing purposes only. Anyone can submit a registration to the private alpha round on [nymvpn.com](https://nymvpn.com/en).
|
||||
```
|
||||
|
||||
## Overview
|
||||
|
||||
The core binaries consist of:
|
||||
|
||||
- **`nym-vpn-cli`**: Basic commandline client for running the vpn. This runs in the foreground.
|
||||
|
||||
- **`nym-vpnd`**: Daemon implementation of the vpn client that can run in the background and interacted with using `nym-vpnc`.
|
||||
|
||||
- **`nym-vpnc`**: The commandline client used to interact with `nym-vpnd`.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
1. Open Github [releases page](https://github.com/nymtech/nym-vpn-client) and download the CLI latest binary for your system (labelled as `nym-vpn-core`)
|
||||
|
||||
2. Verify sha hash of your downloaded binary with the one listed on the [releases page](https://github.com/nymtech/nym-vpn-client). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
|
||||
```sh
|
||||
echo "<SHA_STRING>" | shasum -a 256 -c
|
||||
|
||||
# choose a correct one according to your binary, this is just an example
|
||||
# echo "0e4abb461e86b2c168577e0294112a3bacd3a24bf8565b49783bfebd9b530e23 nym-vpn-cli_<!-- cmdrun ../../../scripts/cmdrun/nym_vpn_cli_version.sh -->_ubuntu-22.04_amd64.tar.gz" | shasum -a 256 -c
|
||||
```
|
||||
|
||||
3. Extract files:
|
||||
```sh
|
||||
tar -xvf <BINARY>.tar.gz
|
||||
# for example
|
||||
# tar -xvf nym-vpn-cli_<!-- cmdrun ../../../scripts/cmdrun/nym_vpn_cli_version.sh -->_ubuntu-22.04_x86_64.tar.gz
|
||||
```
|
||||
|
||||
### Building From Source
|
||||
|
||||
NymVPN CLI can be built from source. This process is recommended for more advanced users as the installation may require different dependencies based on the operating system used.
|
||||
|
||||
Start by installing [Go](https://go.dev/doc/install) and [Rust](https://rustup.rs/) languages on your system and then follow these steps:
|
||||
|
||||
1. Clone NymVPN repository:
|
||||
```sh
|
||||
git clone https://github.com/nymtech/nym-vpn-client.git
|
||||
```
|
||||
|
||||
2. Move to `nym-vpn-client` directory and compile `wireguard`:
|
||||
|
||||
```sh
|
||||
cd nym-vpn-client
|
||||
|
||||
make build-wireguard
|
||||
```
|
||||
|
||||
3. Compile NymVPN CLI
|
||||
```sh
|
||||
make build-nym-vpn-core
|
||||
```
|
||||
|
||||
Now your NymVPN CLI is installed. Navigate to `nym-vpn-core/target/release` and use the commands the section below to run the client.
|
||||
|
||||
## Running
|
||||
|
||||
If you are running Debian/Ubuntu/PopOS or any other distributio supporting debian packages and systemd, see the [relevant section below](#debian-package-for-debianubuntupopos).
|
||||
|
||||
### Daemon
|
||||
|
||||
Start the daemon with
|
||||
|
||||
```sh
|
||||
sudo -E ./nym-vpnd
|
||||
```
|
||||
|
||||
Then run
|
||||
|
||||
```sh
|
||||
./nym-vpnc status
|
||||
./nym-vpnc connect
|
||||
./nym-vpnc disconnect
|
||||
```
|
||||
|
||||
### CLI
|
||||
|
||||
An alternative to the daemon is to run the `nym-vpn-cli` commandline client that runs in the foreground.
|
||||
```sh
|
||||
./nym-vpn-cli run
|
||||
```
|
||||
|
||||
## Credentials
|
||||
|
||||
NymVPN uses [zkNym bandwidth credentials](https://nymtech.net/docs/bandwidth-credentials.html). Those can be imported as a file or base58 encoded string.
|
||||
|
||||
|
||||
```sh
|
||||
sudo -E ./nym-vpn-cli import-credential --credential-path </PATH/TO/freepass.nym>
|
||||
sudo -E ./nym-vpn-cli import-credential --credential-data "<STRING>"
|
||||
```
|
||||
|
||||
## Debian package for Debian/Ubuntu/PopOS
|
||||
|
||||
For linux platforms using deb packages and systemd, there are also debian packages.
|
||||
|
||||
```sh
|
||||
sudo apt install ./nym-vpnd_<!-- cmdrun ../../../scripts/cmdrun/nym_vpn_cli_version.sh -->-1_amd64.deb ./nym-vpnc_<!-- cmdrun ../../../scripts/cmdrun/nym_vpn_cli_version.sh -->-1_amd64.deb
|
||||
|
||||
# In case of error please substitute the correct version
|
||||
```
|
||||
|
||||
Installing the `nym-vpnd` deb package starts a `nym-vpnd.service`. Check that the daemon is running with
|
||||
```sh
|
||||
systemctl status nym-vpnd.service
|
||||
```
|
||||
and check its logs with
|
||||
```sh
|
||||
sudo journalctl -u nym-vpnd.service -f
|
||||
```
|
||||
To stop the background service
|
||||
```sh
|
||||
systemctl stop nym-vpnd.service
|
||||
```
|
||||
It will start again on startup, so disable with
|
||||
```sh
|
||||
systemctl disable nym-vpnd.service
|
||||
```
|
||||
|
||||
Interact with it with `nym-vpnc`
|
||||
```sh
|
||||
nym-vpnc status
|
||||
nym-vpnc connect
|
||||
nym-vpnc disconnect
|
||||
```
|
||||
|
||||
## Commands & Options
|
||||
|
||||
```admonish note
|
||||
Nym Exit Gateway functionality was implemented just recently and not all the Gateways are upgraded and ready to handle the VPN connections. If you want to make sure you are connecting to a Gateway with an embedded Network Requester, IP Packet Router and applied Nym exit policy, visit [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/) and search Gateways with all the functionalities enabled.
|
||||
```
|
||||
|
||||
The basic syntax of `nym-vpn-cli` is:
|
||||
```sh
|
||||
# choose only one conditional --argument listed in {brackets}
|
||||
sudo ./nym-vpn-cli { --exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY> }
|
||||
```
|
||||
|
||||
To see all the possibilities run with `--help` flag:
|
||||
```sh
|
||||
./nym-vpn-cli --help
|
||||
```
|
||||
|
||||
~~~admonish example collapsible=true title="nym-vpn-cli --help"
|
||||
```sh
|
||||
Usage: nym-vpn-cli [OPTIONS] <COMMAND>
|
||||
|
||||
Commands:
|
||||
run Run the client
|
||||
import-credential Import credential
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
-c, --config-env-file <CONFIG_ENV_FILE> Path pointing to an env file describing the network
|
||||
--data-path <DATA_PATH> Path to the data directory of the mixnet client
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
```
|
||||
~~~
|
||||
|
||||
You can also run any command with `--help` flag to see a list of all options associated witht that command, the most important may be `run` command, like in this example.
|
||||
|
||||
~~~admonish example collapsible=true title="nym-vpn-cli run --help"
|
||||
```sh
|
||||
Run the client
|
||||
|
||||
Usage: nym-vpn-cli run [OPTIONS]
|
||||
|
||||
Options:
|
||||
--entry-gateway-id <ENTRY_GATEWAY_ID>
|
||||
Mixnet public ID of the entry gateway
|
||||
--entry-gateway-country <ENTRY_GATEWAY_COUNTRY>
|
||||
Auto-select entry gateway by country ISO
|
||||
--entry-gateway-low-latency
|
||||
Auto-select entry gateway by latency
|
||||
--exit-router-address <EXIT_ROUTER_ADDRESS>
|
||||
Mixnet recipient address
|
||||
--exit-gateway-id <EXIT_GATEWAY_ID>
|
||||
Mixnet public ID of the exit gateway
|
||||
--exit-gateway-country <EXIT_GATEWAY_COUNTRY>
|
||||
Auto-select exit gateway by country ISO
|
||||
--wireguard-mode
|
||||
Enable the wireguard mode
|
||||
--nym-ipv4 <NYM_IPV4>
|
||||
The IPv4 address of the nym TUN device that wraps IP packets in sphinx packets
|
||||
--nym-ipv6 <NYM_IPV6>
|
||||
The IPv6 address of the nym TUN device that wraps IP packets in sphinx packets
|
||||
--nym-mtu <NYM_MTU>
|
||||
The MTU of the nym TUN device that wraps IP packets in sphinx packets
|
||||
--dns <DNS>
|
||||
The DNS server to use
|
||||
--disable-routing
|
||||
Disable routing all traffic through the nym TUN device. When the flag is set, the nym TUN device will be created, but to route traffic through it you will need to do it manually, e.g. ping -Itun0
|
||||
--enable-two-hop
|
||||
Enable two-hop mixnet traffic. This means that traffic jumps directly from entry gateway to exit gateway
|
||||
--enable-poisson-rate
|
||||
Enable Poisson process rate limiting of outbound traffic
|
||||
--disable-background-cover-traffic
|
||||
Disable constant rate background loop cover traffic
|
||||
--enable-credentials-mode
|
||||
Enable credentials mode
|
||||
--min-mixnode-performance <MIN_MIXNODE_PERFORMANCE>
|
||||
Set the minimum performance level for mixnodes
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
```
|
||||
~~~
|
||||
|
||||
|
||||
## Testnet environment
|
||||
|
||||
If you want to run NymVPN CLI in Nym Sandbox environment, there are a few adjustments to be done:
|
||||
|
||||
1. Create Sandbox environment config file by saving [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) as `sandbox.env` in the same directory as your NymVPN binaries:
|
||||
```sh
|
||||
curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env
|
||||
```
|
||||
|
||||
2. Check available Gateways at [Sandbox API](https://sandbox-nym-api1.nymtech.net/api/v1/gateways) or [Sandbox Swagger page](https://sandbox-nym-api1.nymtech.net/api/swagger/index.html)
|
||||
|
||||
3. Run with a flag `-c`
|
||||
```sh
|
||||
sudo ./nym-vpn-cli -c <PATH_TO>/sandbox.env <--exit-router-address <EXIT_ROUTER_ADDRESS>|--exit-gateway-id <EXIT_GATEWAY_ID>|--exit-gateway-country <EXIT_GATEWAY_COUNTRY>>
|
||||
```
|
||||
@@ -1,71 +0,0 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
**NymVPN [*Support & FAQ page*](https://nymvpn.com/en/support)** contains all essential FAQs regarding the client. This page (below) is a source of additional information often seeked by users, operators and developers testing NymVPN.
|
||||
|
||||
If you interested to read more about Nym platform, you can have a look at [Nym general FAQ](https://nymtech.net/developers/faq/general-faq.html) and read through Nym's technical [documentation](https://nymtech.net/docs), [Developer Portal](https://nymtech.net/developers) and [Operators Guide](https://nymtech.net/operators).
|
||||
|
||||
## NymVPN
|
||||
|
||||
If this your first time hearing about NymVPN, make sure you visit [NymVPN webpage](https://nymvpn.com/en), the official NymVPN [support & FAQ page](https://nymvpn.com/en/support) and the proceed to the introduction and guide on how to [install, run and test](intro.md#nymvpn-guides) the client.
|
||||
|
||||
Below are some extra FAQs which came out during the previous alpha testing rounds.
|
||||
|
||||
### What's the difference between 2-hops and 5-hops
|
||||
|
||||
The default is 5-hops (including Entry and Exit Gateways), which means that the traffic goes from the local client to Entry Gateway -> through 3 layers of Mix Nodes -> to Exit Gateway -> internet. this option uses all the Nym Mixnet features for maximum privacy.
|
||||
|
||||
```
|
||||
┌─►mix──┐ mix mix
|
||||
│ │
|
||||
Entry │ │ Exit
|
||||
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
|
||||
│ │
|
||||
│ │
|
||||
mix └─►mix──┘ mix
|
||||
```
|
||||
|
||||
The 2-hop option is going from the local client -> Entry Gateway -> directly to Exit Gateway -> internet. This option is good for operations demanding faster connection. Keep in mind that this setup by-passes the 3 layers of Mix Nodes. The anonymising features done by your local client like breaking data into same-size packets with inserting additional "dummy" ones to break the time and volume patterns is done in both options.
|
||||
|
||||
```
|
||||
Entry Exit
|
||||
client ───► Gateway ────► Gateway ───► internet
|
||||
```
|
||||
|
||||
We highly recommend to read more about [Nym network overview](https://nymtech.net/docs/architecture/network-overview.html) and the [Mixnet traffic flow](https://nymtech.net/docs/architecture/traffic-flow.html).
|
||||
|
||||
### Why do I see different sizes of packets in my terminal log?
|
||||
|
||||
One of features of Nym Mixnet's clients is to break data into the same size packets called Sphinx, which is currently ~2kb. When running NymVPN, the data log shows payload sizes, which are the raw sizes of the IP packets, not Sphinx. The payload sizes will be capped by the configured MTU, which is set around 1500 bytes.
|
||||
|
||||
### What is 'poisson filter' about?
|
||||
|
||||
By default `--enable-poisson` is disabled and packets are sent from the local client to the Entry Gateway as quickly as possible. With the poisson process enabled the Nym client will send packets at a steady stream to the Entry Gateway. By default it's on average one sphinx packet per 20ms, but there is some randomness (poisson distribution). When there are no real data to fill the sphinx packets with, cover packets are generated instead.
|
||||
|
||||
Enabling the poisson filter is one of the key mechanisms to de-correlate input and output traffic to the Mixnet. The performance impact however is dramatic:
|
||||
1 packer per 20ms is 50 packets / sec so ballpark 100kb/s.
|
||||
For mobile clients that means constantly sending data eating up data allowance.
|
||||
|
||||
|
||||
## Nym Mixnet Architecture and Rewards
|
||||
|
||||
We have a list of questions related to Nym Nodes and the incentives behind running them under [FAQ pages](https://nymtech.net/operators/faq/mixnodes-faq.html) in our [Operators Guide](https://nymtech.net/operators). For better knowledge about Nym architecture we recommend to read [Nym network overview](https://nymtech.net/docs/architecture/network-overview.html) and the [Mixnet traffic flow](https://nymtech.net/docs/architecture/traffic-flow.html) in our [technical documentation](https://nymtech.net/docs).
|
||||
|
||||
## Project Smoosh
|
||||
|
||||
Project Smoosh is a code name for a process in which different components of Nym Mixnet architecture get *smooshed* into one binary. Check out [Smoosh FAQ](https://nymtech.net/operators/faq/smoosh-faq.html) in Operators Guide to read more.
|
||||
|
||||
## Exit Gateway
|
||||
|
||||
Part of the the transition under code name [Project Smoosh](#project-smoosh) is a creation of [Nym Exit Gateway](https://nymtech.net/operators/legal/exit-gateway.html) functionality. The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [allowed.list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients.
|
||||
|
||||
* Read more how the exit policy gets implemented [here](https://nymtech.net/operators/faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented)
|
||||
* Check out [Nym Operators Legal Forum](https://nymtech.net/operators/legal/exit-gateway.html)
|
||||
* Do reach out to us with any experiences you may have running Tor Exit relays or legal findings and suggestions for Nym Exit Gateway operators
|
||||
|
||||
## Nym Integrations and SDKs
|
||||
|
||||
If you are a dev who is interested to integrate Nym, have a look on our SDK tutorials:
|
||||
|
||||
* [Rust SDKs](https://nymtech.net/developers/tutorials/cosmos-service/intro.html)
|
||||
* [TypeScript SDKs](https://sdk.nymtech.net/)
|
||||
* [Integration FAQ](https://nymtech.net/developers/faq/integrations-faq.html)
|
||||
@@ -1,85 +0,0 @@
|
||||
# NymVPN alpha - Desktop: Guide for GNU/Linux
|
||||
|
||||
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/908221306?h=404b2bbdc8" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
|
||||
|
||||
```admonish info
|
||||
NymVPN is an experimental software and it's for testing purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
|
||||
```
|
||||
|
||||
## Preparation
|
||||
|
||||
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
### Installation
|
||||
|
||||
1. Open Github [releases page](https://github.com/nymtech/nym-vpn-client) and download the binary for Debian based Linux
|
||||
|
||||
2. (Optional: if you don't want to check shasum, skip this point) Verify sha hash of your downloaded binary with the one listed on the [releases page](https://github.com/nymtech/nym-vpn-client). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
|
||||
```sh
|
||||
echo "<SHA_STRING>" | shasum -a 256 -c
|
||||
|
||||
# choose a correct one according to your binary, this is just an example
|
||||
# echo "a5f91f20d587975e30b6a75d3a9e195234cf1269eac278139a5b9c39b039e807 nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_ubuntu-22.04_x86_64.tar.gz" | shasum -a 256 -c
|
||||
```
|
||||
|
||||
3. Extract files:
|
||||
```sh
|
||||
tar -xvf <BINARY>.tar.gz
|
||||
# for example
|
||||
# tar -xvf nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_ubuntu-22.04_x86_64.tar.gz
|
||||
```
|
||||
|
||||
4. If you prefer to run `.AppImage` make executable by running:
|
||||
```sh
|
||||
# make sure you cd into the right sub-directory after extraction
|
||||
chmod u+x ./nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.AppImage
|
||||
```
|
||||
|
||||
5. If you prefer to use the `.deb` version for installation (works on Debian based Linux only), open terminal in the same directory and run:
|
||||
```sh
|
||||
# make sure you cd into the right sub-directory after extraction
|
||||
sudo dpkg -i ./nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.deb
|
||||
# or
|
||||
sudo apt-get install -f ./nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.deb
|
||||
```
|
||||
|
||||
<!--
|
||||
NymVPN alpha version runs over Nym testnet (called sandbox), a little extra configuration is needed for the application to work.
|
||||
|
||||
### Configuration
|
||||
|
||||
To test NymVPN alpha we must create two configuration files: an environment config file `sandbox.env` and `config.toml` file pointing the application to run over the testnet environment.
|
||||
|
||||
6. Create a NymVPN config directory called `nym-vpn` in your `~/.config`, either manually or by a command:
|
||||
```sh
|
||||
mkdir $HOME/.config/nym-vpn/
|
||||
```
|
||||
7. Create the network testnet config: copy-paste [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) and save as `sandbox.env` in the directory `~/.config/nym-vpn/` you just created. Aternatively do it by runnin a command
|
||||
```sh
|
||||
curl -o $HOME/.config/nym-vpn/sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env
|
||||
```
|
||||
|
||||
8. Create NymVPN main config file: copy-paste the line below and save it as `config.toml` in the same directory `~/.config/nym-vpn/`:
|
||||
```toml
|
||||
# change <USER> to your username
|
||||
env_config_file = "/home/<USER>/.config/nym-vpn/sandbox.env"
|
||||
```
|
||||
-->
|
||||
|
||||
## Run NymVPN
|
||||
|
||||
**For NymVPN to work, all other VPNs must be switched off!** At this alpha stage of NymVPN, the network connection (wifi) must be reconnected after or in between the testing rounds.
|
||||
|
||||
In case you used `.deb` package and installed the client, you may be able to have a NymVPN application icon in your app menu. However this may not work as the application needs root permission.
|
||||
|
||||
Open terminal and run:
|
||||
|
||||
```sh
|
||||
# .AppImage must be run from the same directory as the binary
|
||||
sudo -E ./nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.AppImage
|
||||
|
||||
# .deb installation shall be executable from anywhere as
|
||||
sudo -E nym-vpn
|
||||
```
|
||||
|
||||
In case of errors, see [troubleshooting section](troubleshooting.md).
|
||||
@@ -1,65 +0,0 @@
|
||||
# NymVPN alpha - Desktop: Guide for Mac OS
|
||||
|
||||
```admonish info
|
||||
NymVPN is an experimental software and it's for testing purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
|
||||
```
|
||||
|
||||
## Preparation
|
||||
|
||||
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
### Installation
|
||||
|
||||
1. Open Github [releases page](https://github.com/nymtech/nym-vpn-client) and download the binary for your version of MacOS
|
||||
|
||||
2. Recommended (skip this point if you don't want to verify): Verify sha hash of your downloaded binary with the one listed on the [releases page](https://github.com/nymtech/nym-vpn-client). You can use a simple `shasum` command and compare strings (ie with Python) or run in the same directory the following command, exchanging `<SHA_STRING>` with the one of your binary, like in the example:
|
||||
```sh
|
||||
echo "<SHA_STRING>" | shasum -a 256 -c
|
||||
|
||||
# choose a correct one according to your binary, this is just an example
|
||||
# echo "da4c0bf8e8b52658312d341fa3581954cfcb6efd516d9a448c76d042a454b5df nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_macos_x86_64.zip" | shasum -a 256 -c
|
||||
```
|
||||
|
||||
3. Extract the downloaded file manually or by a command:
|
||||
```sh
|
||||
tar -xvf <BINARY>.tar.gz
|
||||
# for example
|
||||
# tar -xvf nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_macos_aarch64.tar.gz
|
||||
```
|
||||
4. Mount the `.dmg` image you extracted by double clicking on it and move it (drag it) to your `/Application` folder
|
||||
|
||||
<!--
|
||||
NymVPN alpha version runs over Nym testnet (called sandbox), a little extra configuration is needed for the application to work.
|
||||
|
||||
### Configuration
|
||||
|
||||
To test NymVPN alpha we must create two configuration files: an environment config file `sandbox.env` and `config.toml` file pointing the application to run over the testnet environment.
|
||||
|
||||
5. Create testnet configuration file: Open a text editor, copy-paste [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) and save it as `sandbox.env` in `/Applications/nym-vpn.app/Contents/MacOS/`. Alternatively use this command:
|
||||
```sh
|
||||
curl -L "https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env" -o "/Applications/nym-vpn.app/Contents/MacOS/sandbox.env"
|
||||
```
|
||||
|
||||
6. Create application configuration file: Open a text editor, copy-paste the line below and save as `config.toml` in the same directory `/Applications/nym-vpn.app/Contents/MacOS/`
|
||||
```toml
|
||||
env_config_file = "sandbox.env"
|
||||
```
|
||||
Alternatively do it by using this command:
|
||||
```sh
|
||||
echo "env_config_file = sandbox.env" > /Applications/nym-vpn.app/Contents/MacOS/config.toml
|
||||
```
|
||||
-->
|
||||
|
||||
## Run NymVPN
|
||||
|
||||
**For NymVPN to work, all other VPNs must be switched off!** At this alpha stage of NymVPN, the network connection (wifi) must be reconnected after or in between the testing rounds.
|
||||
|
||||
Run:
|
||||
```sh
|
||||
sudo /Applications/nym-vpn.app/Contents/MacOS/nym-vpn
|
||||
|
||||
# If it didn't start try to run with -E flag
|
||||
sudo -E /Applications/nym-vpn.app/Contents/MacOS/nym-vpn
|
||||
```
|
||||
|
||||
In case of errors check out the [troubleshooting](troubleshooting.md#running-gui-failed-due-to-toml-parse-error) section.
|
||||
@@ -1,50 +0,0 @@
|
||||
# NymVPN - Desktop (GUI)
|
||||
|
||||
```admonish info
|
||||
Our alpha testing round is done with participants at live workshop events and the application in this stage may not work for everyone.
|
||||
|
||||
**If you commit to test NymVPN alpha, please start with the [user research form]({{nym_vpn_form_url}}) where all the steps will be provided**. If you disagree with any of the conditions listed, please leave this page.
|
||||
```
|
||||
|
||||
This is a desktop (GUI) version of NymVPN client. A demo of how the application will look like for majority of day-to-day users.
|
||||
|
||||
Follow the simple [automated script](#automated-script-for-gui-installation) below to install and run NymVPN GUI. If the script didn't work for your distribution or you prefer to do a manual setup follow the steps in the guide for [Linux](gui-linux.md) or [MacOS](gui-mac.md) .
|
||||
|
||||
Visit NymVPN alpha latest [release page](https://github.com/nymtech/nym-vpn-client) to check sha sums or download the binaries directly.
|
||||
|
||||
## Linux AppImage Automated Installation Method
|
||||
|
||||
The latest releases contain `appimage.sh` script. This method makes the installation simple for Linux users who want to run NymVPN from AppImmage. Executing the command below will download the binary to `~/.local/bin` and verify the checksum:
|
||||
```sh
|
||||
curl -fsSL https://github.com/nymtech/nym-vpn-client/releases/download/nym-vpn-desktop-v<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->/appimage.sh | bash
|
||||
```
|
||||
|
||||
Run with the command:
|
||||
```sh
|
||||
sudo -E ~/.local/bin/nym-vpn.appimage
|
||||
```
|
||||
|
||||
## Automated Script for GUI Installation (Linux and Mac)
|
||||
|
||||
We wrote a [script](https://gist.github.com/tommyv1987/7d210d4daa8f7abc61f9a696d0321f19) which does download of dependencies and the application, sha256 verification, extraction, installation and configuration for Linux and MacOS users automatically. Turn off all VPNs and follow the steps below.
|
||||
|
||||
1. Open a terminal window in a directory where you want the script to be downloaded and run
|
||||
```sh
|
||||
curl -o nym-vpn-desktop-install-run.sh -L https://gist.githubusercontent.com/tommyv1987/7d210d4daa8f7abc61f9a696d0321f19/raw/939ac8d0afed69f43739b9cf2e5728454ea2c437/nym-vpn-client-install-run.sh && chmod u+x nym-vpn-desktop-install-run.sh && sudo -E ./nym-vpn-desktop-install-run.sh
|
||||
```
|
||||
|
||||
2. Follow the prompts in the program
|
||||
|
||||
To start the application again, reconnect your wifi and run
|
||||
```sh
|
||||
# Linux .AppImage
|
||||
sudo -E ~/nym-vpn-latest/nym-vpn-desktop_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_ubuntu-22.04_x86_64/nym-vpn_<!-- cmdrun scripts/nym_vpn_desktop_version.sh -->_amd64.AppImage
|
||||
|
||||
# Linux .deb
|
||||
sudo -E nym-vpn
|
||||
|
||||
# MacOS
|
||||
sudo -E $HOME/nym-vpn-latest/nym-vpn
|
||||
```
|
||||
|
||||
In case of errors check out the [troubleshooting](troubleshooting.md#running-gui-failed-due-to-toml-parse-error) section.
|
||||
@@ -1,209 +0,0 @@
|
||||
# Testing NymVPN alpha
|
||||
|
||||
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/908640440?h=0f7f6dfa53" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
|
||||
|
||||
```admonish info
|
||||
NymVPN is an experimental software and it's for [testing](./testing.md) purposes only. All users testing the client are expected to sign GDPR Information Sheet and Consent Form (shared at the workshop) so we use their results to improve the client, and submit the form [*NymVPN User research*]({{nym_vpn_form_url}}) with the testing results.
|
||||
```
|
||||
|
||||
> Before you get into testing NymVPN, make sure to go through the preparation steps for NymVPN [CLI](cli.md).
|
||||
|
||||
One of the main aims of NymVPN alpha release is testing; your results will help us to make NymVPN robust and stabilise both the client and the network through provided measurements.
|
||||
|
||||
## Steps to test NymVPN
|
||||
|
||||
> Any syntax in `<>` brackets is a user's/version unique variable. Exchange with a corresponding name without the `<>` brackets.
|
||||
|
||||
1. Create a directory called `nym-vpn-tests` and copy your `nym-vpn-cli` binary ([download here](https://github.com/nymtech/nym-vpn-client))
|
||||
2. Copy or download [`sandbox.env`](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) testnet config file to the same directory
|
||||
```sh
|
||||
curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env
|
||||
```
|
||||
3. Copy the [block below](#testssh) and save it as `tests.sh` to the same folder
|
||||
4. Open terminal in the same directory and make the script executable
|
||||
```sh
|
||||
chmod u+x ./tests.sh
|
||||
```
|
||||
5. Turn off any existing VPN's (including NymVPN instances), reconnect your wifi and run the `tests.sh` script
|
||||
```sh
|
||||
sudo ./tests.sh
|
||||
````
|
||||
6. In case of errors, see the [troubleshooting section](troubleshooting.md#missing-jq-error)
|
||||
7. The script will print a JSON view of existing Gateways and prompt you to:
|
||||
- *Make sure to use two different Gateways for entry and exit!*
|
||||
- `enter a gateway ID:` paste one of the values labeled with a key `"identityKey"` printed above (without `" "`)
|
||||
- `enter an exit address:` paste one of the values labeled with a key `"address"` printed above (without `" "`)
|
||||
- `enable WireGuard? (yes/no):` if you chose yes, find your private key and wireguard IP [here](https://nymvpn.com/en/alpha)
|
||||
8. Note that the testing script doesn't print many logs, in case of doubts you can check logs in the log file `temp_log.txt` located in the same directory.
|
||||
9. The script shall run the tests and generate a folder called `tests_<LONG_STRING>` and files `perf_test_results.log` or `two_hop_perf_test_results.log` as well as some temp files. This is how the directory structure will look like:
|
||||
```sh
|
||||
nym-vpn-tests
|
||||
├── tests.sh
|
||||
├── nym-vpn-cli
|
||||
├── sandbox.env
|
||||
├── perf_test_results.log
|
||||
├── tests_<LONG_STRING>
|
||||
│ ├── api_response_times.txt
|
||||
│ ├── download_time.txt
|
||||
│ └── ping_results.txt
|
||||
├── timeout
|
||||
└── two_hop_perf_test_results.log
|
||||
```
|
||||
10. When the tests are finished, remove the `nym-vpn-cli` binary from the folder and compress the entire folder as `nym-vpn-tests.zip` (both of these can be done in your graphical environment)
|
||||
11. Upload this compressed file to the [form]({{nym_vpn_form_url}}) drop field when prompted
|
||||
|
||||
#### tests.sh
|
||||
|
||||
This is the testing script which needs to be copied and saved as `tests.sh` to your `nym-vpn-tests` folder and then run from there as described [above](#steps-to-test-nymvpn).
|
||||
|
||||
```sh
|
||||
#!/bin/bash
|
||||
|
||||
ENDPOINT="https://sandbox-nym-api1.nymtech.net/api/v1/gateways/described"
|
||||
json_array=()
|
||||
echo "🚀 🏎 - please be patient, i'm fetching you your entry points - 🚀 🏎 "
|
||||
|
||||
data=$(curl -s "$ENDPOINT" | jq -c '.[] | {host: .bond.gateway.host, hostname: .self_described.host_information.hostname, identity_key: .bond.gateway.identity_key, exitGateway: .self_described.ip_packet_router.address}')
|
||||
|
||||
while IFS= read -r entry; do
|
||||
host=$(echo "$entry" | jq -r '.host')
|
||||
hostname=$(echo "$entry" | jq -r '.hostname')
|
||||
identity_key=$(echo "$entry" | jq -r '.identity_key')
|
||||
exit_gateway_address=$(echo "$entry" | jq -r '.exitGateway // empty')
|
||||
valid_ip=$(echo "$host")
|
||||
|
||||
if [ -n "$exit_gateway_address" ]; then
|
||||
exit_gateway="{\"address\": \"${exit_gateway_address}\"}"
|
||||
else
|
||||
exit_gateway="{}"
|
||||
fi
|
||||
if [[ $valid_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
country_info=$(curl -s "http://ipinfo.io/${valid_ip}/country" | tr -d '\n')
|
||||
country_info_escaped=$(echo "$country_info" | tr -d '\n' | jq -aRs . | tr -d '"')
|
||||
else
|
||||
country_info_escaped=""
|
||||
fi
|
||||
json_object="{\"hostname\": \"${hostname}\", \"identityKey\": \"${identity_key}\", \"exitGateway\": ${exit_gateway}, \"location\": \"${country_info_escaped}\"}"
|
||||
json_array+=("$json_object")
|
||||
done < <(echo "$data")
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "error fetching data from endpoint"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
download_file() {
|
||||
local file_url=$1
|
||||
local output_file=$2
|
||||
local time_file=$3
|
||||
|
||||
echo "starting download speed test..."
|
||||
local start_time=$(date +%s)
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
wget -O $output_file $file_url
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
curl -o $output_file $file_url
|
||||
fi
|
||||
local end_time=$(date +%s)
|
||||
local elapsed_time=$((end_time - start_time))
|
||||
echo "download speed test completed in $elapsed_time seconds." >"$time_file"
|
||||
}
|
||||
|
||||
if ! command -v jq &>/dev/null; then
|
||||
echo "jq is not installed. Please install jq to proceed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
temp_log_file="temp_log.txt"
|
||||
|
||||
perform_tests() {
|
||||
local gateway_id=$1
|
||||
local exit_address=$2
|
||||
local test_directory="tests_${gateway_id}_${exit_address}"
|
||||
local file_url="http://ipv4.download.thinkbroadband.com/2MB.zip"
|
||||
|
||||
mkdir -p "$test_directory"
|
||||
local ping_results_file="${test_directory}/ping_results.txt"
|
||||
local download_time_file="${test_directory}/download_time.txt"
|
||||
local api_response_file="${test_directory}/api_response_times.txt"
|
||||
|
||||
# ping test
|
||||
echo "starting ping test..."
|
||||
for site in google.com youtube.com facebook.com baidu.com wikipedia.org amazon.com twitter.com instagram.com yahoo.com ebay.com netflix.com; do
|
||||
ping -c 4 $site >>"$ping_results_file"
|
||||
done
|
||||
echo "ping test completed. Results saved in $ping_results_file"
|
||||
|
||||
# download speed test
|
||||
download_file $file_url /dev/null "$download_time_file"
|
||||
|
||||
# api test
|
||||
local api_endpoint="https://validator.nymtech.net/api/v1/mixnodes"
|
||||
local iterations=10
|
||||
>"$api_response_file"
|
||||
for i in $(seq 1 $iterations); do
|
||||
local start_time=$(date +%s)
|
||||
local response=$(curl -s -o /dev/null -w '%{http_code}' $api_endpoint)
|
||||
local end_time=$(date +%s)
|
||||
|
||||
local elapsed_seconds=$((end_time - start_time))
|
||||
local hours=$((elapsed_seconds / 3600))
|
||||
local minutes=$(((elapsed_seconds % 3600) / 60))
|
||||
local seconds=$((elapsed_seconds % 60))
|
||||
|
||||
local human_readable_time=$(printf "%02dh:%02dm:%02ds" $hours $minutes $seconds)
|
||||
echo "iteration $i: response Time = ${human_readable_time}, status code = $response" >>"$api_response_file"
|
||||
done
|
||||
echo "api response test completed. Results saved in $api_response_file."
|
||||
}
|
||||
|
||||
printf "%s\n" "${json_array[@]}" | jq -s .
|
||||
|
||||
read -p "enter a gateway ID: " identity_key
|
||||
read -p "enter an exit address: " exit_address
|
||||
|
||||
while true; do
|
||||
read -p "enable WireGuard? (yes/no): " enable_wireguard
|
||||
enable_wireguard=$(echo "$enable_wireguard" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
case "$enable_wireguard" in
|
||||
"yes")
|
||||
read -p "enter your WireGuard private key: " priv_key
|
||||
read -p "enter your WireGuard IP: " wg_ip
|
||||
wireguard_options="--enable-wireguard --private-key $priv_key --wg-ip $wg_ip"
|
||||
break
|
||||
;;
|
||||
"no")
|
||||
wireguard_options=""
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "invalid response. please enter 'yes' or 'no'."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
sudo ./nym-vpn-cli -c sandbox.env --entry-gateway-id ${identity_key} --exit-router-address ${exit_address} --enable-two-hop $wireguard_options >"$temp_log_file" 2>&1 &
|
||||
|
||||
timeout=15
|
||||
start_time=$(date +%s)
|
||||
while true; do
|
||||
current_time=$(date +%s)
|
||||
if grep -q "received plain" "$temp_log_file"; then
|
||||
echo "successful configuration with identity_key: $identity_key and exit address: $exit_address" >>perf_test_results.log
|
||||
perform_tests "$identity_key" "$exit_address"
|
||||
break
|
||||
fi
|
||||
if ((current_time - start_time > timeout)); then
|
||||
echo "failed to connect with identity_key: $identity_key using the exit address: $exit_address" >>perf_test_results.log
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "terminating nym-vpn-cli..."
|
||||
pkill -f './nym-vpn-cli'
|
||||
sleep 5
|
||||
rm -f "$temp_log_file"
|
||||
|
||||
```
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
As a general approach, licensing is as follows this pattern:
|
||||
|
||||
* <p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://nymtech.net/docs">Nym Documentation</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://nymtech.net">Nym Technologies</a> is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1"></a></p>
|
||||
* <p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://nym.com/docs">Nym Documentation</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://nym.com">Nym Technologies</a> is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1"></a></p>
|
||||
|
||||
* Nym applications and binaries are [GPL-3.0-only](https://www.gnu.org/licenses/)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ make
|
||||
```
|
||||
|
||||
## Mnemonic Generation
|
||||
Create an account at [nymvpn.com](nymvpn.com) to obtain your mnemonic.
|
||||
Create an account at [nymvpn.com](https://nymvpn.com) to obtain your mnemonic.
|
||||
|
||||
## Start the daemon
|
||||
```sh
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"development-status": "Development Status",
|
||||
"mixnet": "Mixnet Module",
|
||||
"tcpproxy": "TcpProxy Module",
|
||||
"client-pool": "Client Pool",
|
||||
"ffi": "FFI",
|
||||
"tutorials": "Tutorials (Coming Soon)"
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# Client Pool
|
||||
|
||||
We have a configurable-size Client Pool for processes that require multiple clients in quick succession (this is used by default by the [`TcpProxyClient`](./tcpproxy) for instance)
|
||||
|
||||
This will be useful for developers looking to build connection logic, or just are using raw SDK clients in a sitatuation where there are multiple connections with a lot of churn.
|
||||
|
||||
> You can find this code [here](https://github.com/nymtech/nym/blob/develop/sdk/rust/nym-sdk/examples/client_pool.rs)
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"architecture": "Architecture",
|
||||
"example": "Example"
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
# Client Pool Architecture
|
||||
|
||||
## Motivations
|
||||
In situations where multiple connections are expected, and the number of connections can vary greatly, the Client Pool reduces time spent waiting for the creation of a Mixnet Client blocking your code sending traffic through the Mixnet. Instead, a configurable number of Clients can be generated and run in the background which can be very quickly grabbed, used, and disconnected.
|
||||
|
||||
The Pool can be simply run as a background process for the runtime of your program.
|
||||
|
||||
## Clients & Lifetimes
|
||||
The Client Pool creates **ephemeral Mixnet Clients** which are used and then disconnected. Using the [`TcpProxy`](../tcpproxy) as an example, Clients are used for the lifetime of a single incoming TCP connection; after the TCP connection is closed, the Mixnet client is disconnected.
|
||||
|
||||
Clients are popped from the pool when in use, and another Client is created to take its place. If connections are coming in faster than Clients are replenished, you can instead generate an ephemeral Client on the fly, or wait; this is up to the developer to decide. You can see an example of this logic in the example on the next page.
|
||||
|
||||
## Runtime Loop
|
||||
Aside from a few helper / getter functions and a graceful `disconnect_pool()`, the Client Pool is mostly made up of a very simple loop around some conditional logic making up `start()`:
|
||||
- if the number of Clients in the pool is `< client_pool_reserve_number` (set on `new()`) then create more,
|
||||
- if the number of Clients in the pool `== client_pool_reserve_number` (set on `new()`) then `sleep`,
|
||||
- if `client_pool_reserve_number == 0` just `sleep`.
|
||||
|
||||
`disconnect_pool()` will cause this loop to `break` via cancellation token.
|
||||
@@ -1,100 +0,0 @@
|
||||
# Client Pool Example
|
||||
|
||||
> You can find this code [here](https://github.com/nymtech/nym/blob/develop/sdk/rust/nym-sdk/examples/client_pool.rs)
|
||||
|
||||
```rust
|
||||
use anyhow::Result;
|
||||
use nym_network_defaults::setup_env;
|
||||
use nym_sdk::client_pool::ClientPool;
|
||||
use nym_sdk::mixnet::{MixnetClientBuilder, NymNetworkDetails};
|
||||
use tokio::signal::ctrl_c;
|
||||
|
||||
// This client pool is used internally by the TcpProxyClient but can also be used by the Mixnet module, in case you're quickly swapping clients in and out but won't want to use the TcpProxy module.
|
||||
//
|
||||
// Run with: cargo run --example client_pool -- ../../../envs/<NETWORK>.env
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
nym_bin_common::logging::setup_logging();
|
||||
setup_env(std::env::args().nth(1));
|
||||
|
||||
let conn_pool = ClientPool::new(2); // Start the Client Pool with 2 Clients always being kept in reserve
|
||||
let client_maker = conn_pool.clone();
|
||||
tokio::spawn(async move {
|
||||
client_maker.start().await?;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
|
||||
println!("\n\nWaiting a few seconds to fill pool\n\n");
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
|
||||
|
||||
let pool_clone_one = conn_pool.clone();
|
||||
let pool_clone_two = conn_pool.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let client_one = match pool_clone_one.get_mixnet_client().await {
|
||||
Some(client) => {
|
||||
println!("Grabbed client {} from pool", client.nym_address());
|
||||
client
|
||||
}
|
||||
None => {
|
||||
println!("Not enough clients in pool, creating ephemeral client");
|
||||
let net = NymNetworkDetails::new_from_env();
|
||||
let client = MixnetClientBuilder::new_ephemeral()
|
||||
.network_details(net)
|
||||
.build()?
|
||||
.connect_to_mixnet()
|
||||
.await?;
|
||||
println!(
|
||||
"Using {} for the moment, created outside of the connection pool",
|
||||
client.nym_address()
|
||||
);
|
||||
client
|
||||
}
|
||||
};
|
||||
let our_address = client_one.nym_address();
|
||||
println!("\n\nClient 1: {our_address}\n\n");
|
||||
client_one.disconnect().await;
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await; // Emulate doing something
|
||||
return Ok::<(), anyhow::Error>(());
|
||||
});
|
||||
|
||||
tokio::spawn(async move {
|
||||
let client_two = match pool_clone_two.get_mixnet_client().await {
|
||||
Some(client) => {
|
||||
println!("Grabbed client {} from pool", client.nym_address());
|
||||
client
|
||||
}
|
||||
None => {
|
||||
println!("Not enough clients in pool, creating ephemeral client");
|
||||
let net = NymNetworkDetails::new_from_env();
|
||||
let client = MixnetClientBuilder::new_ephemeral()
|
||||
.network_details(net)
|
||||
.build()?
|
||||
.connect_to_mixnet()
|
||||
.await?;
|
||||
println!(
|
||||
"Using {} for the moment, created outside of the connection pool",
|
||||
client.nym_address()
|
||||
);
|
||||
client
|
||||
}
|
||||
};
|
||||
let our_address = *client_two.nym_address();
|
||||
println!("\n\nClient 2: {our_address}\n\n");
|
||||
client_two.disconnect().await;
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await; // Emulate doing something
|
||||
return Ok::<(), anyhow::Error>(());
|
||||
});
|
||||
|
||||
wait_for_ctrl_c(conn_pool).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn wait_for_ctrl_c(pool: ClientPool) -> Result<()> {
|
||||
println!("\n\nPress CTRL_C to disconnect pool\n\n");
|
||||
ctrl_c().await?;
|
||||
println!("CTRL_C received. Killing client pool");
|
||||
pool.disconnect_pool().await;
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
@@ -7,12 +7,9 @@ In the future the SDK will be made up of several modules, each of which will all
|
||||
|-----------|---------------------------------------------------------------------------------------|----------|
|
||||
| Mixnet | Create / load clients & keypairs, subscribe to Mixnet events, send & receive messages | ✔️ |
|
||||
| TcpProxy | Utilise the TcpProxyClient and TcpProxyServer abstractions for streaming | ✔️ |
|
||||
| ClientPool| Create a pool of quickly useable Mixnet clients | ✔️ |
|
||||
| Ecash | Create & verify Ecash credentials | ❌ |
|
||||
| Validator | Sign & broadcast Nyx blockchain transactions, query the blockchain | ❌ |
|
||||
|
||||
The `Mixnet` module currently exposes the logic of two clients: the [websocket client](../clients/websocket), and the [socks client](../clients/socks5).
|
||||
|
||||
The `TcpProxy` module exposes functionality to set up client/server instances that expose a localhost TcpSocket to read/write to.
|
||||
|
||||
The `ClientPool` is a configurable pool of ephemeral clients which can be created as a background process and quickly grabbed.
|
||||
|
||||
@@ -22,7 +22,7 @@ The main functionality of exposed functions will be imported from `sdk/ffi/share
|
||||
|
||||
Furthermore, the `shared/` code makes sure that client access is thread-safe, and that client actions happen in blocking threads on the Rust side of the FFI boundary.
|
||||
|
||||
## Mixnet Module
|
||||
### Mixnet Module
|
||||
This is the basic mixnet component of the SDK, exposing client functionality with which people can build custom interfaces with the Mixnet. These functions are exposed to both Go and C/C++ via the `sdk/ffi/shared/` crate.
|
||||
|
||||
| `shared/lib.rs` function | Rust Function |
|
||||
@@ -36,13 +36,13 @@ This is the basic mixnet component of the SDK, exposing client functionality wit
|
||||
|
||||
> We have also implemented `listen_for_incoming_internal()` which is a wrapper around the Mixnet client's `wait_for_messages()`. This is a helper method for listening out for and handling incoming messages.
|
||||
|
||||
### Currently Unsupported Functionality
|
||||
#### Currently Unsupported Functionality
|
||||
At the time of writing the following functionality is not exposed to the shared FFI library:
|
||||
- `split_sender()`: the ability to [split a client into sender and receiver](./mixnet/examples/split-send) for concurrent send/receive.
|
||||
- The use of [custom network topologies](./mixnet/examples/custom-topology).
|
||||
- `Socks5::new()`: creation and use of the [socks5/4a/4 proxy client](./mixnet/examples/socks).
|
||||
|
||||
## TcpProxy Module
|
||||
### TcpProxy Module
|
||||
A connection abstraction which exposes a local TCP socket which developers are able to interact with basically as expected, being able to read/write to/from a bytestream, without really having to take into account the workings of the Mixnet/Sphinx/the [message-based](../concepts/messages) format of the underlying client.
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
@@ -58,6 +58,3 @@ A connection abstraction which exposes a local TCP socket which developers are a
|
||||
| `proxy_server_new_internal(upstream_address: &str, config_dir: &str, env: Option<String>)` | `NymProxyServer::new(upstream_address, config_dir, env)` |
|
||||
| `proxy_server_run_internal()` | `NymProxyServer.run_with_shutdown()` |
|
||||
| `proxy_server_address_internal()` | `NymProxyServer.nym_address()` |
|
||||
|
||||
## Client Pool
|
||||
There are currently no FFI bindings for the Client Pool. This will be coming in the future. The bindings for the TcpProxy have been updated to be able to use the Client Pool under the hood, but the standalone Pool is not yet exposed to FFI.
|
||||
|
||||
@@ -29,7 +29,7 @@ async fn main() {
|
||||
println!("Sending socks5-wrapped http request");
|
||||
// Message should be sent through the mixnet, via socks5
|
||||
// We don't expect to get anything, as there is no network requester on the other end
|
||||
reqwest_client.get("https://nymtech.net").send().await.ok()
|
||||
reqwest_client.get("https://nym.com").send().await.ok()
|
||||
});
|
||||
|
||||
println!("Waiting for message");
|
||||
|
||||
@@ -112,6 +112,3 @@ Whether the `data` of a SURB request being empty is a feature or a bug is to be
|
||||
You can find a few helper functions [here](./message-helpers.md) to help deal with this issue in the meantime.
|
||||
|
||||
> If you can think of a more succinct or different way of handling this do reach out - we're happy to hear other opinions
|
||||
|
||||
## Lots of `duplicate fragment received` messages
|
||||
You might see a lot of `WARN` level logs about duplicate fragments in your logs, depending on the log level you're using. This occurs when a packet is retransmitted somewhere in the Mixnet, but then the original makes it to the destination client as well. This is not something to do with your client logic, but instead the state of the Mixnet.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"architecture": "Architecture",
|
||||
"examples": "Examples",
|
||||
"troubleshooting": "Troubleshooting"
|
||||
"examples": "Examples"
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ The motivation behind the creation of the `TcpProxy` module is to allow develope
|
||||
|
||||
## Clients
|
||||
Each of the sub-modules exposed by the `TcpProxy` deal with Nym clients in a different way.
|
||||
- the `NymProxyClient` relies on the [`Client Pool`](../client-pool) to create clients and keep a certain number of them in reserve. If the amount of incoming TCP connections rises quicker than the Client Pool can create clients, or you have the pool size set to `0`, the `TcpProxyClient` creates an ephemeral client per new TCP connection, which is closed according to the configurable timeout: we map one ephemeral client per TCP connection. This is to deal with multiple simultaneous streams.
|
||||
- the `NymProxyClient` creates an ephemeral client per new TCP connection, which is closed according to the configurable timeout: we map one ephemeral client per TCP connection. This is to deal with multiple simultaneous streams. In the future, this will be superceded by a connection pool in order to speed up new connections.
|
||||
- the `NymProxyServer` has a single Nym client with a persistent identity.
|
||||
|
||||
## Framing
|
||||
|
||||
@@ -18,8 +18,6 @@ use tokio::net::TcpStream;
|
||||
use tokio::signal;
|
||||
use tokio_stream::StreamExt;
|
||||
use tokio_util::codec;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct ExampleMessage {
|
||||
@@ -28,8 +26,6 @@ struct ExampleMessage {
|
||||
tcp_conn: i8,
|
||||
}
|
||||
|
||||
// This example just starts off a bunch of Tcp connections on a loop to a remote endpoint: in this case the TcpListener behind the NymProxyServer instance on the echo server found in `nym/tools/echo-server/`. It pipes a few messages to it, logs the replies, and keeps track of the number of replies received per connection.
|
||||
//
|
||||
// To run:
|
||||
// - run the echo server with `cargo run`
|
||||
// - run this example with `cargo run --example tcp_proxy_multistream -- <ECHO_SERVER_NYM_ADDRESS> <ENV_FILE_PATH> <CLIENT_PORT>` e.g.
|
||||
@@ -44,13 +40,8 @@ async fn main() -> anyhow::Result<()> {
|
||||
// Nym client logging is very informative but quite verbose.
|
||||
// The Message Decay related logging gives you an ideas of the internals of the proxy message ordering: you need to switch
|
||||
// to DEBUG to see the contents of the msg buffer, sphinx packet chunking, etc.
|
||||
tracing_subscriber::registry()
|
||||
.with(fmt::layer())
|
||||
.with(
|
||||
EnvFilter::new("info")
|
||||
.add_directive("nym_sdk::client_pool=info".parse().unwrap())
|
||||
.add_directive("nym_sdk::tcp_proxy_client=debug".parse().unwrap()),
|
||||
)
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(tracing::Level::INFO)
|
||||
.init();
|
||||
|
||||
let env_path = env::args().nth(2).expect("Env file not specified");
|
||||
@@ -58,42 +49,23 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
let listen_port = env::args().nth(3).expect("Port not specified");
|
||||
|
||||
// Within the TcpProxyClient, individual client shutdown is triggered by the timeout. The final argument is how many clients to keep in reserve in the client pool when running the TcpProxy.
|
||||
// Within the TcpProxyClient, individual client shutdown is triggered by the timeout.
|
||||
let proxy_client =
|
||||
tcp_proxy::NymProxyClient::new(server, "127.0.0.1", &listen_port, 45, Some(env), 2).await?;
|
||||
|
||||
// For our disconnect() logic below
|
||||
let proxy_clone = proxy_client.clone();
|
||||
tcp_proxy::NymProxyClient::new(server, "127.0.0.1", &listen_port, 45, Some(env)).await?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
proxy_client.run().await?;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
|
||||
let example_cancel_token = CancellationToken::new();
|
||||
let client_cancel_token = example_cancel_token.clone();
|
||||
let watcher_cancel_token = example_cancel_token.clone();
|
||||
|
||||
// Cancel listener thread
|
||||
tokio::spawn(async move {
|
||||
signal::ctrl_c().await?;
|
||||
println!(":: CTRL_C received, shutting down + cleanup up proxy server config files");
|
||||
watcher_cancel_token.cancel();
|
||||
proxy_clone.disconnect().await;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
|
||||
println!("waiting for everything to be set up..");
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||
println!("done. sending bytes");
|
||||
|
||||
// In the info traces you will see the different session IDs being set up, one for each TcpStream.
|
||||
for i in 0..8 {
|
||||
let client_cancel_inner_token = client_cancel_token.clone();
|
||||
if client_cancel_token.is_cancelled() {
|
||||
break;
|
||||
}
|
||||
for i in 0..4 {
|
||||
let conn_id = i;
|
||||
println!("Starting TCP connection {}", conn_id);
|
||||
let local_tcp_addr = format!("127.0.0.1:{}", listen_port.clone());
|
||||
tokio::spawn(async move {
|
||||
// Now the client and server proxies are running we can create and pipe traffic to/from
|
||||
@@ -109,10 +81,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
// Lets just send a bunch of messages to the server with variable delays between them, with a message and tcp connection ids to keep track of ordering on the server side (for illustrative purposes **only**; keeping track of anonymous replies is handled by the proxy under the hood with Single Use Reply Blocks (SURBs); for this illustration we want some kind of app-level message id, but irl most of the time you'll probably be parsing on e.g. the incoming response type instead)
|
||||
tokio::spawn(async move {
|
||||
for i in 0..8 {
|
||||
if client_cancel_inner_token.is_cancelled() {
|
||||
break;
|
||||
}
|
||||
for i in 0..4 {
|
||||
let mut rng = SmallRng::from_entropy();
|
||||
let delay: f64 = rng.gen_range(2.5..5.0);
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs_f64(delay)).await;
|
||||
@@ -127,7 +96,12 @@ async fn main() -> anyhow::Result<()> {
|
||||
.write_all(&serialised)
|
||||
.await
|
||||
.expect("couldn't write to stream");
|
||||
println!(">> client sent msg {} on conn {}", &i, &conn_id);
|
||||
println!(
|
||||
">> client sent {}: {} bytes on conn {}",
|
||||
&i,
|
||||
msg.message_bytes.len(),
|
||||
&conn_id
|
||||
);
|
||||
}
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
@@ -139,8 +113,17 @@ async fn main() -> anyhow::Result<()> {
|
||||
while let Some(Ok(bytes)) = framed_read.next().await {
|
||||
match bincode::deserialize::<ExampleMessage>(&bytes) {
|
||||
Ok(msg) => {
|
||||
println!(
|
||||
"<< client received {}: {} bytes on conn {}",
|
||||
msg.message_id,
|
||||
msg.message_bytes.len(),
|
||||
msg.tcp_conn
|
||||
);
|
||||
reply_counter += 1;
|
||||
println!("<< conn {} received {}/8", msg.tcp_conn, reply_counter);
|
||||
println!(
|
||||
"tcp connection {} replies received {}/4",
|
||||
msg.tcp_conn, reply_counter
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("<< client received something that wasn't an example message of {} bytes. error: {}", bytes.len(), e);
|
||||
@@ -155,12 +138,15 @@ async fn main() -> anyhow::Result<()> {
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs_f64(delay)).await;
|
||||
}
|
||||
|
||||
// Once timeout is passed, you can either wait for graceful shutdown or just hard stop it.
|
||||
signal::ctrl_c().await?;
|
||||
println!("CTRL+C received, shutting down");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// emulate a series of small messages followed by a closing larger one
|
||||
fn gen_bytes_fixed(i: usize) -> Vec<u8> {
|
||||
let amounts = [10, 15, 50, 1000, 10, 15, 500, 2000];
|
||||
let amounts = [10, 15, 50, 1000];
|
||||
let len = amounts[i];
|
||||
let mut rng = rand::thread_rng();
|
||||
(0..len).map(|_| rng.gen::<u8>()).collect()
|
||||
|
||||
@@ -21,8 +21,6 @@ use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::signal;
|
||||
use tokio_stream::StreamExt;
|
||||
use tokio_util::codec;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct ExampleMessage {
|
||||
@@ -30,14 +28,7 @@ struct ExampleMessage {
|
||||
message_bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
// This is a basic example which opens a single TCP connection and writes a bunch of messages between a client and an echo
|
||||
// server, so only uses a single session under the hood and doesn't really show off the message ordering capabilities; this is mainly
|
||||
// just a quick introductory illustration on how:
|
||||
// - the mixnet does message ordering
|
||||
// - the NymProxyClient and NymProxyServer can be hooked into and used to communicate between two otherwise pretty vanilla TcpStreams
|
||||
//
|
||||
// For a more irl example checkout tcp_proxy_multistream.rs
|
||||
//
|
||||
|
||||
// Run this with:
|
||||
// `cargo run --example tcp_proxy_single_connection <SERVER_LISTEN_PORT> <ENV_FILE_PATH> <CLIENT_LISTEN_PATH>` e.g.
|
||||
// `cargo run --example tcp_proxy_single_connection 8081 ../../../envs/canary.env 8080 `
|
||||
@@ -48,9 +39,8 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
// Comment this out to just see println! statements from this example, as Nym client logging is very informative but quite verbose.
|
||||
// The Message Decay related logging gives you an ideas of the internals of the proxy message ordering. To see the contents of the msg buffer, sphinx packet chunking, etc change the tracing::Level to DEBUG.
|
||||
tracing_subscriber::registry()
|
||||
.with(fmt::layer())
|
||||
.with(EnvFilter::new("nym_sdk::tcp_proxy=info"))
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(tracing::Level::INFO)
|
||||
.init();
|
||||
|
||||
let server_port = env::args()
|
||||
@@ -73,14 +63,10 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
// We'll run the instance with a long timeout since we're sending everything down the same Tcp connection, so should be using a single session.
|
||||
// Within the TcpProxyClient, individual client shutdown is triggered by the timeout.
|
||||
// The final argument is how many clients to keep in reserve in the client pool when running the TcpProxy.
|
||||
let proxy_client =
|
||||
tcp_proxy::NymProxyClient::new(*proxy_nym_addr, "127.0.0.1", &client_port, 5, Some(env), 1)
|
||||
tcp_proxy::NymProxyClient::new(*proxy_nym_addr, "127.0.0.1", &client_port, 60, Some(env))
|
||||
.await?;
|
||||
|
||||
// For our disconnect() logic below
|
||||
let proxy_clone = proxy_client.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
proxy_server.run_with_shutdown().await?;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
@@ -91,28 +77,10 @@ async fn main() -> anyhow::Result<()> {
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
|
||||
let example_cancel_token = CancellationToken::new();
|
||||
let server_cancel_token = example_cancel_token.clone();
|
||||
let client_cancel_token = example_cancel_token.clone();
|
||||
let watcher_cancel_token = example_cancel_token.clone();
|
||||
|
||||
// Cancel listener thread
|
||||
tokio::spawn(async move {
|
||||
signal::ctrl_c().await?;
|
||||
println!(":: CTRL_C received, shutting down + cleanup up proxy server config files");
|
||||
fs::remove_dir_all(conf_path)?;
|
||||
watcher_cancel_token.cancel();
|
||||
proxy_clone.disconnect().await;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
|
||||
// 'Server side' thread: echo back incoming as response to the messages sent in the 'client side' thread below
|
||||
tokio::spawn(async move {
|
||||
let listener = TcpListener::bind(upstream_tcp_addr).await?;
|
||||
loop {
|
||||
if server_cancel_token.is_cancelled() {
|
||||
break;
|
||||
}
|
||||
let (socket, _) = listener.accept().await.unwrap();
|
||||
let (read, mut write) = socket.into_split();
|
||||
let codec = codec::BytesCodec::new();
|
||||
@@ -150,9 +118,9 @@ async fn main() -> anyhow::Result<()> {
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
|
||||
// Just wait for Nym clients to connect, TCP clients to bind, etc. If there isn't a client in the pool (or you started it with 0) already then the TcpProxyClient just spins up an ephemeral client itself.
|
||||
// Just wait for Nym clients to connect, TCP clients to bind, etc.
|
||||
println!("waiting for everything to be set up..");
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||
println!("done. sending bytes");
|
||||
|
||||
// Now the client and server proxies are running we can create and pipe traffic to/from
|
||||
@@ -172,9 +140,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
tokio::spawn(async move {
|
||||
let mut rng = SmallRng::from_entropy();
|
||||
for i in 0..10 {
|
||||
if client_cancel_token.is_cancelled() {
|
||||
break;
|
||||
}
|
||||
let random_bytes = gen_bytes_fixed(i as usize);
|
||||
let msg = ExampleMessage {
|
||||
message_id: i,
|
||||
@@ -214,12 +179,15 @@ async fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
// Once timeout is passed, you can either wait for graceful shutdown or just hard stop it.
|
||||
signal::ctrl_c().await?;
|
||||
println!(":: CTRL+C received, shutting down + cleanup up proxy server config files");
|
||||
fs::remove_dir_all(conf_path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gen_bytes_fixed(i: usize) -> Vec<u8> {
|
||||
// let amounts = vec![1, 10, 50, 100, 150, 200, 350, 500, 750, 1000];
|
||||
let amounts = [158, 1088, 505, 1001, 150, 200, 3500, 500, 750, 100];
|
||||
let amounts = vec![1, 10, 50, 100, 150, 200, 350, 500, 750, 1000];
|
||||
let len = amounts[i];
|
||||
let mut rng = rand::thread_rng();
|
||||
(0..len).map(|_| rng.gen::<u8>()).collect()
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
## Lots of `duplicate fragment received` messages
|
||||
You might see a lot of `WARN` level logs about duplicate fragments in your logs, depending on the log level you're using. This occurs when a packet is retransmitted somewhere in the Mixnet, but then the original makes it to the destination client as well. This is not something to do with your client logic, but instead the state of the Mixnet.
|
||||
@@ -39,8 +39,6 @@ Options:
|
||||
Listen port [default: 8080]
|
||||
-e, --env-path <ENV_PATH>
|
||||
Optional env filepath - if none is supplied then the proxy defaults to using mainnet else just use a path to one of the supplied files in envs/ e.g. ./envs/sandbox.env
|
||||
--client-pool-reserve <CLIENT_POOL_RESERVE>
|
||||
How many clients to have running in reserve for quick access by incoming connections [default: 2]
|
||||
-h, --help
|
||||
Print help
|
||||
```
|
||||
|
||||
@@ -15,7 +15,7 @@ Sounds great, are there any catches? Well, there are a few (for now):
|
||||
|
||||
- For now, `mixFetch` cannot deal with concurrent requests with the same base URL.
|
||||
|
||||
Read [this article](https://blog.nymtech.net/mixfetch-like-the-fetch-api-but-via-the-mixnet-82acfd435c62) to learn more.
|
||||
Read [this article](https://blog.nym.com/mixfetch-like-the-fetch-api-but-via-the-mixnet-82acfd435c62) to learn more.
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
Right now Gateways are not required to run a Secure Websocket (WSS) listener, so only a subset of nodes running in Gateway mode have configured their nodes to do so.
|
||||
@@ -104,7 +104,7 @@ export function HttpGET() {
|
||||
const [html, setHtml] = React.useState('');
|
||||
async function get() {
|
||||
//Make sure the URL is whitelisted (see 'standard allowed list') otherwise you will get a network requester filter check error
|
||||
const response = await mixFetch('https://nymtech.net/favicon.svg', { mode: 'unsafe-ignore-cors' }, mixFetchOptions);
|
||||
const response = await mixFetch('https://nym.com/favicon.svg', { mode: 'unsafe-ignore-cors' }, mixFetchOptions);
|
||||
const text = await response.text();
|
||||
console.log('response was', text);
|
||||
setHtml(html);
|
||||
|
||||
@@ -9,7 +9,7 @@ Use the [`mixFetch`](https://www.npmjs.com/package/@nymproject/mix-fetch) packag
|
||||
import { mixFetch } from '@nymproject/mix-fetch';
|
||||
|
||||
// HTTP GET
|
||||
const response = await mixFetch('https://nymtech.net');
|
||||
const response = await mixFetch('https://nym.com');
|
||||
const html = await response.text();
|
||||
|
||||
// HTTP POST
|
||||
|
||||
@@ -12,4 +12,4 @@ The blockchain plays a supporting but fundamental role in the mixnet: the `NYM`
|
||||
|
||||
## Further Reading
|
||||
* Detailed info on Nyx Validators and token flow can be found in [Nym Reward Sharing for Mixnets document](https://nymtech.net/nym-cryptoecon-paper.pdf) in section 2.3 and 2.4.
|
||||
* [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) section 3.1
|
||||
* [Nym Whitepaper](https://nym.com/nym-whitepaper.pdf) section 3.1
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
>
|
||||
> SURBs are the Sphinx equivalent of "onion addresses" in Tor, with the caveat that a SURB can only be used once (to prevent replay attacks) and within its epoch of validity (the mix node public keys used to prepare the SURB are only valid for a limited period). SURB headers are encrypted by the sender, so the recipient sending it back cannot infer from it any information about the message route, the per-hop latency, or the sender’s address, which is encoded in the innermost (last) routing layer of the SURB. SURBs ('Single Use Reply Blocks') allow clients to reply to incoming messages anonymously.
|
||||
>
|
||||
> [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) §4.5
|
||||
> [Nym Whitepaper](https://nym.com/nym-whitepaper.pdf) §4.5
|
||||
|
||||
It will often be the case that a client app wants to interact with a service of some kind, or a P2P application on someone else's machine. It defeats the purpose of the whole system if a client app needs to reveal its own gateway public key and client public key in order to get a response.
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
> The Nym mixnet generates cover traffic "loops" ... [l]oops generated by mix nodes ensure a minimum level of anonymity at all times, while end users can generate loops to obfuscate the timing and volume of their active communication through Nym and thus achieve unobservability.
|
||||
>
|
||||
> [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) §4
|
||||
> [Nym Whitepaper](https://nym.com/nym-whitepaper.pdf) §4
|
||||
|
||||
In order to avoid timing attacks where an attacker tries to deanonymise which clients are communicating with each other, cover traffic is implemented. As soon as any client is connected to the mixnet, they will send [Sphinx](../cryptography/sphinx) packets in 'loops' between nodes at a steady rate, inserting packets containing actual payload data (i.e. actual messages being sent between clients) when they are available.
|
||||
|
||||
In this way, Sphinx packets containing actual payload data are hidden in a steady stream of 'background noise' in the form of 'cover' Sphinx packets with empty payloads, but which are indistinguishable to an observer.
|
||||
|
||||
An in-depth explainer can be found in §4.6 of the [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf).
|
||||
An in-depth explainer can be found in §4.6 of the [Nym Whitepaper](https://nym.com/nym-whitepaper.pdf).
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
>
|
||||
> Cover traffic disguises real traffic patterns by adding “dummy” messages that carry no payload data and are simply discarded at their final destination. While routing a message, mix nodes cannot distinguish whether it is a dummy message or a normal message carrying user data. Routing dummy traffic to circle back to the sender rather than ending at a randomly chosen destination was originally proposed to proactively detect active attacks on mixnets. Loopix, the name of which refers to its use of "loops" of dummy traffic, extends this approach to guarantee both a lower bound on anonymity and unobservability properties for end users. Nym follows a similar approach, with participants generating dummy messages that travel in a loop and have themselves as final destination.
|
||||
>
|
||||
> [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) §4.6
|
||||
> [Nym Whitepaper](https://nym.com/nym-whitepaper.pdf) §4.6
|
||||
|
||||
The Nym Mixnet is based upon the [Loopix](https://arxiv.org/pdf/1703.00536) design.
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@ description: Mixnets are networks of nodes that route traffic in a way that make
|
||||
|
||||
> Continuous-time mixing strategies ... delay each message independently, forwarding it to its next destination once a specified delay has timed out. The aggregate effect of independently delaying each message is an output sequence of messages that is randomly reordered with respect to the input sequence.
|
||||
>
|
||||
> [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) §4.4
|
||||
> [Nym Whitepaper](https://nym.com/nym-whitepaper.pdf) §4.4
|
||||
|
||||
Mixnets are networks of nodes that route traffic in a way that makes it untraceable, even for Global Passive Adversaries employing Machine Learning to try and deanonymise traffic based on timing and fingerprinting attacks.
|
||||
|
||||
One of the key features of a Mixnet - unsurprisingly - is that these nodes 'mix' traffic. As traffic moves through the network, each node, on receiving a message, will wait a variable length amount of time before sending it onwards - aka nodes do **not** pass messages on in a FIFO manner. An easy analogy is each node constantly receiving and sending out cards, shuffling their local deck each time and randomly selecting a card to pass along in the chain of messages.
|
||||
|
||||
The Mixnet employs continuous-time mixing, in which each message is dealt with independently of the other messages in the node's local storage. This is in contrast to other Mixnet designs which rely on nodes sending out periodic bursts of accrued messages, such as the Chaumian Mixnet design _"which collects a number of input messages and outputs a random permutation of those messages, is known to suffer from some disadvantages: the end-to-end latency of messages in such mixnets is neither bounded nor predictable, and the bursty communication caused by periodically flushing batches of messages makes these mix designs inefficient at utilizing bandwidth. In terms of anonymity, simple batching strategies are known to offer low anonymity as well as being particularly vulnerable to attacks"_ ([Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) §4.4)
|
||||
The Mixnet employs continuous-time mixing, in which each message is dealt with independently of the other messages in the node's local storage. This is in contrast to other Mixnet designs which rely on nodes sending out periodic bursts of accrued messages, such as the Chaumian Mixnet design _"which collects a number of input messages and outputs a random permutation of those messages, is known to suffer from some disadvantages: the end-to-end latency of messages in such mixnets is neither bounded nor predictable, and the bursty communication caused by periodically flushing batches of messages makes these mix designs inefficient at utilizing bandwidth. In terms of anonymity, simple batching strategies are known to offer low anonymity as well as being particularly vulnerable to attacks"_ ([Nym Whitepaper](https://nym.com/nym-whitepaper.pdf) §4.4)
|
||||
|
||||
Continuous-time mixing, in contrast:
|
||||
- _"offer[s] optimal anonymity properties for a given mean end-to-end latency"_ due to the per-message randomised delay amount: by using an exponential delay distribution, we acheive a situation in which _"if we observe two messages going into the mix node at times t0 < t1, and a message coming out at a later time t2, the probability that the output is any of the two inputs is equal, regardless of
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
As a general approach, licensing is as follows this pattern:
|
||||
|
||||
* <p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://nymtech.net/docs">Nym Documentation</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://nymtech.net">Nym Technologies</a> is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1"></a></p>
|
||||
* <p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://nym.com/docs">Nym Documentation</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://nym.com">Nym Technologies</a> is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1"></a></p>
|
||||
|
||||
* Nym applications and binaries are [GPL-3.0-only](https://www.gnu.org/licenses/)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
>
|
||||
> Nym uses the Sphinx packet format to encapsulate and anonymously route data payloads. Senders prepare Sphinx messages by encrypting them multiple times in reverse routing order. First, a message is encrypted for the recipient; then, for the last mix node in the path; then, for its predecessors in the path, ending with the outermost encryption, which corresponds to the mix node in the first layer. The complete Sphinx packet is finally encrypted with a key shared with the gateway, which forwards decrypted Sphinx packets to the mixnet.
|
||||
>
|
||||
> [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) §4
|
||||
> [Nym Whitepaper](https://nym.com/nym-whitepaper.pdf) §4
|
||||
|
||||
The Nym mixnet re-orders encrypted, indistinguishable [Sphinx](cryptography/sphinx) packets as they travel through the network.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Callout } from 'nextra/components'
|
||||
> ...
|
||||
>
|
||||
> A SURB effectively contains: (1) the encrypted headers of a Sphinx message that, if sent to the mixnet, will be routed back to the original sender; (2) the address of the first-layer mix node where the message should be sent; and (3) a cryptographic key to encrypt the reply payload.
|
||||
> [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) §4.5
|
||||
> [Nym Whitepaper](https://nym.com/nym-whitepaper.pdf) §4.5
|
||||
|
||||
As outlined in the [concepts](../concepts/anonymous-replies) section, SURBs are layer encrypted sets of Sphinx headers detailing a reply path ending in the sending client's [Nym address](../traffic/addressing-system). Clients receiving messages with SURBs attached are able to write a payload to the provided headers without ever learning about anything other than the first hop back into the Mixnet - the Gateway they (the sender of the reply) are currently registered with.
|
||||
|
||||
|
||||
@@ -66,13 +66,15 @@ Quite a bit of stuff gets built. The key working parts are:
|
||||
|
||||
* [Nym Node](../nodes/nym-node/nym-node.mdx): `nym-node`
|
||||
* [Validator](../nodes/validator-setup.mdx)
|
||||
* [websocket client](https://nymtech.net/developers/clients/websocket-client.html): `nym-client`
|
||||
* [socks5 client](https://nymtech.net/developers/clients/socks5-client.html): `nym-socks5-client`
|
||||
* [webassembly client](https://nymtech.net/developers/clients/webassembly-client.html): `webassembly-client`
|
||||
* [nym-cli tool](https://nymtech.net/docs/tools/nym-cli.html): `nym-cli`
|
||||
* [websocket client](../../developers/clients/websocket): `nym-client`
|
||||
* [socks5 client](../../developers/clients/socks5): `nym-socks5-client`
|
||||
* [webassembly client](../../developers/clients/webassembly-client): `webassembly-client`
|
||||
* [nym-cli tool](../../developers/tools/nym-cli): `nym-cli`
|
||||
* [nym-api](../nodes/validator-setup/nym-api.mdx): `nym-api`
|
||||
* [nymvisor](../nodes/maintenance/nymvisor-upgrade.mdx): `nymvisor`
|
||||
|
||||
{/*
|
||||
The repository also contains Typescript applications which aren't built in this process. These can be built by following the instructions on their respective docs pages.
|
||||
* [Nym Wallet](https://nymtech.net/docs/wallet/desktop-wallet.html)
|
||||
* [Network Explorer UI](https://nymtech.net/docs/explorers/mixnet-explorer.html)
|
||||
*/}
|
||||
|
||||
@@ -37,8 +37,17 @@ export const TunnelManagerCommands = () => (
|
||||
|
||||
This page displays a full list of all the changes during our release cycle from `v2024.3-eclipse` onward. Operators can find here the newest updates together with links to relevant documentation. The list is sorted so that the newest changes appear first.
|
||||
|
||||
**Note:** Any information shared on this page was up to date at the time of writing. We do *not* maintain changelog retrospectively.
|
||||
|
||||
<VarInfo />
|
||||
|
||||
## Archived Changelog
|
||||
|
||||
To allow reading through older changelogs, we store them below sorted by years.
|
||||
|
||||
<br />
|
||||
<AccordionTemplate name="Changelog 2024">
|
||||
|
||||
## `v2024.14-crunch-patched`
|
||||
Patch for `v2024.14-crunch` release. [Fixes an issue](https://github.com/nymtech/nym/commit/b656003306184061588f25df0b8b4555b41157f4) to allow only one private IP pair & compatibility issues between nym-nodes and older clients.
|
||||
|
||||
@@ -375,7 +384,7 @@ After changes coming along with `v2024.13-magura` (`nym-node v1.1.10`), Nym Expl
|
||||
|
||||
- Updated [`network_tunnel_manager.sh`](https://github.com/nymtech/nym/blob/develop/scripts/network_tunnel_manager.sh) (moved to our monorepo) helps operators to configure their IP tables rules for `nymtun` and `wireguard` routing.
|
||||
|
||||
- **Please re-run [routing configuration steps](https://nymtech.net/docs/operators/nodes/nym-node/configuration#routing-configuration) to update your routing settings.**
|
||||
- **Please re-run [routing configuration steps](nodes/nym-node/configuration#routing-configuration) to update your routing settings.**
|
||||
|
||||
- We found out that some operators have a wrong value for wireguard IP. Follow these steps to ensure your value is set to `10.1.0.1` (default on new nodes):
|
||||
|
||||
@@ -2818,3 +2827,5 @@ called Result::unwrap() on an Err value: ClientCoreError(ValidatorClientError(Ny
|
||||
| `http://<IP>:8000/stats` | `http://<IP>:8000/api/v1/metrics/mixing` |
|
||||
| `http://<IP>:8000/hardware` | `http://<IP>:8000/api/v1/system-info` |
|
||||
| `http://<IP>:8000/description` | `http://<IP>:8000/api/v1/description` |
|
||||
|
||||
</ AccordionTemplate>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { MyTab } from 'components/generic-tabs.tsx';
|
||||
|
||||
This page is a part of Nym Community Counsel (before Legal Forum) and its content is composed by shared advices in [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) as well as though pull requests done by the node operators directly to our [repository](https://github.com/nymtech/nym/tree/develop/documentation/docs/pages/operators), reviewed by Nym DevRels.
|
||||
|
||||
This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. [**Nym exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) was inspired by (nowadays deprecated) Tor Null deny list and Tor reduced policy and created to meet the changes decided by Nym operators community through the governance (like in this [vote](https://forum.nymtech.net/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464)). This policy aims to find a healthy compromise between protecting the operators and NymVPN users against attacks while allowing for as wide experience when accessing the internet through Nym Network.
|
||||
This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. [**Nym exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) was inspired by (nowadays deprecated) Tor Null deny list and Tor reduced policy and created to meet the changes decided by Nym operators community through the governance (like in this [vote](https://forum.nym.com/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464)). This policy aims to find a healthy compromise between protecting the operators and NymVPN users against attacks while allowing for as wide experience when accessing the internet through Nym Network.
|
||||
|
||||
|
||||
<Callout type="warning" emoji="⚠️">
|
||||
@@ -28,7 +28,7 @@ To achieve this, operators running Exit Gateways would have to “open” their
|
||||
|
||||
* To decentralise and enable privacy for a broader range of services, Nym transitioned from allow list to a deny list - creating a new [Nym exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt).
|
||||
|
||||
* Future changes of the exit policy is done via an off-chain governance, like in this [vote](https://forum.nymtech.net/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464).
|
||||
* Future changes of the exit policy is done via an off-chain governance, like in this [vote](https://forum.nym.com/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464).
|
||||
|
||||
* This will enhance the usage and appeal of Nym products for end users. As a result, increased usage will ultimately lead to higher revenues for Nym operators.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This is **Nym's Operators guide**, containing information and setup guides for the various components of Nym network and Nyx blockchain validators.
|
||||
|
||||
Nym network (also known as mixnet) routes and mixes packets through Gateways and Mixnodes, all run from the same binary called `nym-node`.
|
||||
Nym network (also known as Nym mixnet) routes and mixes packets through Gateways and Mixnodes, all run from the same binary called `nym-node`.
|
||||
|
||||
```ascii
|
||||
┌─►mix──┐ mix mix
|
||||
@@ -14,10 +14,13 @@ client ───► Gateway ──┘ mix │ mix ┌─►mix ───►
|
||||
mix └─►mix──┘ mix
|
||||
```
|
||||
|
||||
If you are new to Nym and want to learn about the Mixnet, explore kickstart options and demos, learn how to integrate with the network, and follow developer tutorials check out the [Developer Portal](https://nymtech.net/docs/developers/).
|
||||
If you want to dive deeper into Nym Network architecture, clients and nodes visit the [Network docs](../network).
|
||||
|
||||
If you want to dive deeper into Nym's architecture, clients, nodes, and SDK examples visit the [technical docs](https://nymtech.net/docs/network).
|
||||
If you want to explore kickstart options and examples, learn how to integrate with the network, and follow developer tutorials check out the [Developer Portal](../developers).
|
||||
|
||||
## Minimum Requirements
|
||||
|
||||
**If you are an operator and want to join the journey of starting and mantaining a Nym Node, begin with visiting [Minimum requirements page](nodes.mdx).**
|
||||
|
||||
## Popular pages
|
||||
|
||||
@@ -52,4 +55,4 @@ If you want to dive deeper into Nym's architecture, clients, nodes, and SDK exam
|
||||
|
||||
**Archive**
|
||||
|
||||
*[FAQ: Project Smoosh](archive/faq/smoosh-faq.mdx)
|
||||
* [FAQ: Project Smoosh](archive/faq/smoosh-faq.mdx)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
As a general approach, licensing is as follows this pattern:
|
||||
|
||||
* <p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://nymtech.net/docs">Nym Documentation</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://nymtech.net">Nym Technologies</a> is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1"></a></p>
|
||||
* <p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://nym.com">Nym Documentation</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://nym.com">Nym Technologies</a> is licensed under <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1"></a></p>
|
||||
|
||||
* Nym applications and binaries are [GPL-3.0-only](https://www.gnu.org/licenses/)
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Callout } from 'nextra/components';
|
||||
import { Steps } from 'nextra/components';
|
||||
import { Tabs } from 'nextra/components';
|
||||
import NymNodeSpecs from 'components/operators/snippets/nym-node-specs.mdx';
|
||||
|
||||
# Nym Nodes Operator Guides
|
||||
|
||||
Welcome to the section containing setup guides for operators of Nym Nodes and Nym Validators. To setup, configure, run, bond and maintain a `nym-node` is not a difficult process, but it takes dedication. Before you start, please check out [minimum requirements](#minimum-requirements) and then follow the [Steps for Nym Node Operators](#steps-for-nym-node-operators) below.
|
||||
|
||||
## Minimum Requirements
|
||||
|
||||
Operating a `nym-node` is not a set-and-forget endeavor. To prevent operators committing their time and money into a sub-optimal server, resulting in frustration of never seeing their node active, we composed this list of prerequisites. Please read below about expectations regarding operators [skill set](#knowledge-base), [time dedication](#time) and [minimum hardware specs](#vps-hardware-specs).
|
||||
|
||||
### Knowledge base
|
||||
|
||||
**All nodes are run remotely from operators shell, using [SSH](https://www.ssh.com/academy/ssh) and [Bash](https://www.gnu.org/software/bash/) commands. Node operators need to be experienced super users or sys-admins.** If you never used terminal before, maybe start with some tutorial of [basic Linux administration](https://www.linode.com/docs/guides/linux-system-administration-basics/) before committing to run a node.
|
||||
|
||||
<NymNodeSpecs />
|
||||
|
||||
### Time
|
||||
|
||||
Last but not least, managing a Nym Node is work. More skilled an operator is, less time it takes to run and maintain a node (and search extra details), but just like any other work, it takes effort.
|
||||
|
||||
Reserve 45-120 minutes for the initial setup and configuration (depends on your skills). Then count on a few minutes once in 2-4 weeks to upgrade node version binaries. Patches don't always come out [regularly](release-cycle.mdx), operators need to keep their eyes on [Matrix announcement channel](https://matrix.to/#/#node-ops-announcements:nymtech.chat).
|
||||
|
||||
Outdated nodes are never selected for routing/mixing packets, resulting in not receiving any rewards. You can read more on our [Tokenomics page](tokenomics/mixnet-rewards.mdx) to understand the selection and rewards logic.
|
||||
|
||||
## Steps for Nym Node Operators
|
||||
|
||||
This is a summary of all needed steps for node operators to setup and configure a `nym-node` and register it to Nym Network:
|
||||
|
||||
|
||||
1. **Start with [Preliminary Steps](preliminary-steps.mdx), preparing:**
|
||||
- [VPS](preliminary-steps/vps-setup.mdx)
|
||||
- [Nym wallet](preliminary-steps/wallet-preparation/mdx)
|
||||
|
||||
2. **[Setup](nym-node/setup.mdx) the node**
|
||||
|
||||
3. **[Configure](nym-node/configuration.mdx) the node and (optionally) automation, Wireguard, WSS, reverse proxy ...**
|
||||
|
||||
4. **[Run](nym-node/setup.mdx#initialise--run) the node or [the service](nym-node/configuration.md#systemd)**
|
||||
|
||||
5. **[Bond](nym-node/bonding.mdx) the node to the Nym API, using Nym wallet**
|
||||
|
||||
Make sure to follow the steps thoroughly, in case you find any point difficult don't hesitate to ask in our [Operators channel](https://matrix.to/#/#operators:nymtech.chat).
|
||||
@@ -7,18 +7,4 @@ NYM NODE is a tool for running a node within the Nym network. Nym Nodes containi
|
||||
|
||||
To setup any type of Nym Node, start with either building [Nym's platform](../binaries/building-nym.mdx) from source or download [pre-compiled binaries](../binaries/pre-built-binaries.mdx) on the [configured server (VPS)](preliminary-steps/vps-setup.mdx) where you want to run the node. Your Nym Node will need to be bonded before it can be run. We recommend most users use the [Nym desktop wallet](preliminary-steps/wallet-preparation.mdx) for this.
|
||||
|
||||
**Follow [preliminary steps](preliminary-steps.mdx) page before you configure and run a `nym-node`!**
|
||||
|
||||
## Steps for Nym Node Operators
|
||||
|
||||
Once [VPS and Nym wallet are configured](preliminary-steps.mdx), binaries ready, the operators of `nym-node` need to:
|
||||
|
||||
1. **[Setup](nym-node/setup.mdx) the node**
|
||||
|
||||
2. **[Configure](nym-node/configuration.mdx) the node and optionally automation, Wireguard, WSS, reversed proxy ...**
|
||||
|
||||
3. **[Run](nym-node/setup.mdx#initialise--run) the node or [the service](nym-node/configuration.md#systemd)**
|
||||
|
||||
4. **[Bond](nym-node/bonding.mdx) the node to the Nym API, using Nym wallet**
|
||||
|
||||
Make sure to follow the steps thoroughly, in case you find any point difficult don't hesitate to ask in our [Operators channel](https://matrix.to/#/#operators:nymtech.chat).
|
||||
**Read thoroughly [Minimum Requirement page](../nodes.mdx) before you configure and run a `nym-node`!**
|
||||
|
||||
@@ -69,7 +69,7 @@ echo "$(curl -4 https://ifconfig.me)"
|
||||
- Enter the `Amount`, `Operating cost` and `Profit margin` and press `Next`
|
||||
|
||||
<Callout type="warning" emoji="⚠️">
|
||||
If you are part of [Nym Delegation Program](https://delegations.explorenym.net) or Service Grants Program, make sure your values are within the [rules](https://forum.nymtech.net/t/nym-delegations-program-update/466) of the programs. Operators setting up larger OP or PM than defined in the rules will be excluded from the program without prior warning!
|
||||
If you are part of [Nym Delegation Program](https://delegations.explorenym.net) or Service Grants Program, make sure your values are within the [rules](https://forum.nym.com/t/nym-delegations-program-update/466) of the programs. Operators setting up larger OP or PM than defined in the rules will be excluded from the program without prior warning!
|
||||
</Callout>
|
||||
|
||||
- You will be asked to run a `sign` command with your `nym-node` - copy and paste the long signature as the value of `--contract-msg` and sing it on your VPS:
|
||||
@@ -149,4 +149,4 @@ Versions older than `nym-wallet v 1.2.15` will not allow bonding new nodes.
|
||||
|
||||
## Bond via the CLI (power users)
|
||||
|
||||
If you want to bond your Mix Node via the CLI, then check out the [relevant section in the Nym CLI](https://nymtech.net/docs/tools/nym-cli.html#bond-a-mix-node) docs.
|
||||
If you want to bond your Mix Node via the CLI, then check out the [relevant section in the Nym CLI](../../../developers/tools/nym-cli/usage#usage) docs.
|
||||
|
||||
@@ -217,7 +217,7 @@ This lets your operating system know it's ok to reload the service configuration
|
||||
|
||||
## Connectivity Test and Configuration
|
||||
|
||||
During our ongoing testing events [Fast and Furious](https://nymtech.net/events/fast-and-furious) we found out, that after introducing IP Packet Router (IPR) and [Nym exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) on embedded Network Requester (NR) by default, only a fragment of Gateways routes correctly through IPv4 and IPv6. We built a useful monitor to check out your Gateway (`nym-node --mode exit-gateway`) at [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/).
|
||||
During our ongoing testing events we found out, that after introducing IP Packet Router (IPR) and [Nym exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) on embedded Network Requester (NR) by default, only a fragment of Gateways routes correctly through IPv4 and IPv6. We built a useful monitor to check out your Gateway (`nym-node --mode exit-gateway`) at [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/).
|
||||
|
||||
IPv6 routing is not only a case for gateways. Imagine a rare occasion when you run a `mixnode` without IPv6 enabled and a client will sent IPv6 packets through the Mixnet through such route:
|
||||
```ascii
|
||||
@@ -491,7 +491,7 @@ sudo setcap 'cap_net_bind_service=+ep cap_net_admin=+ep' nym-node
|
||||
- `After=network.target`
|
||||
- `Group=<USER>`
|
||||
- `Type=simple`
|
||||
|
||||
|
||||
- Your service file will then look like this:
|
||||
|
||||
```ini
|
||||
@@ -500,7 +500,7 @@ Description=Nym Node
|
||||
After=network.target
|
||||
StartLimitInterval=350
|
||||
StartLimitBurst=10
|
||||
|
||||
|
||||
[Service]
|
||||
User=<USER>
|
||||
Group=<USER>
|
||||
@@ -510,7 +510,7 @@ ExecStart=<PATH>/nym-node run <ARGUMENTS> # add all the flags you use to run you
|
||||
KillSignal=SIGINT
|
||||
Restart=on-failure
|
||||
RestartSec=30
|
||||
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
+3
-4
@@ -119,8 +119,8 @@ white-space: nowrap;
|
||||
<p>
|
||||
You are most likely accessing this website because you've had some issue with
|
||||
the traffic coming from this IP. This router is part of the <a
|
||||
href="https://nymtech.net/">NYM project</a>, which is
|
||||
dedicated to <a href="https://nymtech.net/about/mission">create</a> outstanding
|
||||
href="https://nym.com/">NYM project</a>, which is
|
||||
dedicated to <a href="https://nym.com/about/mission">create</a> outstanding
|
||||
privacy software that is legally compliant without sacrificing integrity or
|
||||
having any backdoors.
|
||||
This router IP should be generating no other traffic, unless it has been
|
||||
@@ -180,7 +180,7 @@ stroke: var(--text-color);
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://nymtech.net/about/mixnet">Read more about how Nym works.</a></p>
|
||||
<a href="https://nym.com/about/mixnet">Read more about how Nym works.</a></p>
|
||||
|
||||
<p>
|
||||
Nym relies on a growing ecosystem of users, developers and researcher partners
|
||||
@@ -576,4 +576,3 @@ wscat -c wss://<HOSTNAME>:<WSS_PORT>
|
||||
```
|
||||
|
||||
- Check Swagger API of your node using the hostname: `https://<HOSTNAME>/api/v1/swagger/#/`
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ This documentation page provides a guide on how to set up and run a [NYM NODE](.
|
||||
```sh
|
||||
nym-node
|
||||
Binary Name: nym-node
|
||||
Build Timestamp: 2024-12-11T13:49:11.974104790Z
|
||||
Build Version: 1.2.0
|
||||
Commit SHA: a491e6a71a8cf862d77defd740a4ee8d65d8292a
|
||||
Commit Date: 2024-12-11T10:28:47.000000000+01:00
|
||||
Build Timestamp: 2024-12-18T10:18:42.978852430Z
|
||||
Build Version: 1.2.1
|
||||
Commit SHA: 8d5a41a790e96ae5e821964865affaa7d3343eab
|
||||
Commit Date: 2024-12-18T11:07:49.000000000+01:00
|
||||
Commit Branch: HEAD
|
||||
rustc Version: 1.83.0
|
||||
rustc Channel: stable
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
There are a couple of steps that need completing before starting to set up your `nym-node`:
|
||||
|
||||
1. **[Prepare your wallet](preliminary-steps/wallet-preparation.mdx):** [desktop](https://nymtech.net/docs/wallet/desktop-wallet.html) or [CLI](../../developers/tools/nym-cli/commands.mdx).
|
||||
1. **[Prepare your wallet](preliminary-steps/wallet-preparation.mdx):** [desktop](https://nym.com/download/wallet) or [CLI](../../developers/tools/nym-cli/commands.mdx).
|
||||
2. **[Requisition and setup a VPS](preliminary-steps/vps-setup.mdx)** (Virtual Private Server)
|
||||
|
||||
Make sure to follow these steps carefully as it prevents a lot of troubleshooting later on.
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Steps } from 'nextra/components';import { Tabs } from 'nextra/component
|
||||
import { MyTab } from 'components/generic-tabs.tsx';
|
||||
import PortsNymNode from 'components/operators/snippets/ports-nym-node.mdx';
|
||||
import PortsValidator from 'components/operators/snippets/ports-validator.mdx'
|
||||
import NymNodeSpecs from 'components/operators/snippets/nym-node-specs.mdx'
|
||||
|
||||
# VPS Setup & Configuration
|
||||
|
||||
@@ -13,51 +14,9 @@ We aim for Nym Network to be reliable and quality base layer of privacy accross
|
||||
A sub-optimally configured VPS often results in a non-functional node. To follow these steps carefully will save you time and money later on.
|
||||
</Callout>
|
||||
|
||||
## VPS Hardware Specs
|
||||
<NymNodeSpecs />
|
||||
|
||||
You will need to rent a VPS to run your node on. One key reason for this is that your node **must be able to send TCP data using both IPv4 and IPv6** (as other nodes you talk to may use either protocol).
|
||||
|
||||
Tor community created a very helpful table called [*Good Bad ISPs*](https://community.torproject.org/relay/community-resources/good-bad-isps/), you can use that one as a guideline for your choice of ISP for your VPS.
|
||||
|
||||
**Update:** Nym community started an ISP table called [*Where to host your nym node?*](../../community-counsel/isp-list.mdx), check it out and add your findings!
|
||||
|
||||
### `nym-node`
|
||||
|
||||
Before we conclude the testing with exact results, these are the rough specs:
|
||||
|
||||
| **Hardware** | **Minimum Specification** w
|
||||
| :--- | ---: |
|
||||
| CPU Cores | 4 |
|
||||
| Memory | 4 GB RAM |
|
||||
| Storage | 40 GB |
|
||||
| Connectivity | IPv4, IPv6, TCP/IP, UDP |
|
||||
| Bandwidth | 1Tb |
|
||||
| Port speed | 1Gbps |
|
||||
|
||||
### Nyx validator
|
||||
|
||||
The specification mentioned below is for running a full node alongside the nym-api. It is recommended to run `nym-api` and a full Nyx node on the same machine for optimum performance.
|
||||
|
||||
Bear in mind that credential signing is primarily CPU-bound, so choose the fastest CPU available to you.
|
||||
|
||||
#### Minimum Requirements
|
||||
|
||||
| Hardware | **Minimum Specification** |
|
||||
|----------|--------------------------------------------|
|
||||
| CPU | 8-cores, 2.8GHz base clock speed or higher |
|
||||
| RAM | 16GB DDR4+ |
|
||||
| Disk | 500 GiB+ NVMe SSD |
|
||||
|
||||
#### Recommended Requirements
|
||||
|
||||
| Hardware | **Minimum Specification** |
|
||||
|----------|---------------------------------------------|
|
||||
| CPU | 16-cores, 2.8GHz base clock speed or higher |
|
||||
| RAM | 32GB DDR4+ |
|
||||
| Disk | 1 TiB+ NVMe SSD |
|
||||
|
||||
|
||||
#### Full node configuration (validator)
|
||||
## Full node configuration (validator)
|
||||
|
||||
To install a full node from scratch, refer to the [validator setup guide](../validator-setup.mdx) and follow the steps outlined there.
|
||||
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
## Mainnet
|
||||
|
||||
Head to our [website](https://nymtech.net/download) and download the Nym wallet for your operating system. If pre-compiled binaries for your operating system aren't available, you can build the wallet yourself with instructions [here](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||
Head to our [website](https://nym.com/download/wallet) and download Nym wallet for your operating system.
|
||||
|
||||
{/*
|
||||
|
||||
If pre-compiled binaries for your operating system aren't available, you can build the wallet yourself with instructions [here](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||
*/}
|
||||
|
||||
If you don't already have one, please create a Nym address using the wallet, and fund it with NYM tokens. The minimum amount required to bond a node is 100 `NYM`, but make sure you have a bit more to account for gas costs.
|
||||
|
||||
@@ -14,5 +19,3 @@ If you don't already have one, please create a Nym address using the wallet, and
|
||||
## Sandbox testnet
|
||||
|
||||
Make sure to download a wallet and create an account as outlined above. Then head to our [Sandbox Testnet page](../../sandbox.mdx#sandbox-token-faucet) and request testnet NYM tokens.
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import { AccordionTemplate } from 'components/accordion-template.tsx';
|
||||
The Nym API is a binary that will be operated by the Nyx validator set. This binary can be run in several different modes, and has two main bits of functionality:
|
||||
|
||||
* Network monitoring (calculating the routing score of Mixnet nodes)
|
||||
* Generation and validation of [zk-nyms](https://blog.nymtech.net/zk-nyms-are-here-a-major-milestone-towards-a-market-ready-mixnet-a3470c9ab10a), our implementation of the Coconut Selective Disclosure Credential Scheme.
|
||||
* Generation and validation of [zk-nyms](../../../network/cryptography/zk-nym), our implementation of the Coconut Selective Disclosure Credential Scheme.
|
||||
|
||||
This is important for both the proper decentralisation of the network uptime calculation and, more pressingly, enabling the NymVPN to utilise privacy preserving payments.
|
||||
|
||||
@@ -94,7 +94,7 @@ The example value of `100` for `pruning-interval` can be customised as per your
|
||||
|
||||
### Credential Generation
|
||||
|
||||
Validators that took part in the DKG ceremony became part of the 'quorum' generating and verifying zk-nym credentials. These will initially be used for private proof of payment for NymVPN (see our blogposts [here](https://blog.nymtech.net/nymvpn-an-invitation-for-privacy-experts-and-enthusiasts-63644139d09d) and [here](https://blog.nymtech.net/zk-nyms-are-here-a-major-milestone-towards-a-market-ready-mixnet-a3470c9ab10a) for more on this), and in the future will be expanded into more general use-cases such as [offline ecash](https://arxiv.org/abs/2303.08221).
|
||||
Validators that took part in the DKG ceremony became part of the 'quorum' generating and verifying zk-nym credentials. These will initially be used for private proof of payment for NymVPN (moe [here](https://blog.nym.com/nymvpn-an-invitation-for-privacy-experts-and-enthusiasts-63644139d09d) and [here](https://blog.nym.com/zk-nyms-are-here-a-major-milestone-towards-a-market-ready-mixnet-a3470c9ab10a)), and in the future will be expanded into more general use-cases such as [offline ecash](https://arxiv.org/abs/2303.08221).
|
||||
|
||||
The DKG ceremony was used to create a subset of existing validators who run `nym-api` alongside a Nyx full-node. As outlined above, they are the ones taking part in the generation and verification of zk-nym credentials. The size of the 'minimum viable quorum' is 10 - the intial set taking part in DKG was 17 validators. This is in order to have some redundancy in the case of a validator dropping or going offline.
|
||||
|
||||
@@ -301,4 +301,3 @@ You can also use `nymvisor` to automatically update the `nym-api` node. The step
|
||||
It is recommended to expose the webserver over HTTPS by using a webserver like Nginx. An example configuration for configuring Nginx is listed on [Reverse proxy page](../nym-node/configuration/proxy-configuration.mdx). If you're using a custom solution, ensure to allow requests from anywhere by setting a permissive CORS policy.
|
||||
|
||||
For example, it is configured in Nginx using: `add_header 'Access-Control-Allow-Origin' '*';`
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/env
|
||||
- In case you downloaded `sandbox.env` to same directory, `<PATH>` is not needed
|
||||
|
||||
###### 3. Bond your node to Nym Sandbox environment
|
||||
- Open [Nym Wallet](https://nymtech.net/download/wallet) and switch to testnet
|
||||
- Open [Nym Wallet](https://nym.com/download/wallet) and switch to testnet
|
||||
- Go to [faucet.nymtech.net](https://faucet.nymtech.net) and aquire 101 testnet NYM tokens
|
||||
- Follow the steps on the [bonding page](nodes/nym-node/bonding.mdx)
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ import { AccordionTemplate } from 'components/accordion-template.tsx';
|
||||
|
||||
Nym Network is composed of two main elements, the Mixnet represented by [Nym Nodes](nodes/nym-node/nym-node.mdx) routing and mixing the data packets, and Nyx blockchain distributted accros [validator set](tokenomics/validator-rewards.mdx), using smart contracts (based on [cosmwasm](https://cosmwasm.com/)) to monitor and reward Nym Nodes by querying API endpoints and distributing NYM token to operators according to work done by their nodes. All Nym nodes and validators are run by decentralised community of operators.
|
||||
|
||||
* Nym tokenomics are based on the research paper [*Reward Sharing for Mixnets*](https://nymtech.net/nym-cryptoecon-paper.pdf)
|
||||
* For a more comprehensive overview, token live data and supply graphs, visit [*nymtech.net/about/token*](https://nymtech.net/about/token)
|
||||
* Nym tokenomics are based on the research paper [*Reward Sharing for Mixnets*](https://nym.com/nym-cryptoecon-paper.pdf)
|
||||
* For a more comprehensive overview, token live data and supply graphs, visit [*nym.com/about/token*](https://nymtech.net/about/token)
|
||||
* To read about rewards calculation, visit [Nym Node rewards page](tokenomics/mixnet-rewards.mdx)
|
||||
* To understand the implementation and release plan, see [Nym operators roadmap](tokenomics/mixnet-rewards.mdx#roadmap)
|
||||
|
||||
@@ -83,11 +83,11 @@ Below is a table with token supply distribution.
|
||||
|
||||
<TokenTable />
|
||||
|
||||
To get live data, visit [Nym token page](https://nymtech.net/about/token) or see how to [query API endpoints](#query-tokenomics-api).
|
||||
To get live data, visit [Nym token page](https://nym.com.net/about/token) or see how to [query API endpoints](#query-tokenomics-api).
|
||||
|
||||
### Calculation & Explanation
|
||||
|
||||
To get a full comprehension of [node operators rewards](tokenomics/mixnet-rewards.mdx) calculation and [delegators APR height](https://nymtech.net/about/token), we need to understand some basic logic behind the numbers presented. This chapter covers some of the most essential variables in Nym tokenomics flow.
|
||||
To get a full comprehension of [node operators rewards](tokenomics/mixnet-rewards.mdx) calculation and [delegators APR height](https://nym.com/about/token), we need to understand some basic logic behind the numbers presented. This chapter covers some of the most essential variables in Nym tokenomics flow.
|
||||
|
||||
```ascii
|
||||
|
||||
@@ -104,7 +104,7 @@ To get a full comprehension of [node operators rewards](tokenomics/mixnet-reward
|
||||
<br />
|
||||
<b>Circulating supply is <span style={{display: 'inline-block'}}><CirculatingSupply /></span> NYM.</b>
|
||||
|
||||
NYM token is capped at 1b. Visit [Nym token page](https://nymtech.net/about/token) to see live data and graphs.
|
||||
NYM token is capped at 1b. Visit [Nym token page](https://nym.com/about/token) to see live data and graphs.
|
||||
|
||||
#### Staking target
|
||||
|
||||
|
||||
@@ -439,7 +439,7 @@ wscat -c ws://<PUBLIC_IP>:<PORT>
|
||||
|
||||
</Steps>
|
||||
|
||||
### My exit Gateway "is still not online..."
|
||||
### My Exit Gateway "is still not online..."
|
||||
|
||||
The Nyx chain epoch takes up to 60 min. To prevent the Gateway getting blacklisted, it's essential to start it before the bonding process and let it running. In case it already got [blacklisted](#my-gateway-is-backlisted) check the steps above.
|
||||
|
||||
@@ -482,7 +482,7 @@ http://<YOUR_LISTENING_IP_ADDRESS>:8080/api/v1/roles
|
||||
# in case of hostname domain
|
||||
https://<YOUR_DOMAIN>/api/v1/roles
|
||||
```
|
||||
3. Make sure all your [ports are open](https://nymtech.net/operators/nodes/maintenance.html#configure-your-firewall) properly
|
||||
3. Make sure all your [ports are open](../nodes/preliminary-steps/vps-setup#install-dependencies--configure-firewall) properly
|
||||
4. Make sure to run your Gateway with embedded IPR as root. Either in a root shell with your configs in `/root/.nym/` or with a command `sudo -E` which gives root privileges but looks for user config folder
|
||||
5. If it's all good in the API but you don't see the right tick/badge in the [Performance testing list](https://nymtech.net/events/fast-and-furious), just wait some time and then try to refresh the page
|
||||
5. If it's all good in the API but you don't see the right tick/badge in the [Performance testing list](https://nym.com/events/fast-and-furious), just wait some time and then try to refresh the page
|
||||
*/}
|
||||
|
||||
@@ -13,6 +13,6 @@ The most common reason for your validator being jailed is that your validator is
|
||||
|
||||
## Where can I get more help?
|
||||
|
||||
The fastest way to reach one of us or get a help from the community, visit our [Telegram Node Setup Help Chat](https://t.me/nymchan_help_chat) or head to our [Discord](https://nymtech.net/go/discord).
|
||||
The fastest way to reach one of us or get a help from the community, visit our [Telegram Node Setup Help Chat](https://t.me/nymchan_help_chat) or head to our [Discord](https://nym.com/go/discord).
|
||||
|
||||
For more tech heavy question join our [Matrix core community channel](https://matrix.to/#/#general:nymtech.chat), where you can meet other builders and Nym core team members.
|
||||
|
||||
+6
-57
@@ -1,15 +1,10 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_network_defaults::TICKETBOOK_VALIDITY_DAYS;
|
||||
use std::net::SocketAddr;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
// TODO: can we move those away?
|
||||
pub const DEFAULT_CLIENT_BANDWIDTH_MAX_FLUSHING_RATE: Duration = Duration::from_millis(5);
|
||||
pub const DEFAULT_CLIENT_BANDWIDTH_MAX_DELTA_FLUSHING_AMOUNT: i64 = 512 * 1024; // 512kB
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
pub gateway: Gateway,
|
||||
@@ -96,18 +91,13 @@ pub struct Debug {
|
||||
/// Defines a maximum change in client bandwidth before it gets flushed to the persistent storage.
|
||||
pub client_bandwidth_max_delta_flushing_amount: i64,
|
||||
|
||||
pub zk_nym_tickets: ZkNymTicketHandlerDebug,
|
||||
}
|
||||
/// Specifies how often the clean-up task should check for stale data.
|
||||
pub stale_messages_cleaner_run_interval: Duration,
|
||||
|
||||
impl Default for Debug {
|
||||
fn default() -> Self {
|
||||
Debug {
|
||||
client_bandwidth_max_flushing_rate: DEFAULT_CLIENT_BANDWIDTH_MAX_FLUSHING_RATE,
|
||||
client_bandwidth_max_delta_flushing_amount:
|
||||
DEFAULT_CLIENT_BANDWIDTH_MAX_DELTA_FLUSHING_AMOUNT,
|
||||
zk_nym_tickets: Default::default(),
|
||||
}
|
||||
}
|
||||
/// Specifies maximum age of stored messages before they are removed from the storage
|
||||
pub stale_messages_max_age: Duration,
|
||||
|
||||
pub zk_nym_tickets: ZkNymTicketHandlerDebug,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -131,44 +121,3 @@ pub struct ZkNymTicketHandlerDebug {
|
||||
/// That's required as nym-apis will purge all ticket information for tickets older than maximum validity.
|
||||
pub maximum_time_between_redemption: Duration,
|
||||
}
|
||||
|
||||
impl ZkNymTicketHandlerDebug {
|
||||
pub const DEFAULT_REVOCATION_BANDWIDTH_PENALTY: f32 = 10.0;
|
||||
pub const DEFAULT_PENDING_POLLER: Duration = Duration::from_secs(300);
|
||||
pub const DEFAULT_MINIMUM_API_QUORUM: f32 = 0.8;
|
||||
pub const DEFAULT_MINIMUM_REDEMPTION_TICKETS: usize = 100;
|
||||
|
||||
// use min(4/5 of max validity, validity - 1), but making sure it's no greater than 1 day
|
||||
// ASSUMPTION: our validity period is AT LEAST 2 days
|
||||
//
|
||||
// this could have been a constant, but it's more readable as a function
|
||||
pub const fn default_maximum_time_between_redemption() -> Duration {
|
||||
let desired_secs = TICKETBOOK_VALIDITY_DAYS * (86400 * 4) / 5;
|
||||
let desired_secs_alt = (TICKETBOOK_VALIDITY_DAYS - 1) * 86400;
|
||||
|
||||
// can't use `min` in const context
|
||||
let target_secs = if desired_secs < desired_secs_alt {
|
||||
desired_secs
|
||||
} else {
|
||||
desired_secs_alt
|
||||
};
|
||||
|
||||
assert!(
|
||||
target_secs > 86400,
|
||||
"the maximum time between redemption can't be lower than 1 day!"
|
||||
);
|
||||
Duration::from_secs(target_secs as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ZkNymTicketHandlerDebug {
|
||||
fn default() -> Self {
|
||||
ZkNymTicketHandlerDebug {
|
||||
revocation_bandwidth_penalty: Self::DEFAULT_REVOCATION_BANDWIDTH_PENALTY,
|
||||
pending_poller: Self::DEFAULT_PENDING_POLLER,
|
||||
minimum_api_quorum: Self::DEFAULT_MINIMUM_API_QUORUM,
|
||||
minimum_redemption_tickets: Self::DEFAULT_MINIMUM_REDEMPTION_TICKETS,
|
||||
maximum_time_between_redemption: Self::default_maximum_time_between_redemption(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
pub(crate) mod receiver;
|
||||
|
||||
pub(crate) use receiver::listener::Listener;
|
||||
pub(crate) use receiver::packet_processing::PacketProcessor;
|
||||
@@ -1,247 +0,0 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::node::client_handling::active_clients::ActiveClientsStore;
|
||||
use crate::node::client_handling::websocket::message_receiver::MixMessageSender;
|
||||
use crate::node::mixnet_handling::receiver::packet_processing::PacketProcessor;
|
||||
use futures::channel::mpsc::SendError;
|
||||
use futures::StreamExt;
|
||||
use nym_gateway_storage::{error::GatewayStorageError, GatewayStorage};
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_sphinx::forwarding::packet::MixPacket;
|
||||
use nym_sphinx::framing::codec::NymCodec;
|
||||
use nym_sphinx::framing::packet::FramedNymPacket;
|
||||
use nym_sphinx::framing::processing::ProcessedFinalHop;
|
||||
use nym_sphinx::DestinationAddressBytes;
|
||||
use nym_task::TaskClient;
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use thiserror::Error;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_util::codec::Framed;
|
||||
use tracing::*;
|
||||
|
||||
use super::packet_processing::process_packet;
|
||||
|
||||
// defines errors that warrant a panic if not thrown in the context of a shutdown
|
||||
#[derive(Debug, Error)]
|
||||
enum CriticalPacketProcessingError {
|
||||
#[error("failed to forward an ack")]
|
||||
AckForwardingFailure { source: SendError },
|
||||
}
|
||||
|
||||
pub(crate) struct ConnectionHandler {
|
||||
packet_processor: PacketProcessor,
|
||||
|
||||
// TODO: investigate performance trade-offs for whether this cache even makes sense
|
||||
// at this point.
|
||||
// keep the following in mind: each action on ActiveClientsStore requires going through RwLock
|
||||
// and each `get` internally copies the channel, however, is it really that expensive?
|
||||
clients_store_cache: HashMap<DestinationAddressBytes, MixMessageSender>,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
storage: GatewayStorage,
|
||||
ack_sender: MixForwardingSender,
|
||||
}
|
||||
|
||||
impl Clone for ConnectionHandler {
|
||||
fn clone(&self) -> Self {
|
||||
// remove stale entries from the cache while cloning
|
||||
let mut clients_store_cache = HashMap::with_capacity(self.clients_store_cache.capacity());
|
||||
for (k, v) in self.clients_store_cache.iter() {
|
||||
if !v.is_closed() {
|
||||
clients_store_cache.insert(*k, v.clone());
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionHandler {
|
||||
packet_processor: self.packet_processor.clone(),
|
||||
clients_store_cache,
|
||||
active_clients_store: self.active_clients_store.clone(),
|
||||
storage: self.storage.clone(),
|
||||
ack_sender: self.ack_sender.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectionHandler {
|
||||
pub(crate) fn new(
|
||||
packet_processor: PacketProcessor,
|
||||
storage: GatewayStorage,
|
||||
ack_sender: MixForwardingSender,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
) -> Self {
|
||||
ConnectionHandler {
|
||||
packet_processor,
|
||||
clients_store_cache: HashMap::new(),
|
||||
storage,
|
||||
active_clients_store,
|
||||
ack_sender,
|
||||
}
|
||||
}
|
||||
|
||||
fn update_clients_store_cache_entry(&mut self, client_address: DestinationAddressBytes) {
|
||||
if let Some(client_senders) = self.active_clients_store.get_sender(client_address) {
|
||||
self.clients_store_cache
|
||||
.insert(client_address, client_senders);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_cache(&mut self, client_address: DestinationAddressBytes) {
|
||||
match self.clients_store_cache.get(&client_address) {
|
||||
None => self.update_clients_store_cache_entry(client_address),
|
||||
Some(entry) => {
|
||||
if entry.is_closed() {
|
||||
self.update_clients_store_cache_entry(client_address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_push_message_to_client(
|
||||
&mut self,
|
||||
client_address: DestinationAddressBytes,
|
||||
message: Vec<u8>,
|
||||
) -> Result<(), Vec<u8>> {
|
||||
self.check_cache(client_address);
|
||||
|
||||
match self.clients_store_cache.get(&client_address) {
|
||||
None => Err(message),
|
||||
Some(sender_channel) => {
|
||||
if let Err(unsent) = sender_channel.unbounded_send(vec![message]) {
|
||||
// the unwrap here is fine as the original message got returned;
|
||||
// plus we're only ever sending 1 message at the time (for now)
|
||||
#[allow(clippy::unwrap_used)]
|
||||
return Err(unsent.into_inner().pop().unwrap());
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn store_processed_packet_payload(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
message: Vec<u8>,
|
||||
) -> Result<(), GatewayStorageError> {
|
||||
debug!("Storing received message for {client_address} on the disk...",);
|
||||
|
||||
self.storage.store_message(client_address, message).await
|
||||
}
|
||||
|
||||
fn forward_ack(
|
||||
&self,
|
||||
forward_ack: Option<MixPacket>,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<(), CriticalPacketProcessingError> {
|
||||
if let Some(forward_ack) = forward_ack {
|
||||
let next_hop = forward_ack.next_hop();
|
||||
trace!("Sending ack from packet for {client_address} to {next_hop}",);
|
||||
self.ack_sender
|
||||
.forward_packet(forward_ack)
|
||||
.map_err(|source| CriticalPacketProcessingError::AckForwardingFailure { source })?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_processed_packet(
|
||||
&mut self,
|
||||
processed_final_hop: ProcessedFinalHop,
|
||||
) -> Result<(), CriticalPacketProcessingError> {
|
||||
let client_address = processed_final_hop.destination;
|
||||
let message = processed_final_hop.message;
|
||||
let forward_ack = processed_final_hop.forward_ack;
|
||||
|
||||
// we failed to push message directly to the client - it's probably offline.
|
||||
// we should store it on the disk instead.
|
||||
match self.try_push_message_to_client(client_address, message) {
|
||||
Err(unsent_plaintext) => match self
|
||||
.store_processed_packet_payload(client_address, unsent_plaintext)
|
||||
.await
|
||||
{
|
||||
Err(err) => error!("Failed to store client data - {err}"),
|
||||
Ok(_) => trace!("Stored packet for {client_address}"),
|
||||
},
|
||||
Ok(_) => trace!("Pushed received packet to {client_address}"),
|
||||
}
|
||||
|
||||
// if we managed to either push message directly to the [online] client or store it at
|
||||
// its inbox, it means that it must exist at this gateway, hence we can send the
|
||||
// received ack back into the network
|
||||
self.forward_ack(forward_ack, client_address)
|
||||
}
|
||||
|
||||
async fn handle_received_packet(
|
||||
&mut self,
|
||||
framed_sphinx_packet: FramedNymPacket,
|
||||
) -> Result<(), CriticalPacketProcessingError> {
|
||||
//
|
||||
// TODO: here be replay attack detection - it will require similar key cache to the one in
|
||||
// packet processor for vpn packets,
|
||||
// question: can it also be per connection vs global?
|
||||
//
|
||||
|
||||
let processed_final_hop =
|
||||
match process_packet(framed_sphinx_packet, self.packet_processor.sphinx_key()) {
|
||||
Err(err) => {
|
||||
debug!("We failed to process received sphinx packet - {err}");
|
||||
return Ok(());
|
||||
}
|
||||
Ok(processed_final_hop) => processed_final_hop,
|
||||
};
|
||||
|
||||
self.handle_processed_packet(processed_final_hop).await
|
||||
}
|
||||
|
||||
pub(crate) async fn handle_connection(
|
||||
mut self,
|
||||
conn: TcpStream,
|
||||
remote: SocketAddr,
|
||||
mut shutdown: TaskClient,
|
||||
) {
|
||||
debug!("Starting connection handler for {:?}", remote);
|
||||
shutdown.disarm();
|
||||
let mut framed_conn = Framed::new(conn, NymCodec);
|
||||
while !shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = shutdown.recv() => {
|
||||
trace!("ConnectionHandler: received shutdown");
|
||||
}
|
||||
framed_sphinx_packet = framed_conn.next() => {
|
||||
match framed_sphinx_packet {
|
||||
Some(Ok(framed_sphinx_packet)) => {
|
||||
// TODO: benchmark spawning tokio task with full processing vs just processing it
|
||||
// synchronously under higher load in single and multi-threaded situation.
|
||||
|
||||
// in theory we could process multiple sphinx packet from the same connection in parallel,
|
||||
// but we already handle multiple concurrent connections so if anything, making
|
||||
// that change would only slow things down
|
||||
if let Err(critical_err) = self.handle_received_packet(framed_sphinx_packet).await {
|
||||
if !shutdown.is_shutdown() {
|
||||
panic!("experienced critical failure when processing received packet: {critical_err}")
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Err(err)) => {
|
||||
error!(
|
||||
"The socket connection got corrupted with error: {err}. Closing the socket",
|
||||
);
|
||||
return;
|
||||
}
|
||||
None => break, // stream got closed by remote
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match framed_conn.into_inner().peer_addr() {
|
||||
Ok(peer_addr) => {
|
||||
debug!("closing connection from {peer_addr}")
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("closing connection from an unknown peer: {err}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
|
||||
use nym_task::TaskClient;
|
||||
use std::net::SocketAddr;
|
||||
use std::process;
|
||||
use tokio::task::JoinHandle;
|
||||
use tracing::*;
|
||||
|
||||
pub(crate) struct Listener {
|
||||
address: SocketAddr,
|
||||
shutdown: TaskClient,
|
||||
}
|
||||
|
||||
// TODO: this file is nearly identical to the one in mixnode
|
||||
impl Listener {
|
||||
pub(crate) fn new(address: SocketAddr, shutdown: TaskClient) -> Self {
|
||||
Listener { address, shutdown }
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self, connection_handler: ConnectionHandler) {
|
||||
info!("Starting mixnet listener at {}", self.address);
|
||||
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
|
||||
Ok(listener) => listener,
|
||||
Err(err) => {
|
||||
error!("Failed to bind to {} - {err}. Are you sure nothing else is running on the specified port and your user has sufficient permission to bind to the requested address?", self.address);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
while !self.shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = self.shutdown.recv() => {
|
||||
trace!("mixnet_handling::Listener: Received shutdown");
|
||||
}
|
||||
connection = tcp_listener.accept() => {
|
||||
match connection {
|
||||
Ok((socket, remote_addr)) => {
|
||||
let handler = connection_handler.clone();
|
||||
tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone().named(format!("MixnetConnectionHandler_{remote_addr}"))));
|
||||
}
|
||||
Err(err) => warn!("failed to get client: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn start(mut self, connection_handler: ConnectionHandler) -> JoinHandle<()> {
|
||||
info!("Running mix listener on {:?}", self.address.to_string());
|
||||
|
||||
tokio::spawn(async move { self.run(connection_handler).await })
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
pub(crate) mod connection_handler;
|
||||
pub(crate) mod listener;
|
||||
pub(crate) mod packet_processing;
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_crypto::asymmetric::encryption;
|
||||
use nym_mixnode_common::packet_processor::error::MixProcessingError;
|
||||
use nym_mixnode_common::packet_processor::processor::SphinxPacketProcessor;
|
||||
use nym_sphinx::framing::packet::FramedNymPacket;
|
||||
use nym_sphinx::framing::processing::{
|
||||
process_framed_packet, MixProcessingResult, PacketProcessingError, ProcessedFinalHop,
|
||||
};
|
||||
use nym_sphinx::PrivateKey;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum GatewayProcessingError {
|
||||
#[error("failed to process received mix packet - {0}")]
|
||||
PacketProcessing(#[from] MixProcessingError),
|
||||
|
||||
#[error("received a forward hop mix packet")]
|
||||
ForwardHopReceived,
|
||||
|
||||
#[error("failed to process received sphinx packet: {0}")]
|
||||
NymPacketProcessing(#[from] PacketProcessingError),
|
||||
}
|
||||
|
||||
// PacketProcessor contains all data required to correctly unwrap and store sphinx packets
|
||||
#[derive(Clone)]
|
||||
pub struct PacketProcessor {
|
||||
inner_processor: SphinxPacketProcessor,
|
||||
}
|
||||
|
||||
impl PacketProcessor {
|
||||
pub fn sphinx_key(&self) -> &PrivateKey {
|
||||
self.inner_processor.sphinx_key()
|
||||
}
|
||||
|
||||
pub(crate) fn new(encryption_key: &encryption::PrivateKey) -> Self {
|
||||
PacketProcessor {
|
||||
inner_processor: SphinxPacketProcessor::new(encryption_key.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn process_packet(
|
||||
received: FramedNymPacket,
|
||||
sphinx_key: &nym_sphinx::PrivateKey,
|
||||
) -> Result<ProcessedFinalHop, GatewayProcessingError> {
|
||||
match process_framed_packet(received, sphinx_key)? {
|
||||
MixProcessingResult::ForwardHop(..) => Err(GatewayProcessingError::ForwardHopReceived),
|
||||
MixProcessingResult::FinalHop(processed_final) => Ok(processed_final),
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,9 @@ use zeroize::Zeroizing;
|
||||
|
||||
pub(crate) mod client_handling;
|
||||
mod internal_service_providers;
|
||||
mod stale_data_cleaner;
|
||||
|
||||
use crate::node::stale_data_cleaner::StaleMessagesCleaner;
|
||||
pub use client_handling::active_clients::ActiveClientsStore;
|
||||
pub use nym_gateway_stats_storage::PersistentStatsStorage;
|
||||
pub use nym_gateway_storage::{error::GatewayStorageError, GatewayStorage};
|
||||
@@ -446,6 +448,15 @@ impl GatewayTasksBuilder {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn build_stale_messages_cleaner(&self) -> StaleMessagesCleaner {
|
||||
StaleMessagesCleaner::new(
|
||||
&self.storage,
|
||||
self.shutdown.fork("stale-messages-cleaner"),
|
||||
self.config.debug.stale_messages_max_age,
|
||||
self.config.debug.stale_messages_cleaner_run_interval,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub async fn try_start_wireguard(
|
||||
&mut self,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_gateway_storage::{GatewayStorage, InboxManager};
|
||||
use nym_task::TaskClient;
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::task::JoinHandle;
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
pub struct StaleMessagesCleaner {
|
||||
inbox_manager: InboxManager,
|
||||
task_client: TaskClient,
|
||||
max_message_age: Duration,
|
||||
run_interval: Duration,
|
||||
}
|
||||
|
||||
impl StaleMessagesCleaner {
|
||||
pub(crate) fn new(
|
||||
storage: &GatewayStorage,
|
||||
task_client: TaskClient,
|
||||
max_message_age: Duration,
|
||||
run_interval: Duration,
|
||||
) -> Self {
|
||||
StaleMessagesCleaner {
|
||||
inbox_manager: storage.inbox_manager().clone(),
|
||||
task_client,
|
||||
max_message_age,
|
||||
run_interval,
|
||||
}
|
||||
}
|
||||
|
||||
async fn clean_up_stale_messages(&mut self) -> Result<(), impl Error> {
|
||||
let cutoff = OffsetDateTime::now_utc() - self.max_message_age;
|
||||
self.inbox_manager.remove_stale(cutoff).await
|
||||
}
|
||||
|
||||
async fn run(&mut self) {
|
||||
let mut interval = tokio::time::interval(self.run_interval);
|
||||
while !self.task_client.is_shutdown() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = self.task_client.recv() => {
|
||||
trace!("StaleMessagesCleaner: received shutdown");
|
||||
}
|
||||
_ = interval.tick() => {
|
||||
if let Err(err) = self.clean_up_stale_messages().await {
|
||||
warn!("failed to clean up stale messages: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("StaleMessagesCleaner: Exiting");
|
||||
}
|
||||
|
||||
pub fn start(mut self) -> JoinHandle<()> {
|
||||
tokio::spawn(async move { self.run().await })
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ zeroize = { workspace = true }
|
||||
# wasm-specific deps
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
wasm-bindgen = { workspace = true }
|
||||
js-sys = "0.3.70"
|
||||
js-sys = "0.3.76"
|
||||
tsify = { workspace = true, features = ["js"] }
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
|
||||
|
||||
@@ -174,10 +174,10 @@ mod api_regression {
|
||||
let location_result = client.locate_ip(my_ip).await;
|
||||
assert!(location_result.is_ok(), "Did ipinfo response change?");
|
||||
|
||||
assert!(
|
||||
client.check_remaining_bandwidth().await.is_ok(),
|
||||
"Failed to check remaining bandwidth?"
|
||||
);
|
||||
client
|
||||
.check_remaining_bandwidth()
|
||||
.await
|
||||
.expect("Failed to check remaining bandwidth?");
|
||||
|
||||
// when serialized, these fields should be present because they're exposed over API
|
||||
let location_result = location_result.unwrap();
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-node"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
@@ -47,6 +47,10 @@ pub struct Debug {
|
||||
/// Number of messages from offline client that can be pulled at once (i.e. with a single SQL query) from the storage.
|
||||
pub message_retrieval_limit: i64,
|
||||
|
||||
pub stale_messages: StaleMessageDebug,
|
||||
|
||||
pub client_bandwidth: ClientBandwidthDebug,
|
||||
|
||||
pub zk_nym_tickets: ZkNymTicketHandlerDebug,
|
||||
}
|
||||
|
||||
@@ -58,6 +62,8 @@ impl Default for Debug {
|
||||
fn default() -> Self {
|
||||
Debug {
|
||||
message_retrieval_limit: Self::DEFAULT_MESSAGE_RETRIEVAL_LIMIT,
|
||||
stale_messages: Default::default(),
|
||||
client_bandwidth: Default::default(),
|
||||
zk_nym_tickets: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -129,6 +135,54 @@ impl Default for ZkNymTicketHandlerDebug {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub struct ClientBandwidthDebug {
|
||||
/// Defines maximum delay between client bandwidth information being flushed to the persistent storage.
|
||||
pub max_flushing_rate: Duration,
|
||||
|
||||
/// Defines a maximum change in client bandwidth before it gets flushed to the persistent storage.
|
||||
pub max_delta_flushing_amount: i64,
|
||||
}
|
||||
|
||||
impl ClientBandwidthDebug {
|
||||
const DEFAULT_CLIENT_BANDWIDTH_MAX_FLUSHING_RATE: Duration = Duration::from_millis(5);
|
||||
const DEFAULT_CLIENT_BANDWIDTH_MAX_DELTA_FLUSHING_AMOUNT: i64 = 512 * 1024; // 512kB
|
||||
}
|
||||
|
||||
impl Default for ClientBandwidthDebug {
|
||||
fn default() -> Self {
|
||||
ClientBandwidthDebug {
|
||||
max_flushing_rate: Self::DEFAULT_CLIENT_BANDWIDTH_MAX_FLUSHING_RATE,
|
||||
max_delta_flushing_amount: Self::DEFAULT_CLIENT_BANDWIDTH_MAX_DELTA_FLUSHING_AMOUNT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub struct StaleMessageDebug {
|
||||
/// Specifies how often the clean-up task should check for stale data.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub cleaner_run_interval: Duration,
|
||||
|
||||
/// Specifies maximum age of stored messages before they are removed from the storage
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub max_age: Duration,
|
||||
}
|
||||
|
||||
impl StaleMessageDebug {
|
||||
const DEFAULT_STALE_MESSAGES_CLEANER_RUN_INTERVAL: Duration = Duration::from_secs(60 * 60);
|
||||
const DEFAULT_STALE_MESSAGES_MAX_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
}
|
||||
|
||||
impl Default for StaleMessageDebug {
|
||||
fn default() -> Self {
|
||||
StaleMessageDebug {
|
||||
cleaner_run_interval: Self::DEFAULT_STALE_MESSAGES_CLEANER_RUN_INTERVAL,
|
||||
max_age: Self::DEFAULT_STALE_MESSAGES_MAX_AGE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GatewayTasksConfig {
|
||||
pub fn new_default<P: AsRef<Path>>(data_dir: P) -> Self {
|
||||
GatewayTasksConfig {
|
||||
|
||||
@@ -24,10 +24,22 @@ fn ephemeral_gateway_config(config: &Config) -> nym_gateway::config::Config {
|
||||
enabled: config.service_providers.network_requester.debug.enabled,
|
||||
},
|
||||
nym_gateway::config::Debug {
|
||||
client_bandwidth_max_flushing_rate:
|
||||
nym_gateway::config::DEFAULT_CLIENT_BANDWIDTH_MAX_FLUSHING_RATE,
|
||||
client_bandwidth_max_delta_flushing_amount:
|
||||
nym_gateway::config::DEFAULT_CLIENT_BANDWIDTH_MAX_DELTA_FLUSHING_AMOUNT,
|
||||
client_bandwidth_max_flushing_rate: config
|
||||
.gateway_tasks
|
||||
.debug
|
||||
.client_bandwidth
|
||||
.max_flushing_rate,
|
||||
client_bandwidth_max_delta_flushing_amount: config
|
||||
.gateway_tasks
|
||||
.debug
|
||||
.client_bandwidth
|
||||
.max_delta_flushing_amount,
|
||||
stale_messages_cleaner_run_interval: config
|
||||
.gateway_tasks
|
||||
.debug
|
||||
.stale_messages
|
||||
.cleaner_run_interval,
|
||||
stale_messages_max_age: config.gateway_tasks.debug.stale_messages.max_age,
|
||||
zk_nym_tickets: nym_gateway::config::ZkNymTicketHandlerDebug {
|
||||
revocation_bandwidth_penalty: config
|
||||
.gateway_tasks
|
||||
|
||||
@@ -1095,6 +1095,7 @@ pub async fn try_upgrade_config_v6<P: AsRef<Path>>(
|
||||
.zk_nym_tickets
|
||||
.maximum_time_between_redemption,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
service_providers: ServiceProvidersConfig {
|
||||
|
||||
@@ -665,6 +665,10 @@ impl NymNode {
|
||||
info!("node not running with wireguard: authenticator service provider and wireguard will remain unavailable");
|
||||
}
|
||||
|
||||
// start task for removing stale and un-retrieved client messages
|
||||
let stale_messages_cleaner = gateway_tasks_builder.build_stale_messages_cleaner();
|
||||
stale_messages_cleaner.start();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Generated
+8
-5
@@ -3194,6 +3194,7 @@ dependencies = [
|
||||
"strum 0.26.3",
|
||||
"thiserror",
|
||||
"time",
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3290,6 +3291,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"time",
|
||||
"ts-rs",
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3395,6 +3397,7 @@ dependencies = [
|
||||
"serde",
|
||||
"sha2 0.10.8",
|
||||
"time",
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3422,6 +3425,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"utoipa",
|
||||
"x25519-dalek",
|
||||
]
|
||||
|
||||
@@ -6208,9 +6212,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "utoipa"
|
||||
version = "4.2.3"
|
||||
version = "5.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23"
|
||||
checksum = "435c6f69ef38c9017b4b4eea965dfb91e71e53d869e896db40d1cf2441dd75c0"
|
||||
dependencies = [
|
||||
"indexmap 2.5.0",
|
||||
"serde",
|
||||
@@ -6220,11 +6224,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "utoipa-gen"
|
||||
version = "4.3.0"
|
||||
version = "5.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bf0e16c02bc4bf5322ab65f10ab1149bdbcaa782cba66dc7057370a3f8190be"
|
||||
checksum = "a77d306bc75294fd52f3e99b13ece67c02c1a2789190a6f31d32f736624326f7"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.85",
|
||||
|
||||
@@ -35,7 +35,7 @@ serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "time"] }
|
||||
thiserror = { workspace = true }
|
||||
time = {version = "0.3.36"}
|
||||
time = {version = "0.3.37"}
|
||||
tokio = { workspace = true, features = ["process", "rt-multi-thread"] }
|
||||
tokio-util = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
@@ -18,6 +18,6 @@ nym-sphinx-anonymous-replies = { path = "../../../common/nymsphinx/anonymous-rep
|
||||
nym-ffi-shared = { path = "../shared" }
|
||||
lazy_static = "1.5.0"
|
||||
# error handling
|
||||
anyhow = "1.0.90"
|
||||
anyhow = "1.0.95"
|
||||
# base58 en/decoding
|
||||
bs58 = "0.5.0"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user