feat(web): add webhook-managed machine access and multi-instance CLI support (#1989)

* feat: add webhook-managed access and multi-instance CLI support
* fix(foreign): verify credential of foreign credential peer
This commit is contained in:
KKRainbow
2026-03-15 12:08:50 +08:00
committed by GitHub
parent c8f3c5d6aa
commit e6ac31fb20
27 changed files with 2678 additions and 980 deletions
+6 -43
View File
@@ -10,9 +10,10 @@ use std::{
use crate::{
common::{
config::{
get_avaliable_encrypt_methods, load_config_from_file, ConfigFileControl, ConfigLoader,
ConsoleLoggerConfig, FileLoggerConfig, LoggingConfigLoader, NetworkIdentity,
PeerConfig, PortForwardConfig, TomlConfigLoader, VpnPortalConfig,
get_avaliable_encrypt_methods, load_config_from_file, process_secure_mode_cfg,
ConfigFileControl, ConfigLoader, ConsoleLoggerConfig, FileLoggerConfig,
LoggingConfigLoader, NetworkIdentity, PeerConfig, PortForwardConfig, TomlConfigLoader,
VpnPortalConfig,
},
constants::EASYTIER_VERSION,
log,
@@ -27,10 +28,8 @@ use crate::{
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;
@@ -773,42 +772,6 @@ 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());
@@ -1006,7 +969,7 @@ impl NetworkOptions {
local_private_key: Some(credential_secret.clone()),
local_public_key: None,
};
cfg.set_secure_mode(Some(Self::process_secure_mode_cfg(c)?));
cfg.set_secure_mode(Some(process_secure_mode_cfg(c)?));
} else if let Some(secure_mode) = self.secure_mode {
if secure_mode {
let c = SecureModeConfig {
@@ -1014,7 +977,7 @@ impl NetworkOptions {
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)?));
cfg.set_secure_mode(Some(process_secure_mode_cfg(c)?));
}
}