mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 18:24:36 +00:00
Introduce secure mode (part 1) (#1808)
Use noise protocol on handshake. Check peer's public key if needed. Also support rekey and replay attack prevention. E2EE and temporary password will be implemented based on this.
This commit is contained in:
+75
-1
@@ -19,15 +19,17 @@ use crate::{
|
||||
defer,
|
||||
instance_manager::NetworkInstanceManager,
|
||||
launcher::add_proxy_network_to_config,
|
||||
proto::common::CompressionAlgoPb,
|
||||
proto::common::{CompressionAlgoPb, SecureModeConfig},
|
||||
rpc_service::ApiRpcServer,
|
||||
tunnel::PROTO_PORT_OFFSET,
|
||||
utils::{init_logger, setup_panic_handler},
|
||||
web_client, ShellType,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use base64::{prelude::BASE64_STANDARD, Engine as _};
|
||||
use cidr::IpCidr;
|
||||
use clap::{CommandFactory, Parser};
|
||||
use rand::rngs::OsRng;
|
||||
use rust_i18n::t;
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
@@ -600,6 +602,29 @@ struct NetworkOptions {
|
||||
num_args = 0..
|
||||
)]
|
||||
stun_servers_v6: Option<Vec<String>>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
env = "ET_SECURE_MODE",
|
||||
help = t!("core_clap.secure_mode").to_string(),
|
||||
num_args = 0..=1,
|
||||
default_missing_value = "true"
|
||||
)]
|
||||
secure_mode: Option<bool>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
env = "ET_LOCAL_PRIVATE_KEY",
|
||||
help = t!("core_clap.local_private_key").to_string()
|
||||
)]
|
||||
local_private_key: Option<String>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
env = "ET_LOCAL_PUBLIC_KEY",
|
||||
help = t!("core_clap.local_public_key").to_string()
|
||||
)]
|
||||
local_public_key: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
@@ -723,6 +748,42 @@ impl NetworkOptions {
|
||||
false
|
||||
}
|
||||
|
||||
fn process_secure_mode_cfg(mut user_cfg: SecureModeConfig) -> anyhow::Result<SecureModeConfig> {
|
||||
if !user_cfg.enabled {
|
||||
return Ok(user_cfg);
|
||||
}
|
||||
|
||||
let private_key = if user_cfg.local_private_key.is_none() {
|
||||
// if no private key, generate random one
|
||||
let private = x25519_dalek::StaticSecret::random_from_rng(OsRng);
|
||||
user_cfg.local_private_key = Some(BASE64_STANDARD.encode(private.clone().as_bytes()));
|
||||
private
|
||||
} else {
|
||||
// check if private key is valid
|
||||
user_cfg.private_key()?
|
||||
};
|
||||
|
||||
let public = x25519_dalek::PublicKey::from(&private_key);
|
||||
|
||||
match user_cfg.local_public_key {
|
||||
None => {
|
||||
user_cfg.local_public_key = Some(BASE64_STANDARD.encode(public.as_bytes()));
|
||||
}
|
||||
Some(ref user_pub) => {
|
||||
let public = user_cfg.public_key()?;
|
||||
if *user_pub != BASE64_STANDARD.encode(public.as_bytes()) {
|
||||
return Err(anyhow::anyhow!(
|
||||
"local public key {} does not match generated public key {}",
|
||||
user_pub,
|
||||
BASE64_STANDARD.encode(public.as_bytes())
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(user_cfg)
|
||||
}
|
||||
|
||||
fn merge_into(&self, cfg: &TomlConfigLoader) -> anyhow::Result<()> {
|
||||
if self.hostname.is_some() {
|
||||
cfg.set_hostname(self.hostname.clone());
|
||||
@@ -760,6 +821,7 @@ impl NetworkOptions {
|
||||
uri: p
|
||||
.parse()
|
||||
.with_context(|| format!("failed to parse peer uri: {}", p))?,
|
||||
peer_public_key: None,
|
||||
});
|
||||
}
|
||||
cfg.set_peers(peers);
|
||||
@@ -820,6 +882,7 @@ impl NetworkOptions {
|
||||
uri: external_nodes.parse().with_context(|| {
|
||||
format!("failed to parse external node uri: {}", external_nodes)
|
||||
})?,
|
||||
peer_public_key: None,
|
||||
});
|
||||
cfg.set_peers(old_peers);
|
||||
}
|
||||
@@ -902,6 +965,17 @@ impl NetworkOptions {
|
||||
cfg.set_port_forwards(old);
|
||||
}
|
||||
|
||||
if let Some(secure_mode) = self.secure_mode {
|
||||
if secure_mode {
|
||||
let c = SecureModeConfig {
|
||||
enabled: secure_mode,
|
||||
local_private_key: self.local_private_key.clone(),
|
||||
local_public_key: self.local_public_key.clone(),
|
||||
};
|
||||
cfg.set_secure_mode(Some(Self::process_secure_mode_cfg(c)?));
|
||||
}
|
||||
}
|
||||
|
||||
let mut f = cfg.get_flags();
|
||||
if let Some(default_protocol) = &self.default_protocol {
|
||||
f.default_protocol = default_protocol.clone()
|
||||
|
||||
Reference in New Issue
Block a user