cargo: upgrade (#2116)

update dependencies
This commit is contained in:
Luna Yao
2026-09-16 20:50:43 +08:00
committed by GitHub
parent 5477d4bca2
commit 7223677264
45 changed files with 5152 additions and 4997 deletions
Generated
+2887 -2934
View File
File diff suppressed because it is too large Load Diff
+70
View File
@@ -21,6 +21,76 @@ exclude = [
edition = "2024"
rust-version = "1.95"
[workspace.dependencies]
# Shared versions and sources; members select features and optional dependencies.
anyhow = "1.0"
arc-swap = "1.9"
async-trait = "0.1.92"
atomic-shim = "0.2.0"
auto_impl = "1.3.0"
base64 = "0.23"
bon = "3.10.1"
bytecodec = "0.5.0"
bytes = "1.12.1"
chrono = "0.4.45"
cidr = "0.3.2"
clap = "4.6.7"
crossbeam = "0.8.5"
dashmap = "6.2.1"
easytier = { version = "2.7.0", path = "easytier", default-features = false }
easytier-core = { version = "2.7.0", path = "easytier-core", default-features = false }
easytier-ffi = { path = "easytier-contrib/easytier-ffi", default-features = false }
easytier-proto = { version = "2.7.0", path = "easytier-proto", default-features = false }
futures = "0.3"
guarden = "0.3"
hmac = "0.13.0"
http-body-util = "0.1"
hyper = { version = "1", default-features = false }
hyper-util = { version = "0.1", default-features = false }
indoc = "2.0.7"
log = "0.4"
mimalloc = "*"
once_cell = "1.21"
parking_lot = "0.12.5"
percent-encoding = "2.3.2"
pin-project-lite = "0.2.17"
prost = "0.14.4"
prost-types = "0.14.4"
quanta = "0.12"
# rand 0.10 / x25519-dalek 3 require a coordinated RNG trait migration.
rand = "0.8.8"
reqwest = { version = "0.13.5", default-features = false }
rust-i18n = "4"
rustls = { version = "0.23.45", default-features = false }
# tower-sessions-sqlx-store 0.15 requires SQLx 0.8; SeaORM 2 requires SQLx 0.9.
sea-orm = "1.1.20"
sea-orm-migration = "1.1.20"
serde = "1.0.229"
serde_json = "1.0"
sha2 = "0.11.0"
smoltcp = { version = "0.14.0", default-features = false }
sqlx = "0.8.6"
strum = "0.28.0"
stun_codec = "0.4.0"
sys-locale = "0.3"
tauri = "2.11.5"
tempfile = "3.27.0"
thiserror = "2.0"
thunk-rs = { git = "https://github.com/EasyTier/thunk.git", default-features = false }
tokio = { version = "1.53", default-features = false }
tokio-rustls = { version = "0.26", default-features = false }
tokio-util = "0.7.19"
toml = "1.1.6"
tower-http = "0.7"
tracing = "0.1"
tracing-subscriber = { version = "0.3", default-features = false }
url = "2.5"
uuid = "1.26.1"
winapi = "0.3.9"
x25519-dalek = "2.0.1"
# zerocopy 0.8 requires migrating the packet layout and casting APIs.
zerocopy = "0.7.35"
[profile.dev]
panic = "unwind"
debug = 2
@@ -7,11 +7,11 @@ edition.workspace = true
crate-type = ["cdylib"]
[dependencies]
jni = "0.21"
once_cell = "1.18.0"
log = "0.4"
android_logger = "0.13"
serde = { version = "1.0.220", features = ["derive"] }
serde_json = "1.0"
easytier = { path = "../../easytier" }
easytier-ffi = { path = "../easytier-ffi", default-features = false }
# JNI 0.22 changes native entry points to EnvUnowned and Env.
jni = "0.21.1"
once_cell.workspace = true
log.workspace = true
android_logger = "0.15"
serde_json.workspace = true
easytier = { workspace = true, default-features = true }
easytier-ffi.workspace = true
+14 -10
View File
@@ -15,20 +15,24 @@ ffi-dataplane = [
]
[dependencies]
easytier = { path = "../../easytier", features = ["tracing-log"] }
easytier-core = { path = "../../easytier-core" }
easytier = { workspace = true, default-features = true, features = ["tracing-log"] }
easytier-core = { workspace = true, default-features = true }
once_cell = "1.18.0"
tokio = { version = "1", features = ["rt-multi-thread", "io-util", "time", "sync", "macros"] }
async-trait = "0.1"
log = "0.4"
once_cell.workspace = true
tokio = { workspace = true, default-features = true, features = ["rt-multi-thread", "io-util", "time", "sync", "macros"] }
async-trait.workspace = true
log.workspace = true
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
uuid = "1.17.0"
serde_json.workspace = true
uuid.workspace = true
[build-dependencies]
thunk-rs = { git = "https://github.com/easytier/thunk.git", default-features = false, features = [
thunk-rs = { workspace = true, features = [
"win7",
] }
[package.metadata.cargo-machete]
ignored = [
# Windows-only build.rs setup calls thunk::thunk().
"thunk-rs",
]
+7 -8
View File
@@ -7,18 +7,17 @@ edition.workspace = true
crate-type = ["staticlib", "rlib"]
[dependencies]
serde_json = "1.0"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
easytier-ffi = { path = "../easytier-ffi", default-features = false, features = [
serde_json.workspace = true
tracing.workspace = true
tracing-subscriber = { workspace = true, default-features = true, features = ["env-filter"] }
easytier-ffi = { workspace = true, features = [
"c-abi",
] }
[dev-dependencies]
uuid = "1"
tokio = { version = "1", features = ["io-util"] }
easytier-core = { path = "../../easytier-core" }
easytier-ffi = { path = "../easytier-ffi", default-features = false, features = [
uuid.workspace = true
easytier-core = { workspace = true, default-features = true }
easytier-ffi = { workspace = true, features = [
"c-abi",
"ffi-dataplane",
] }
+3 -3
View File
@@ -8,8 +8,8 @@ license-file = "../../LICENSE"
build = "build.rs"
[dependencies]
anyhow = "1.0"
easytier = { path = "../../easytier", version = "2.7.0", default-features = false, features = [
anyhow.workspace = true
easytier = { workspace = true, features = [
"aes-gcm",
"dhcp-ipv4",
"logging",
@@ -18,4 +18,4 @@ easytier = { path = "../../easytier", version = "2.7.0", default-features = fals
"tun",
"web-client",
] }
tokio = { version = "1", default-features = false, features = ["macros", "rt", "signal"] }
tokio = { workspace = true, features = ["macros", "rt", "signal"] }
+1673 -1615
View File
File diff suppressed because it is too large Load Diff
@@ -40,7 +40,6 @@ napi-ohos = { version = "1.1", default-features = false, features = [
"tokio_io_util",
"deferred_trace",
"napi8",
"node_version_detect",
"web_stream",
] }
once_cell = "1.21.3"
+23 -41
View File
@@ -4,24 +4,22 @@ version = "0.1.0"
edition.workspace = true
[dependencies]
tokio = { version = "1.0", features = ["full"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = { version = "0.4", features = ["serde"] }
uuid = { version = "1.0", features = ["v4", "serde"] }
guarden = "0.1"
tokio = { workspace = true, default-features = true, features = ["full"] }
tracing.workspace = true
tracing-subscriber = { workspace = true, default-features = true, features = ["env-filter"] }
anyhow.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
chrono = { workspace = true, features = ["serde"] }
uuid = { workspace = true, features = ["v4", "serde"] }
# Axum web framework
axum = { version = "0.8.4", features = ["macros"] }
axum-extra = { version = "0.10", features = ["query"] }
tower-http = { version = "0.6", features = ["cors", "compression-full"] }
tower = "0.5"
axum = { version = "0.8.9", features = ["macros"] }
axum-extra = { version = "0.12", features = ["query"] }
tower-http = { workspace = true, features = ["cors", "compression-full"] }
# SeaORM dependencies
sea-orm = { version = "1.1", features = [
sea-orm = { workspace = true, features = [
"sqlx-sqlite",
"runtime-tokio-rustls",
"macros",
@@ -29,39 +27,23 @@ sea-orm = { version = "1.1", features = [
"with-uuid",
"with-json"
] }
sea-orm-migration = { version = "1.1" }
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio-rustls", "chrono", "uuid"] }
sea-orm-migration.workspace = true
sqlx = { workspace = true, features = ["sqlite", "runtime-tokio-rustls", "chrono", "uuid"] }
# Validation
validator = { version = "0.18", features = ["derive"] }
thiserror = "1.0"
jsonwebtoken = "9.0"
# Configuration and serialization
serde_yaml = "0.9"
toml = "0.8"
validator = { version = "0.21", features = ["derive"] }
thiserror.workspace = true
jsonwebtoken = { version = "11.0", features = ["rust_crypto"] }
# Network and async
async-trait = "0.1"
futures = "0.3"
tokio-util = { version = "0.7", features = ["full"] }
# Filesystem operations
tempfile = "3.8"
async-trait.workspace = true
tokio-util = { workspace = true, features = ["full"] }
# Additional utilities
dashmap = "6.1.0"
clap = { version = "4.0", features = ["derive"] }
parking_lot = "0.12"
once_cell = "1.19"
dashmap.workspace = true
clap = { workspace = true, features = ["derive"] }
# EasyTier core
easytier = { path = "../../easytier" }
easytier = { workspace = true, default-features = true }
mimalloc = { version = "*" }
# Testing
[dev-dependencies]
mockall = "0.12"
tokio-test = "0.4"
reqwest = "0.12"
mimalloc.workspace = true
@@ -383,7 +383,14 @@ mod tests {
assert_eq!(node.name, "Test Node");
assert_eq!(node.host, "test.example.com");
assert_eq!(node.port, 11010);
assert!(!node.is_active);
assert!(!node.is_approved);
let node = NodeOperations::update_node_status(&db, node.id, true, Some(1))
.await
.unwrap();
assert!(node.is_active);
assert_eq!(node.current_connections, 1);
// 测试获取节点
let found_node = NodeOperations::get_node_by_id(&db, node.id).await.unwrap();
+67 -60
View File
@@ -18,76 +18,76 @@ crate-type = ["rlib", "cdylib"]
wasm-opt = ["-Oz", "--enable-bulk-memory", "--enable-nontrapping-float-to-int"]
[dependencies]
anyhow = "1.0"
ariadne = { version = "0.5", optional = true }
arc-swap = "1.7"
async-ringbuf = "0.3.1"
async-trait = "0.1.74"
auto_impl = "1.1.0"
base64 = "0.22"
bitflags = "2.5"
bytecodec = "0.4.15"
bytes = "1.5.0"
chrono = { version = "0.4.37", features = ["clock"] }
cidr = { version = "0.3.1", features = ["serde"] }
crossbeam = "0.8.4"
dashmap = "6.0"
derive_builder = "0.20.2"
easytier-proto = { path = "../easytier-proto", default-features = false, features = ["core"] }
futures = "0.3"
guarden = "0.2"
hmac = "0.12.1"
http-body-util = { version = "0.1", optional = true }
hyper = { version = "1", default-features = false, features = ["client", "http1"], optional = true }
hyper-util = { version = "0.1", default-features = false, features = ["tokio"], optional = true }
idna = "1.0"
atomic-shim = "0.2.0"
ordered_hash_map = "0.5.0"
parking_lot = "0.12.1"
percent-encoding = "2.3.1"
petgraph = "0.8.1"
pin-project-lite = "0.2.13"
prefix-trie = { version = "0.7.0", features = ["cidr"] }
prost = "0.14.3"
prost-types = "0.14.3"
rand = "0.8.5"
quanta = "0.12"
anyhow.workspace = true
ariadne = { version = "0.6", optional = true }
arc-swap.workspace = true
async-ringbuf = "0.3.9"
async-trait.workspace = true
auto_impl.workspace = true
base64.workspace = true
bitflags = "2.13"
bytecodec.workspace = true
bytes.workspace = true
chrono = { workspace = true, features = ["clock"] }
cidr = { workspace = true, features = ["serde"] }
crossbeam.workspace = true
dashmap.workspace = true
bon.workspace = true
easytier-proto = { workspace = true, features = ["core"] }
futures.workspace = true
guarden.workspace = true
hmac.workspace = true
http-body-util = { workspace = true, optional = true }
hyper = { workspace = true, features = ["client", "http1"], optional = true }
hyper-util = { workspace = true, features = ["tokio"], optional = true }
idna = "1.1"
atomic-shim.workspace = true
ordered_hash_map = "0.6.1"
parking_lot.workspace = true
percent-encoding.workspace = true
petgraph = "0.8.3"
pin-project-lite.workspace = true
prefix-trie = { version = "0.10.1", features = ["cidr"] }
prost.workspace = true
prost-types.workspace = true
rand.workspace = true
quanta.workspace = true
ring = { version = "0.17", optional = true }
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"], optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
sha2 = "0.10.8"
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp.git", rev = "0a926767a68bc88d5512afefa7529c5ecdade4ea", optional = true, default-features = false }
stun_codec = "0.3.4"
thiserror = "1.0"
tracing = "0.1"
strum = { version = "0.27.2", features = ["derive"] }
toml = "0.8.12"
tokio = { version = "1", default-features = false, features = [
rustls = { workspace = true, features = ["ring", "std", "tls12"], optional = true }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
sha2.workspace = true
smoltcp = { workspace = true, optional = true }
stun_codec.workspace = true
thiserror.workspace = true
tracing.workspace = true
strum = { workspace = true, features = ["derive"] }
toml.workspace = true
tokio = { workspace = true, features = [
"rt",
"time",
"sync",
"macros",
"io-util",
] }
tokio-util = { version = "0.7", features = ["io", "rt"] }
tokio-rustls = { version = "0.26", default-features = false, optional = true }
url = { version = "2.5", features = ["serde"] }
wildmatch = "2.3.4"
uuid = { version = "1.5.0", features = ["v4", "fast-rng", "serde"] }
webpki-roots = { version = "0.26", optional = true }
x25519-dalek = { version = "2.0", features = ["static_secrets"] }
zerocopy = { version = "0.7.32", features = ["derive", "simd"] }
zstd = { version = "0.13", optional = true }
aes-gcm = { version = "0.10.3", optional = true }
chacha20poly1305 = { version = "0.10.1", optional = true }
tokio-util = { workspace = true, features = ["io", "rt"] }
tokio-rustls = { workspace = true, optional = true }
url = { workspace = true, features = ["serde"] }
wildmatch = "2.6.1"
uuid = { workspace = true, features = ["v4", "fast-rng", "serde"] }
webpki-roots = { version = "1.0", optional = true }
x25519-dalek = { workspace = true, features = ["static_secrets"] }
zerocopy = { workspace = true, features = ["derive", "simd"] }
zstd = { version = "0.14", optional = true }
aes-gcm = { version = "0.11.1", optional = true }
chacha20poly1305 = { version = "0.11.0", optional = true }
openssl = { version = "0.10", optional = true, features = ["vendored"] }
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
getrandom-02 = { package = "getrandom", version = "0.2.15", features = ["js"] }
getrandom-03 = { package = "getrandom", version = "0.3.2", features = ["wasm_js"] }
getrandom-02 = { package = "getrandom", version = "0.2.17", features = ["js"] }
getrandom-03 = { package = "getrandom", version = "0.3.4", features = ["wasm_js"] }
snow = { version = "0.10.0", default-features = false, features = ["default-resolver", "default-resolver-crypto"] }
uuid = { version = "1.5.0", features = ["js"] }
uuid = { workspace = true, features = ["js"] }
wasm-bindgen = "0.2"
[target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dependencies]
@@ -153,4 +153,11 @@ tracing-log = ["tracing/log"]
zstd = ["dep:zstd"]
[target.'cfg(not(target_os = "wasi"))'.dev-dependencies]
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
tokio = { workspace = true, features = ["rt-multi-thread"] }
[package.metadata.cargo-machete]
ignored = [
# Enable browser entropy backends for transitive rand/snow dependencies.
"getrandom-02",
"getrandom-03",
]
+3 -3
View File
@@ -428,11 +428,11 @@ pub struct ConsoleLoggerConfig {
pub level: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, derive_builder::Builder)]
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, bon::Builder)]
pub struct LoggingConfig {
#[builder(setter(into, strip_option), default = None)]
#[builder(into)]
pub file_logger: Option<FileLoggerConfig>,
#[builder(setter(into, strip_option), default = None)]
#[builder(into)]
pub console_logger: Option<ConsoleLoggerConfig>,
}
@@ -474,7 +474,7 @@ mod tests {
!try_process_wrapped_tcp_packet_from_nic(
&mut packet,
context(transport),
|_| false,
|_, _| false,
|_| async { true },
)
.await
+1 -1
View File
@@ -16,7 +16,7 @@ use easytier_proto::{
common::{FlagsInConfig, PeerFeatureFlag, SecureModeConfig, StunInfo, TunnelInfo},
peer_rpc::{PeerGroupInfo, TrustedCredentialPubkeyProof},
};
use hmac::{Hmac, Mac};
use hmac::{Hmac, KeyInit, Mac};
use sha2::Sha256;
pub use crate::config::{NetworkIdentity, NetworkSecretDigest};
@@ -12,7 +12,7 @@ use std::{
use dashmap::{DashMap, DashSet};
use easytier_proto::common::FlagsInConfig;
use guarden::{Guard, defer};
use guarden::defer;
use tokio::sync::{
Mutex, RwLock, RwLockReadGuard,
mpsc::{self, UnboundedReceiver, UnboundedSender},
@@ -702,7 +702,7 @@ impl OspfRouteTable {
.load()
.iter()
.filter(|(_, pv)| pv.peer_id != peer_id)
.map(|(cidr, _)| *cidr)
.map(|(cidr, _)| cidr)
.collect()
}
@@ -711,7 +711,7 @@ impl OspfRouteTable {
.load()
.iter()
.filter(|(_, pv)| pv.peer_id != peer_id)
.map(|(cidr, _)| *cidr)
.map(|(cidr, _)| cidr)
.collect()
}
}
+18 -10
View File
@@ -1,5 +1,5 @@
use aes_gcm::{AeadCore, AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit};
use rand::rngs::OsRng;
use aes_gcm::{AeadInOut, Aes128Gcm, Aes256Gcm, Key, KeyInit};
use rand::{RngCore, rngs::OsRng};
use zerocopy::{AsBytes, FromBytes};
use crate::packet::{StandardAeadTail, ZCPacket};
@@ -54,16 +54,16 @@ impl Encryptor for AesGcmCipher {
let tag = aes_tail.tag.into();
let rs = match &self.cipher {
AesGcmEnum::AES128GCM(aes_gcm) => aes_gcm.decrypt_in_place_detached(
AesGcmEnum::AES128GCM(aes_gcm) => aes_gcm.decrypt_inout_detached(
&nonce,
&[],
&mut zc_packet.mut_payload()[..text_len],
(&mut zc_packet.mut_payload()[..text_len]).into(),
&tag,
),
AesGcmEnum::AES256GCM(aes_gcm) => aes_gcm.decrypt_in_place_detached(
AesGcmEnum::AES256GCM(aes_gcm) => aes_gcm.decrypt_inout_detached(
&nonce,
&[],
&mut zc_packet.mut_payload()[..text_len],
(&mut zc_packet.mut_payload()[..text_len]).into(),
&tag,
),
};
@@ -107,16 +107,24 @@ impl Encryptor for AesGcmCipher {
let (tag, nonce) = match &self.cipher {
AesGcmEnum::AES128GCM(aes_gcm) => {
let nonce = nonce.unwrap_or_else(|| Aes128Gcm::generate_nonce(&mut OsRng));
let nonce = nonce.unwrap_or_else(|| {
let mut nonce = [0u8; StandardAeadTail::NONCE_SIZE];
OsRng.fill_bytes(&mut nonce);
nonce.into()
});
(
aes_gcm.encrypt_in_place_detached(&nonce, &[], zc_packet.mut_payload()),
aes_gcm.encrypt_inout_detached(&nonce, &[], zc_packet.mut_payload().into()),
nonce,
)
}
AesGcmEnum::AES256GCM(aes_gcm) => {
let nonce = nonce.unwrap_or_else(|| Aes256Gcm::generate_nonce(&mut OsRng));
let nonce = nonce.unwrap_or_else(|| {
let mut nonce = [0u8; StandardAeadTail::NONCE_SIZE];
OsRng.fill_bytes(&mut nonce);
nonce.into()
});
(
aes_gcm.encrypt_in_place_detached(&nonce, &[], zc_packet.mut_payload()),
aes_gcm.encrypt_inout_detached(&nonce, &[], zc_packet.mut_payload().into()),
nonce,
)
}
+14 -5
View File
@@ -1,5 +1,5 @@
use chacha20poly1305::{AeadCore, AeadInPlace, ChaCha20Poly1305, Key, KeyInit};
use rand::rngs::OsRng;
use chacha20poly1305::{AeadInOut, ChaCha20Poly1305, Key, KeyInit};
use rand::{RngCore, rngs::OsRng};
use zerocopy::{AsBytes, FromBytes};
use crate::packet::{StandardAeadTail, ZCPacket};
@@ -42,7 +42,12 @@ impl Encryptor for ChaCha20Cipher {
let tag = tail.tag.into();
self.cipher
.decrypt_in_place_detached(&nonce, &[], &mut zc_packet.mut_payload()[..text_len], &tag)
.decrypt_inout_detached(
&nonce,
&[],
(&mut zc_packet.mut_payload()[..text_len]).into(),
&tag,
)
.map_err(|_| Error::DecryptionFailed)?;
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
@@ -76,11 +81,15 @@ impl Encryptor for ChaCha20Cipher {
.map_err(|_| Error::EncryptionFailed)
})
.transpose()?
.unwrap_or_else(|| ChaCha20Poly1305::generate_nonce(&mut OsRng));
.unwrap_or_else(|| {
let mut nonce = [0u8; StandardAeadTail::NONCE_SIZE];
OsRng.fill_bytes(&mut nonce);
nonce.into()
});
let tag = self
.cipher
.encrypt_in_place_detached(&nonce, &[], zc_packet.mut_payload())
.encrypt_inout_detached(&nonce, &[], zc_packet.mut_payload().into())
.map_err(|_| Error::EncryptionFailed)?;
let tail = StandardAeadTail {
+1 -1
View File
@@ -8,7 +8,7 @@ use std::{
use anyhow::anyhow;
use atomic_shim::AtomicU64;
use hmac::{Hmac, Mac as _};
use hmac::{Hmac, KeyInit as _, Mac as _};
use rand::RngCore as _;
use sha2::Sha256;
use zerocopy::FromBytes;
+29 -26
View File
@@ -14,54 +14,50 @@ crate-type = ["staticlib", "cdylib", "rlib"]
[dependencies]
# wry 0.47 may crash on android, see https://github.com/EasyTier/EasyTier/issues/527
tauri = { version = "2.7.0", features = [
tauri = { workspace = true, features = [
"tray-icon",
"image-png",
"image-ico",
"devtools",
] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
easytier = { path = "../../easytier" }
easytier-core = { path = "../../easytier-core" }
tokio = { version = "1", features = ["full"] }
anyhow = "1.0"
chrono = { version = "0.4.37", features = ["serde"] }
easytier = { workspace = true, default-features = true }
easytier-core = { workspace = true, default-features = true }
tokio = { workspace = true, default-features = true, features = ["full"] }
anyhow.workspace = true
once_cell = "1.18.0"
dashmap = "6.0"
gethostname = "1.0.2"
once_cell.workspace = true
dashmap.workspace = true
dunce = "1.0.4"
tauri-plugin-shell = "2.3.0"
tauri-plugin-process = "2.3.0"
tauri-plugin-clipboard-manager = "2.3.0"
tauri-plugin-positioner = { version = "2.3.0", features = ["tray-icon"] }
tauri-plugin-shell = "2.3.6"
tauri-plugin-process = "2.3.1"
tauri-plugin-clipboard-manager = "2.3.3"
tauri-plugin-vpnservice = { path = "../../tauri-plugin-vpnservice" }
tauri-plugin-os = "2.3.0"
tauri-plugin-os = "2.3.2"
uuid = "1.17.0"
async-trait = "0.1.89"
uuid.workspace = true
async-trait.workspace = true
url = { version = "2.5", features = ["serde"] }
url = { workspace = true, features = ["serde"] }
[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "0.52", features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] }
winapi = { version = "0.3.9", features = ["securitybaseapi", "processthreadsapi"] }
windows = { version = "0.62", features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] }
winapi = { workspace = true, features = ["securitybaseapi", "processthreadsapi"] }
[target.'cfg(target_family = "unix")'.dependencies]
libc = "0.2"
[target.'cfg(target_os = "macos")'.dependencies]
security-framework-sys = "2.9.0"
security-framework-sys = "2.17.0"
[build-dependencies]
tauri-build = { version = "2.0.0-rc", features = [] }
thunk-rs = { git = "https://github.com/easytier/thunk.git", default-features = false, features = [
tauri-build = { version = "2.6.3", features = [] }
thunk-rs = { workspace = true, features = [
"win7",
] }
@@ -71,4 +67,11 @@ thunk-rs = { git = "https://github.com/easytier/thunk.git", default-features = f
custom-protocol = ["tauri/custom-protocol"]
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-single-instance = "2.3.2"
tauri-plugin-single-instance = "2.4.4"
[package.metadata.cargo-machete]
ignored = [
# Called by build.rs; thunk is only used on Windows.
"tauri-build",
"thunk-rs",
]
@@ -5,7 +5,7 @@ buildscript {
}
dependencies {
classpath("com.android.tools.build:gradle:8.3.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.21")
}
}
@@ -19,4 +19,3 @@ allprojects {
tasks.register("clean").configure {
delete("build")
}
@@ -12,7 +12,6 @@ use winapi::shared::minwindef::{DWORD, LPVOID};
use winapi::um::processthreadsapi::{GetCurrentProcess, OpenProcessToken};
use winapi::um::securitybaseapi::GetTokenInformation;
use winapi::um::winnt::{HANDLE, TOKEN_ELEVATION, TOKEN_QUERY, TokenElevation};
use windows::Win32::Foundation::HWND;
use windows::Win32::UI::Shell::ShellExecuteW;
use windows::Win32::UI::WindowsAndMessaging::SW_HIDE;
use windows::core::{HSTRING, PCWSTR, w};
@@ -97,7 +96,7 @@ impl Command {
// the cwd always point to %SystemRoot%\System32 and cannot be changed by settting lpdirectory param
let r = unsafe {
ShellExecuteW(
HWND(0),
None,
w!("runas"),
&HSTRING::from(self.cmd.get_program()),
&HSTRING::from(parameters),
+3 -6
View File
@@ -23,9 +23,7 @@ use easytier::web_client::{self, WebClient};
use easytier::{
common::config::{NetworkConfig, NetworkConfigExt},
common::{
config::{
ConfigLoader, ConfigSource, FileLoggerConfig, LoggingConfigBuilder, TomlConfigLoader,
},
config::{ConfigLoader, ConfigSource, FileLoggerConfig, LoggingConfig, TomlConfigLoader},
log,
},
instance::factory::{NativeInstanceManager, native_instance_manager},
@@ -1463,7 +1461,7 @@ pub fn run_gui() -> std::process::ExitCode {
let Ok(log_dir) = get_log_dir(app.app_handle()) else {
return Ok(());
};
let config = LoggingConfigBuilder::default()
let config = LoggingConfig::builder()
.file_logger(FileLoggerConfig {
dir: Some(log_dir.to_string_lossy().to_string()),
level: None,
@@ -1471,8 +1469,7 @@ pub fn run_gui() -> std::process::ExitCode {
size_mb: None,
count: None,
})
.build()
.map_err(|e| e.to_string())?;
.build();
let Ok(_) = log::init(&config, true) else {
return Ok(());
};
+41 -25
View File
@@ -13,44 +13,44 @@ license-file = "../LICENSE"
build = "build/main.rs"
[dependencies]
anyhow = { version = "1.0", optional = true }
async-trait = { version = "0.1.74", optional = true }
auto_impl = { version = "1.1.0", optional = true }
base64 = { version = "0.22", optional = true }
bytes = { version = "1.5.0", optional = true }
chrono = { version = "0.4.37", features = ["serde"], optional = true }
cidr = { version = "0.3.1", features = ["serde"], optional = true }
hmac = { version = "0.12.1", optional = true }
prost = { version = "0.14.3", optional = true }
prost-types = { version = "0.14.3", optional = true }
prost-wkt-types = { version = "0.7.1", optional = true }
anyhow = { workspace = true, optional = true }
async-trait = { workspace = true, optional = true }
auto_impl = { workspace = true, optional = true }
base64 = { workspace = true, optional = true }
bytes = { workspace = true, optional = true }
chrono = { workspace = true, features = ["serde"], optional = true }
cidr = { workspace = true, features = ["serde"], optional = true }
hmac = { workspace = true, optional = true }
prost = { workspace = true, optional = true }
prost-types = { workspace = true, optional = true }
prost-wkt-types = { version = "0.7.2", optional = true }
pbjson = { version = "0.9.0", optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }
serde_json = { version = "1", optional = true }
sha2 = { version = "0.10.8", optional = true }
thiserror = { version = "1.0", optional = true }
tokio = { version = "1", default-features = false, features = ["time"], optional = true }
url = { version = "2.5", features = ["serde"], optional = true }
uuid = { version = "1.5.0", features = ["serde"], optional = true }
x25519-dalek = { version = "2.0", features = ["static_secrets"], optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
serde_json = { workspace = true, optional = true }
sha2 = { workspace = true, optional = true }
thiserror = { workspace = true, optional = true }
tokio = { workspace = true, features = ["time"], optional = true }
url = { workspace = true, features = ["serde"], optional = true }
uuid = { workspace = true, features = ["serde"], optional = true }
x25519-dalek = { workspace = true, features = ["static_secrets"], optional = true }
[build-dependencies]
indoc = "2.0"
indoc.workspace = true
pbjson-build = "0.9.0"
proc-macro2 = "1"
prost-build = "0.14.3"
prost-build = "0.14.4"
quote = "1"
[target.'cfg(windows)'.build-dependencies]
reqwest = { version = "0.12.12", features = ["blocking"] }
zip = "4.0.0"
reqwest = { workspace = true, default-features = true, features = ["blocking"] }
zip = "8.6.0"
[dev-dependencies]
tokio = { version = "1", default-features = false, features = [
tokio = { workspace = true, features = [
"macros",
"rt",
] }
uuid = { version = "1.5.0", features = [
uuid = { workspace = true, features = [
"v4",
"fast-rng",
] }
@@ -99,3 +99,19 @@ websocket = []
wireguard = []
zstd = []
json-rpc = ["dep:prost-wkt-types"]
[package.metadata.cargo-machete]
ignored = [
# Used by build/main.rs and build/rpc.rs, including the Windows protoc download.
"indoc",
"pbjson-build",
"proc-macro2",
"prost-build",
"quote",
"reqwest",
"zip",
# Referenced by generated protobuf, serde and RPC code.
"auto_impl",
"pbjson",
"serde",
]
+1 -1
View File
@@ -1,4 +1,4 @@
use hmac::{Hmac, Mac};
use hmac::{Hmac, KeyInit, Mac};
use prost::Message;
use sha2::Sha256;
#[cfg(feature = "api")]
+44 -37
View File
@@ -5,78 +5,85 @@ edition.workspace = true
description = "Config server for easytier. easytier-core gets config from this and web frontend use it as restful api server."
[dependencies]
easytier = { path = "../easytier" }
easytier-core = { path = "../easytier-core" }
tracing = "0.1"
anyhow = { version = "1.0" }
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
tokio-util = { version = "0.7", features = ["rt"] }
dashmap = "6.1"
url = "2.2"
async-trait = "0.1"
easytier = { workspace = true, default-features = true }
easytier-core = { workspace = true, default-features = true }
tracing.workspace = true
anyhow.workspace = true
thiserror.workspace = true
tokio = { workspace = true, default-features = true, features = ["full"] }
tokio-util = { workspace = true, features = ["rt"] }
dashmap.workspace = true
url.workspace = true
async-trait.workspace = true
maxminddb = "0.24"
once_cell = "1.18"
maxminddb = "0.32"
axum = { version = "0.7", features = ["macros"] }
axum-login = { version = "0.16" }
axum = { version = "0.8", features = ["macros"] }
axum-login = { version = "0.18" }
password-auth = { version = "1.0.0" }
axum-messages = "0.7.0"
axum-messages = "0.8.0"
axum-embed = { version = "0.1.0", optional = true }
tower-sessions-sqlx-store = { version = "0.14.1", features = ["sqlite"] }
tower-sessions = { version = "0.13.0", default-features = false, features = [
tower-sessions-sqlx-store = { version = "0.15.0", features = ["sqlite"] }
# Match axum-login 0.18 and the SQLx session store.
tower-sessions = { version = "0.14.0", default-features = false, features = [
"signed",
"axum-core",
] }
tower-http = { version = "0.6", features = ["cors", "compression-full"] }
sqlx = { version = "0.8", features = ["sqlite"] }
sea-orm = { version = "1.1", features = [
tower-http = { workspace = true, features = ["cors", "compression-full"] }
sqlx = { workspace = true, features = ["sqlite"] }
sea-orm = { workspace = true, features = [
"sqlx-sqlite",
"runtime-tokio-rustls",
"macros",
] }
sea-orm-migration = { version = "1.1" }
sea-orm-migration.workspace = true
# for captcha
rust-embed = { version = "8.5.0", features = ["debug-embed", "include-exclude"] }
base64 = "0.22"
rand = "0.8"
image = { version = "0.24", default-features = false, features = ["png"] }
rusttype = "0.9.3"
imageproc = "0.23.0"
rust-embed = { version = "8.12.0", features = ["debug-embed", "include-exclude"] }
base64.workspace = true
rand.workspace = true
image = { version = "0.25", default-features = false, features = ["png"] }
ab_glyph = "0.2.32"
imageproc = { version = "0.27.0", default-features = false, features = ["text"] }
rust-i18n = "3"
sys-locale = "0.3"
clap = { version = "4.4.8", features = [
rust-i18n.workspace = true
sys-locale.workspace = true
clap = { workspace = true, features = [
"string",
"unicode",
"derive",
"wrap_help",
"env",
] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "1.5.0", features = [
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
uuid = { workspace = true, features = [
"v4",
"fast-rng",
"macro-diagnostics",
"serde",
] }
chrono = { version = "0.4.37", features = ["serde"] }
chrono = { workspace = true, features = ["serde"] }
openidconnect = { version = "4.0", default-features = false, features = ["accept-rfc3339-timestamps", "reqwest"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
reqwest = { workspace = true, features = ["json", "rustls"] }
subtle = "2.6"
mimalloc = { version = "*" }
mimalloc.workspace = true
[build-dependencies]
thunk-rs = { git = "https://github.com/easytier/thunk.git", default-features = false, features = [
thunk-rs = { workspace = true, features = [
"win7",
] }
[features]
default = []
embed = ["dep:axum-embed"]
[package.metadata.cargo-machete]
ignored = [
# Windows-only build.rs setup calls thunk::thunk().
"thunk-rs",
]
@@ -485,9 +485,7 @@ mod tests {
common::config::{ConfigLoader as _, ConfigSource, NetworkConfigExt},
proto::api::manage::{ConfigSource as RpcConfigSource, NetworkConfig, NetworkMeta},
};
use easytier_core::management::remote_client::{
ListNetworkProps, PersistentConfig as _, Storage as _,
};
use easytier_core::management::remote_client::ListNetworkProps;
use serde_json::json;
use super::*;
+30 -21
View File
@@ -430,29 +430,33 @@ impl ClientManager {
}
let location = if let Some(db) = &*geoip_db {
match db.lookup::<geoip2::City>(ip) {
Ok(city) => {
match db
.lookup(ip)
.and_then(|result| result.decode::<geoip2::City>())
{
Ok(Some(city)) => {
let country = city
.country
.and_then(|c| c.names)
.and_then(|n| {
n.get("zh-CN")
.or_else(|| n.get("en"))
.map(|s| s.to_string())
})
.unwrap_or_else(|| "海外".to_string());
let city_name = city.city.and_then(|c| c.names).and_then(|n| {
n.get("zh-CN")
.or_else(|| n.get("en"))
.map(|s| s.to_string())
});
let region = city.subdivisions.map(|r| {
r.iter()
.filter_map(|x| x.names.as_ref())
.filter_map(|x| x.get("zh-CN").or_else(|| x.get("en")))
.map(|x| x.to_string())
.names
.simplified_chinese
.or(city.country.names.english)
.unwrap_or("海外")
.to_string();
let city_name = city
.city
.names
.simplified_chinese
.or(city.city.names.english)
.map(str::to_string);
let region = (!city.subdivisions.is_empty()).then(|| {
city.subdivisions
.iter()
.filter_map(|subdivision| {
subdivision
.names
.simplified_chinese
.or(subdivision.names.english)
})
.collect::<Vec<_>>()
.join(",")
});
@@ -463,6 +467,11 @@ impl ClientManager {
region,
}
}
Ok(None) => Location {
country: "海外".to_string(),
city: None,
region: None,
},
Err(err) => {
tracing::debug!("GeoIP lookup failed for {}: {}", ip, err);
Location {
@@ -5,7 +5,7 @@ use super::super::utils::font;
use base64::Engine;
use base64::prelude::BASE64_STANDARD;
use rusttype::Font;
use ab_glyph::FontArc;
use std::fmt::Debug;
use std::io::Write;
use std::sync::Arc;
@@ -142,7 +142,7 @@ impl Captcha {
}
}
pub fn get_font(&'_ mut self) -> Arc<Font<'_>> {
pub fn get_font(&'_ mut self) -> Arc<FontArc> {
if let Some(font) = font::get_font(&self.font_name) {
font
} else {
@@ -7,10 +7,10 @@ use super::super::base::captcha::{AbstractCaptcha, Captcha};
use super::super::{CaptchaFont, NewCaptcha};
use ab_glyph::{FontArc, PxScale};
use image::{ImageBuffer, Rgba};
use imageproc::drawing;
use rand::{Rng, rngs::ThreadRng};
use rusttype::{Font, Scale};
use std::io::{Cursor, Write};
use std::sync::Arc;
@@ -40,7 +40,7 @@ mod color {
}
///the builder of captcha
pub struct CaptchaBuilder<'a, 'b> {
pub struct CaptchaBuilder<'b> {
///captcha image width
pub width: u32,
///captcha image height
@@ -55,7 +55,7 @@ pub struct CaptchaBuilder<'a, 'b> {
///image background color (optional)
pub background_color: Option<Rgba<u8>>,
///fonts collection for text
pub fonts: &'b [Arc<Font<'a>>],
pub fonts: &'b [Arc<FontArc>],
///The maximum number of lines to draw behind of the image
pub max_behind_lines: Option<u32>,
///The maximum number of lines to draw in front of the image
@@ -64,7 +64,7 @@ pub struct CaptchaBuilder<'a, 'b> {
pub max_ellipse_lines: Option<u32>,
}
impl<'a, 'b> Default for CaptchaBuilder<'a, 'b> {
impl<'b> Default for CaptchaBuilder<'b> {
fn default() -> Self {
Self {
width: 150,
@@ -80,7 +80,7 @@ impl<'a, 'b> Default for CaptchaBuilder<'a, 'b> {
}
}
impl<'a, 'b> CaptchaBuilder<'a, 'b> {
impl<'b> CaptchaBuilder<'b> {
fn write_phrase(
&self,
image: &mut ImageBuffer<Rgba<u8>, Vec<u8>>,
@@ -90,25 +90,13 @@ impl<'a, 'b> CaptchaBuilder<'a, 'b> {
//println!("phrase={}", phrase);
//println!("width={}, height={}", self.width, self.height);
let font_size = (self.width as f32) / (self.length as f32) - rng.gen_range(1.0..=4.0);
let scale = Scale::uniform(font_size);
let scale = PxScale::from(font_size);
if self.fonts.is_empty() {
panic!("no fonts loaded");
}
let font_index = rng.gen_range(0..self.fonts.len());
let font = &self.fonts[font_index];
let glyphs: Vec<_> = font
.layout(phrase, scale, rusttype::point(0.0, 0.0))
.collect();
let text_height = {
let v_metrics = font.v_metrics(scale);
(v_metrics.ascent - v_metrics.descent).ceil() as u32
};
let text_width = {
let min_x = glyphs.first().unwrap().pixel_bounding_box().unwrap().min.x;
let max_x = glyphs.last().unwrap().pixel_bounding_box().unwrap().max.x;
let last_x_pos = glyphs.last().unwrap().position().x as i32;
(max_x + last_x_pos - min_x) as u32
};
let font = self.fonts[font_index].as_ref();
let (text_width, text_height) = drawing::text_size(scale, font, phrase);
let node_width = text_width / self.length;
//println!("text_width={}, text_height={}", text_width, text_height);
let mut x = ((self.width as i32) - (text_width as i32)) / 2;
@@ -291,7 +279,7 @@ impl AbstractCaptcha for SpecCaptcha {
..Default::default()
};
let image = builder.build_image(phrase.iter().collect());
let format = image::ImageOutputFormat::Png;
let format = image::ImageFormat::Png;
let mut raw_data: Vec<u8> = Vec::new();
image.write_to(&mut Cursor::new(&mut raw_data), format)?;
out.write_all(&raw_data)?;
@@ -313,6 +301,22 @@ impl AbstractCaptcha for SpecCaptcha {
#[cfg(test)]
mod test {
use super::*;
#[test]
fn it_works() {}
fn captcha_renders_text_and_encodes_png() {
let mut captcha = SpecCaptcha::with_size_and_len(150, 48, 5);
let mut png = Vec::new();
captcha.out(&mut png).unwrap();
let decoded = image::load_from_memory_with_format(&png, image::ImageFormat::Png)
.unwrap()
.to_rgba8();
assert_eq!(decoded.dimensions(), (150, 48));
assert_eq!(captcha.get_chars().len(), 5);
assert!(
decoded
.pixels()
.any(|pixel| pixel[0] < 160 && pixel[1] < 160 && pixel[2] < 160)
);
}
}
@@ -1,5 +1,5 @@
use ab_glyph::FontArc;
use rust_embed::RustEmbed;
use rusttype::Font;
use std::error::Error;
use std::sync::Arc;
@@ -11,7 +11,7 @@ struct FontAssets;
// pub(crate) static ref FONTS: RwLock<HashMap<String, Arc<Font>>> = Default::default();
// }
pub fn get_font(font_name: &'_ str) -> Option<Arc<Font<'_>>> {
pub fn get_font(font_name: &'_ str) -> Option<Arc<FontArc>> {
// let fonts_cell = FONTS.get_or_init(|| Default::default());
// let guard = fonts_cell.read();
//
@@ -31,10 +31,10 @@ pub fn get_font(font_name: &'_ str) -> Option<Arc<Font<'_>>> {
// }
}
pub fn load_font(font_name: &'_ str) -> Result<Option<Font<'_>>, Box<dyn Error>> {
pub fn load_font(font_name: &'_ str) -> Result<Option<FontArc>, Box<dyn Error>> {
match FontAssets::get(font_name) {
Some(assets) => {
let font = Font::try_from_vec(Vec::from(assets.data)).unwrap();
let font = FontArc::try_from_vec(Vec::from(assets.data))?;
Ok(Some(font))
}
None => {
+1 -1
View File
@@ -252,7 +252,7 @@ impl RestfulServer {
get(Self::handle_list_all_sessions_internal),
)
.route(
"/api/internal/users/:user-id/sessions/:machine-id",
"/api/internal/users/{user-id}/sessions/{machine-id}",
delete(Self::handle_disconnect_session_internal),
)
.merge(NetworkApi::build_route_internal())
+10 -10
View File
@@ -505,7 +505,7 @@ impl NetworkApi {
pub fn build_route_internal() -> Router<AppStateInner> {
Router::new()
.route(
"/api/internal/users/:user-id/machines/:machine-id/networks",
"/api/internal/users/{user-id}/machines/{machine-id}/networks",
put(Self::handle_reconcile_managed_network_configs_internal)
.patch(Self::handle_patch_managed_network_configs_internal)
.layer(DefaultBodyLimit::max(MAX_MANAGED_CONFIG_REQUEST_BODY_SIZE))
@@ -513,11 +513,11 @@ impl NetworkApi {
.get(Self::handle_list_network_instance_ids_internal),
)
.route(
"/api/internal/users/:user-id/machines/:machine-id/networks/:inst-id",
"/api/internal/users/{user-id}/machines/{machine-id}/networks/{inst-id}",
delete(Self::handle_remove_network_instance_internal),
)
.route(
"/api/internal/users/:user-id/machines/:machine-id/networks/info",
"/api/internal/users/{user-id}/machines/{machine-id}/networks/info",
get(Self::handle_collect_network_info_internal),
)
}
@@ -526,31 +526,31 @@ impl NetworkApi {
Router::new()
.route("/api/v1/machines", get(Self::handle_list_machines))
.route(
"/api/v1/machines/:machine-id/validate-config",
"/api/v1/machines/{machine-id}/validate-config",
post(Self::handle_validate_config),
)
.route(
"/api/v1/machines/:machine-id/networks",
"/api/v1/machines/{machine-id}/networks",
post(Self::handle_run_network_instance).get(Self::handle_list_network_instance_ids),
)
.route(
"/api/v1/machines/:machine-id/networks/:inst-id",
"/api/v1/machines/{machine-id}/networks/{inst-id}",
delete(Self::handle_remove_network_instance).put(Self::handle_update_network_state),
)
.route(
"/api/v1/machines/:machine-id/networks/info",
"/api/v1/machines/{machine-id}/networks/info",
get(Self::handle_collect_network_info),
)
.route(
"/api/v1/machines/:machine-id/networks/info/:inst-id",
"/api/v1/machines/{machine-id}/networks/info/{inst-id}",
get(Self::handle_collect_one_network_info),
)
.route(
"/api/v1/machines/:machine-id/networks/config/:inst-id",
"/api/v1/machines/{machine-id}/networks/config/{inst-id}",
get(Self::handle_get_network_config).put(Self::handle_save_network_config),
)
.route(
"/api/v1/machines/:machine-id/networks/metas",
"/api/v1/machines/{machine-id}/networks/metas",
post(Self::handle_get_network_metas),
)
}
+1
View File
@@ -1,3 +1,4 @@
use openidconnect::reqwest;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
+2 -2
View File
@@ -205,7 +205,7 @@ pub async fn handle_proxy_rpc(
pub fn router() -> Router<super::AppStateInner> {
Router::new().route(
"/api/v1/machines/:machine-id/proxy-rpc",
"/api/v1/machines/{machine-id}/proxy-rpc",
post(handle_proxy_rpc),
)
}
@@ -227,7 +227,7 @@ pub async fn handle_proxy_rpc_internal(
pub fn router_internal() -> Router<super::AppStateInner> {
Router::new().route(
"/api/internal/users/:user-id/machines/:machine-id/proxy-rpc",
"/api/internal/users/{user-id}/machines/{machine-id}/proxy-rpc",
post(handle_proxy_rpc_internal),
)
}
-3
View File
@@ -1,6 +1,5 @@
use std::collections::HashSet;
use async_trait::async_trait;
use axum_login::{AuthUser, AuthnBackend, AuthzBackend, UserId};
use password_auth::verify_password;
use sea_orm::{
@@ -148,7 +147,6 @@ pub enum Error {
TaskJoin(#[from] task::JoinError),
}
#[async_trait]
impl AuthnBackend for Backend {
type User = User;
type Credentials = Credentials;
@@ -208,7 +206,6 @@ impl From<&str> for Permission {
}
}
#[async_trait]
impl AuthzBackend for Backend {
type Permission = Permission;
+111 -97
View File
@@ -24,7 +24,7 @@ required-features = ["management"]
[[bin]]
name = "easytier-cli"
path = "src/easytier-cli.rs"
required-features = ["management"]
required-features = ["management", "cli"]
[lib]
name = "easytier"
@@ -35,36 +35,35 @@ name = "packet_bytes_extraction"
harness = false
[dependencies]
easytier-core = { path = "../easytier-core", version = "2.7.0", default-features = false }
easytier-proto = { path = "../easytier-proto", version = "2.7.0", default-features = false, features = ["api", "core"] }
easytier-core.workspace = true
easytier-proto = { workspace = true, features = ["api", "core"] }
git-version = "0.3.9"
tracing = "0.1"
log = { version = "0.4", features = ["std"] }
tracing-subscriber = { version = "0.3", default-features = false, features = [
tracing.workspace = true
log = { workspace = true, features = ["std"] }
tracing-subscriber = { workspace = true, features = [
"registry",
], optional = true }
derive_more = { version = "2.1.1", features = ["full"] }
console-subscriber = { version = "0.4.1", optional = true }
indoc = "2.0.7"
console-subscriber = { version = "0.5.0", optional = true }
indoc.workspace = true
paste = "1.0"
thiserror = "1.0"
auto_impl = "1.1.0"
crossbeam = "0.8.4"
arc-swap = "1.7"
toml = "0.8.12"
chrono = { version = "0.4.37", features = ["serde"] }
thiserror.workspace = true
crossbeam.workspace = true
arc-swap.workspace = true
toml.workspace = true
chrono = { workspace = true, features = ["serde"] }
guarden = "0.2"
quanta = "0.12"
guarden.workspace = true
quanta.workspace = true
strum = { version = "0.27.2", features = ["derive"] }
strum = { workspace = true, features = ["derive"] }
gethostname = "0.5.0"
gethostname = "1.1.0"
futures = { version = "0.3", features = ["bilock", "unstable"] }
futures = { workspace = true, features = ["bilock", "unstable"] }
tokio = { version = "1", default-features = false, features = [
tokio = { workspace = true, features = [
"fs",
"io-util",
"macros",
@@ -75,27 +74,27 @@ tokio = { version = "1", default-features = false, features = [
"sync",
"time",
] }
tokio-util = { version = "0.7.9", features = ["codec", "net", "io", "rt"] }
tokio-util = { workspace = true, features = ["codec", "net", "io", "rt"] }
async-trait = "0.1.74"
async-trait.workspace = true
dashmap = "6.0"
dashmap.workspace = true
moka = { version = "0.12", features = ["future"] }
# for full-path zero-copy
zerocopy = { version = "0.7.32", features = ["derive", "simd"] }
bytes = "1.5.0"
pin-project-lite = "0.2.13"
zerocopy = { workspace = true, features = ["derive", "simd"] }
bytes.workspace = true
pin-project-lite.workspace = true
atomic_refcell = "0.1.13"
atomic-write-file = { version = "0.2.3", optional = true }
atomic_refcell = "0.1.14"
atomic-write-file = { version = "0.3.1", optional = true }
quinn = { version = "0.11.8", optional = true, features = ["ring"] }
quinn-proto = { version = "0.11.12", optional = true }
quinn = { version = "0.11.12", optional = true, features = ["ring"] }
quinn-proto = { version = "0.11.18", optional = true }
seahash = { version = "4.1.0", optional = true }
rustls = { version = "0.23.0", features = [
rustls = { workspace = true, features = [
"ring", "tls12"
], default-features = false, optional = true }
], optional = true }
# for websocket
tokio-websockets = { version = "0.13.2", git = "https://github.com/EasyTier/tokio-websockets", optional = true, features = [
@@ -109,15 +108,15 @@ forwarded-header-value = { version = "0.1.1", optional = true }
http = { version = "1", default-features = false, features = [
"std",
], optional = true }
rcgen = { version = "0.12.1", optional = true }
tokio-rustls = { version = "0.26", default-features = false, optional = true }
rcgen = { version = "0.14.10", optional = true }
tokio-rustls = { workspace = true, optional = true }
# for tap device
tun = { package = "tun-easytier", git = "https://github.com/EasyTier/rust-tun", features = [
"async",
], optional = true }
# for net ns
nix = { version = "0.29.0", features = [
nix = { version = "0.31.3", features = [
"sched",
"socket",
"ioctl",
@@ -125,7 +124,7 @@ nix = { version = "0.29.0", features = [
"fs",
] }
uuid = { version = "1.5.0", features = [
uuid = { workspace = true, features = [
"v4",
"fast-rng",
"macro-diagnostics",
@@ -133,73 +132,73 @@ uuid = { version = "1.5.0", features = [
] }
# for ring tunnel
once_cell = "1.18.0"
once_cell.workspace = true
# for rpc
prost = "0.14.3"
anyhow = "1.0"
prost.workspace = true
anyhow.workspace = true
url = { version = "2.5", features = ["serde"] }
percent-encoding = "2.3.1"
url = { workspace = true, features = ["serde"] }
percent-encoding.workspace = true
# for tun packet
byteorder = "1.5.0"
# for proxy
cidr = { version = "0.3.1", features = ["serde"] }
socket2 = { version = "0.5.10", features = ["all"] }
cidr = { workspace = true, features = ["serde"] }
socket2 = { version = "0.6.5", features = ["all"] }
# for hole punching
rand = "0.8.5"
rand.workspace = true
serde = { version = "1.0", features = ["derive"] }
serde = { workspace = true, features = ["derive"] }
pnet_datalink = { version = "0.35.0", optional = true }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp.git", rev = "0a926767a68bc88d5512afefa7529c5ecdade4ea", optional = true, default-features = false, features = [
smoltcp = { workspace = true, optional = true, features = [
"std",
"medium-ethernet",
"proto-ipv4",
"proto-ipv6",
"socket-raw",
] }
serde_json = "1"
serde_json.workspace = true
clap = { version = "4.5.30", features = [
clap = { workspace = true, features = [
"string",
"unicode",
"derive",
"wrap_help",
"env",
] }
clap_complete = { version = "4.5.55" }
clap_complete_nushell = { version = "4.5.10" }
clap_complete = { version = "4.6.10" }
clap_complete_nushell = { version = "4.6.2" }
async-recursion = "1.0.5"
async-recursion = "1.1.1"
network-interface = "2.0.5"
# for wireguard
boringtun = { package = "boringtun-easytier", version = "0.6.1", optional = true }
hkdf = { version = "0.12", optional = true }
sha2 = { version = "0.10", optional = true }
hkdf = { version = "0.13", optional = true }
sha2 = { workspace = true, optional = true }
# for cli
tabled = "0.16"
humansize = "2.1.3"
terminal_size = "0.4"
unicode-width = "0.1"
tabled = { version = "0.22", optional = true }
humansize = { version = "2.1.3", optional = true }
terminal_size = { version = "0.4", optional = true }
unicode-width = { version = "0.2", optional = true }
base64 = "0.22"
base64.workspace = true
mimalloc = { version = "*", optional = true }
mimalloc = { workspace = true, optional = true }
# mips
atomic-shim = "0.2.0"
atomic-shim.workspace = true
parking_lot = { version = "0.12.0" }
parking_lot.workspace = true
rust-i18n = "3"
sys-locale = "0.3"
rust-i18n.workspace = true
sys-locale.workspace = true
service-manager = { git = "https://github.com/EasyTier/service-manager-rs.git", branch = "main" }
@@ -216,26 +215,26 @@ hickory-server = { version = "0.25.2", features = [
"resolver",
], optional = true }
bon = "3.9.1"
derive_builder = "0.20.2"
humantime-serde = "1.1.1"
shellexpand = "3.1.1"
bon.workspace = true
derive_builder = { version = "0.20.2", optional = true }
humantime-serde = { version = "1.1.1", optional = true }
shellexpand = "3.1.2"
# for fake tcp
flume = { version = "0.12", optional = true }
# for upnp
http-body-util = { version = "0.1", optional = true }
hyper = { version = "1", default-features = false, features = ["client", "http1"], optional = true }
hyper-util = { version = "0.1", default-features = false, features = ["tokio"], optional = true }
http-body-util = { workspace = true, optional = true }
hyper = { workspace = true, features = ["client", "http1"], optional = true }
hyper-util = { workspace = true, features = ["tokio"], optional = true }
natpmp = { version = "0.5.0", optional = true }
xmltree = { version = "0.10", optional = true }
xmltree = { version = "0.12", optional = true }
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd"))'.dependencies]
machine-uid = "0.5.3"
machine-uid = "0.6.0"
[target.'cfg(any(target_os = "linux"))'.dependencies]
netlink-sys = { version = "0.8.7", optional = true }
netlink-sys = { version = "0.9.0", optional = true }
[target.'cfg(all(windows, any(target_arch = "x86_64", target_arch = "x86")))'.dependencies]
windivert = { git = "https://github.com/EasyTier/windivert-rust.git", rev = "adcc56d1550f7b5377ec2b3429f413ee24a77375", features = [
"static",
@@ -257,52 +256,50 @@ windows = { version = "0.62.2", features = [
"Win32_System_IO",
] }
encoding = "0.2"
winreg = "0.52"
windows-service = "0.7.0"
winapi = { version = "0.3.9", features = ["impl-default"] }
winreg = "0.56"
windows-service = "0.8.1"
winapi = { workspace = true, features = ["impl-default"] }
[target.'cfg(not(windows))'.dependencies]
jemallocator = { package = "tikv-jemallocator", version = "0.6.0", optional = true, features = [
jemallocator = { package = "tikv-jemallocator", version = "0.7.0", optional = true, features = [
"unprefixed_malloc_on_supported_platforms",
] }
jemalloc-ctl = { package = "tikv-jemalloc-ctl", version = "0.6.0", optional = true, features = [
jemalloc-ctl = { package = "tikv-jemalloc-ctl", version = "0.7.0", optional = true, features = [
"use_std",
] }
[target.'cfg(not(target_os = "macos"))'.dependencies]
jemalloc-sys = { package = "tikv-jemalloc-sys", version = "0.6.0", features = [
jemalloc-sys = { package = "tikv-jemalloc-sys", version = "0.7.1", features = [
"background_threads_runtime_support",
"background_threads",
], optional = true }
[target.'cfg(target_os = "macos")'.dependencies]
jemalloc-sys = { package = "tikv-jemalloc-sys", version = "0.6.0", features = [
jemalloc-sys = { package = "tikv-jemalloc-sys", version = "0.7.1", features = [
], optional = true }
[build-dependencies]
cfg_aliases = "0.2.1"
globwalk = "0.8.1"
cfg_aliases = "0.2.2"
globwalk = "0.9.1"
regex = "1"
thunk-rs = { git = "https://github.com/easytier/thunk.git", default-features = false, features = [
thunk-rs = { workspace = true, features = [
"win7",
] }
[dev-dependencies]
criterion = "0.5.1"
easytier-core = { path = "../easytier-core", version = "2.7.0", default-features = false, features = [
criterion = "0.8.2"
easytier-core = { workspace = true, features = [
"test-utils",
] }
serial_test = "3.0.0"
rstest = "0.25.0"
futures-util = "0.3.31"
serial_test = "4.0.1"
rstest = "0.27.0"
maplit = "1.0.2"
tempfile = "3.22.0"
ctor = "0.8.0"
stun_codec = "0.3.4"
bytecodec = "0.4.15"
x25519-dalek = { version = "2.0", features = ["static_secrets"] }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp.git", rev = "0a926767a68bc88d5512afefa7529c5ecdade4ea", default-features = false, features = [
tempfile.workspace = true
stun_codec.workspace = true
bytecodec.workspace = true
x25519-dalek = { workspace = true, features = ["static_secrets"] }
smoltcp = { workspace = true, features = [
"std",
"medium-ethernet",
"proto-ipv4",
@@ -311,12 +308,13 @@ smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp.git", rev = "0a926767a6
] }
[target.'cfg(target_os = "linux")'.dev-dependencies]
defguard_wireguard_rs = "0.4.2"
tokio-socks = "0.5.2"
defguard_wireguard_rs = "0.12.0"
tokio-socks = "0.5.3"
[features]
default = [
"cli",
"wireguard",
"websocket",
"smoltcp",
@@ -336,6 +334,7 @@ default = [
"tcp-hole-punch",
]
full = [
"cli",
"websocket",
"wireguard",
"aes-gcm",
@@ -355,6 +354,7 @@ full = [
"extended-services",
"tcp-hole-punch",
]
cli = ["management", "dep:tabled", "dep:humansize", "dep:terminal_size", "dep:unicode-width"]
wireguard = ["vpn-portal", "dep:boringtun", "dep:hkdf", "dep:sha2", "ring-crypto", "easytier-proto/wireguard"]
quic = ["wrapped-transport", "easytier-core/proxy-packet", "dep:quinn", "dep:quinn-proto", "dep:seahash", "dep:rustls", "easytier-proto/quic"]
kcp = ["wrapped-transport", "easytier-core/proxy-packet", "dep:kcp-sys"]
@@ -378,7 +378,7 @@ smoltcp = ["easytier-core/proxy-smoltcp-stack"]
icmp-proxy = ["easytier-core/proxy-packet"]
socks5 = ["smoltcp"]
ffi-dataplane = ["socks5"]
jemalloc = ["dep:jemallocator", "dep:jemalloc-sys"]
jemalloc = ["dep:jemallocator"]
jemalloc-prof = [
"jemalloc",
"dep:jemalloc-ctl",
@@ -391,6 +391,8 @@ tracing-log = ["tracing/log", "easytier-core/tracing-log"]
logging = []
dns-resolver = ["dep:hickory-proto", "dep:hickory-resolver"]
magic-dns = [
"dep:derive_builder",
"dep:humantime-serde",
"dns-resolver",
"dep:hickory-client",
"dep:hickory-server",
@@ -446,3 +448,15 @@ hotpath-cpu = ["hotpath"]
hotpath-alloc = ["hotpath"]
# For Network Extension on macOS
macos-ne = []
[package.metadata.cargo-machete]
ignored = [
# Used by build/main.rs, including the Windows-only thunk setup.
"cfg_aliases",
"globwalk",
"regex",
"thunk-rs",
# Referenced by serde attributes or enabled for allocator feature unification.
"humantime-serde",
"jemalloc-sys",
]
+5 -3
View File
@@ -1,3 +1,5 @@
#![cfg(feature = "cli")]
use std::{
collections::{BTreeMap, HashMap},
ffi::OsString,
@@ -22,7 +24,7 @@ use easytier_core::connectivity::stun::StunInfoProvider as _;
use humansize::format_size;
use rust_i18n::t;
use service_manager::*;
use tabled::settings::{Disable, Modify, Style, Width, location::ByColumnName, object::Columns};
use tabled::settings::{Modify, Remove, Style, Width, location::ByColumnName, object::Columns};
use terminal_size::{Width as TerminalWidth, terminal_size};
use unicode_width::UnicodeWidthStr;
@@ -1845,7 +1847,7 @@ impl<'a> CommandHandler<'a> {
struct RouteTableItem {
ipv4: String,
hostname: String,
#[tabled(display_with = "format_proxy_cidrs")]
#[tabled(display("format_proxy_cidrs"))]
proxy_cidrs: String,
next_hop_ipv4: String,
@@ -3127,7 +3129,7 @@ fn apply_column_drops(table: &mut tabled::Table, drop_indices: &[usize]) {
let mut indices = drop_indices.to_vec();
indices.sort_unstable_by(|a, b| b.cmp(a));
for index in indices {
table.with(Disable::column(Columns::single(index)));
table.with(Remove::column(Columns::one(index)));
}
}
+1 -1
View File
@@ -124,7 +124,7 @@ impl Service {
let status = self.status()?;
if status == service_manager::ServiceStatus::NotInstalled {
return Err(anyhow::anyhow!("Service is not installed"))?;
return Err(anyhow::anyhow!("Service is not installed"));
}
if status == service_manager::ServiceStatus::Running {
@@ -221,11 +221,7 @@ fn build_tcp_filter(
b.set_label(l_v4_proto_ok);
let l_v4_fragment_ok = b.new_label();
b.push(stmt(BPF_LD | BPF_H | BPF_ABS, 6));
b.push_jset(
IPV4_FRAGMENT_OFFSET_MASK,
l_reject,
l_v4_fragment_ok,
);
b.push_jset(IPV4_FRAGMENT_OFFSET_MASK, l_reject, l_v4_fragment_ok);
b.set_label(l_v4_fragment_ok);
let dst_ip = match dst_addr.ip() {
@@ -271,9 +267,9 @@ fn build_tcp_filter(
IpAddr::V6(ip) => ip.octets(),
_ => unreachable!(),
};
for (i, chunk) in dst_ip.chunks_exact(4).enumerate() {
for (i, chunk) in dst_ip.as_chunks::<4>().0.iter().enumerate() {
let off = 24 + (i * 4);
let v = u32::from_be_bytes(chunk.try_into().unwrap());
let v = u32::from_be_bytes(*chunk);
let l_v6_dstip_word_ok = b.new_label();
b.push(stmt(BPF_LD | BPF_W | BPF_ABS, off as u32));
b.push_jeq(v, l_v6_dstip_word_ok, l_reject);
@@ -285,9 +281,9 @@ fn build_tcp_filter(
IpAddr::V6(ip) => ip.octets(),
_ => unreachable!(),
};
for (i, chunk) in src_ip.chunks_exact(4).enumerate() {
for (i, chunk) in src_ip.as_chunks::<4>().0.iter().enumerate() {
let off = 8 + (i * 4);
let v = u32::from_be_bytes(chunk.try_into().unwrap());
let v = u32::from_be_bytes(*chunk);
let l_v6_srcip_word_ok = b.new_label();
b.push(stmt(BPF_LD | BPF_W | BPF_ABS, off as u32));
b.push_jeq(v, l_v6_srcip_word_ok, l_reject);
@@ -747,7 +743,7 @@ mod tests {
packet[10..12].fill(0);
let mut sum = 0u32;
for word in packet[..header_len].chunks_exact(2) {
for word in packet[..header_len].as_chunks::<2>().0 {
sum += u32::from(u16::from_be_bytes([word[0], word[1]]));
}
while sum > u16::MAX as u32 {
+1 -1
View File
@@ -350,7 +350,7 @@ pub(crate) fn prepare_proxy_tcp_socket(stream: &TcpStream) -> io::Result<()> {
let socket = SockRef::from(stream);
socket.set_tcp_keepalive(&keepalive)?;
if let Err(error) = socket.set_nodelay(true) {
if let Err(error) = socket.set_tcp_nodelay(true) {
tracing::warn!(?error, "set_nodelay failed, ignore it");
}
+15 -4
View File
@@ -1781,7 +1781,8 @@ pub async fn foreign_network_forward_nic_data() {
use std::{net::SocketAddr, str::FromStr};
use defguard_wireguard_rs::{
InterfaceConfiguration, WGApi, WireguardInterfaceApi, host::Peer, key::Key, net::IpAddrMask,
InterfaceConfiguration, Kernel, WGApi, WireguardInterfaceApi, key::Key, net::IpAddrMask,
peer::Peer,
};
pub(super) fn wireguard_ifname(base: &str) -> String {
@@ -1802,7 +1803,7 @@ pub(super) fn run_wireguard_client(
client_ip: String,
) -> Result<(), Box<dyn std::error::Error>> {
// Create new API object for interface
let wgapi = WGApi::new(ifname.to_owned(), false)?;
let mut wgapi = WGApi::<Kernel>::new(ifname.to_owned())?;
// create interface
wgapi.create_interface()?;
@@ -1822,16 +1823,26 @@ pub(super) fn run_wireguard_client(
let interface_config = InterfaceConfiguration {
name: ifname.to_owned(),
prvkey: client_private_key.to_string(),
address: client_ip,
addresses: vec![IpAddrMask::from_str(client_ip.as_str())?],
port: 12345,
peers: vec![peer],
mtu: None,
fwmark: None,
};
#[cfg(not(windows))]
wgapi.configure_interface(&interface_config)?;
#[cfg(windows)]
wgapi.configure_interface(&interface_config, &[])?;
wgapi.configure_peer_routing(&interface_config.peers)?;
// These split-tunnel clients reach the endpoint through an existing route.
// defguard 0.12 also rewrites endpoint routes (or blackholes them without a
// default gateway), so pass only the allowed IPs to its routing helper.
// The actual WireGuard peer above retains its endpoint.
let mut routing_peers = interface_config.peers.clone();
for peer in &mut routing_peers {
peer.endpoint = None;
}
wgapi.configure_peer_routing(&routing_peers)?;
Ok(())
}
+3 -3
View File
@@ -204,10 +204,10 @@ fn get_insecure_tls_cert<'a>() -> (
rustls::pki_types::PrivateKeyDer<'a>,
) {
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap();
let cert_der = cert.serialize_der().unwrap();
let private_key = cert.serialize_private_key_der();
let cert_der = cert.cert.der().clone();
let private_key = cert.signing_key.serialize_der();
let private_key = rustls::pki_types::PrivatePkcs8KeyDer::from(private_key);
(vec![cert_der.into()], private_key.into())
(vec![cert_der], private_key.into())
}
pub(crate) async fn upgrade_accepted<S>(
Generated
+3 -3
View File
@@ -48,11 +48,11 @@
]
},
"locked": {
"lastModified": 1776395632,
"narHash": "sha256-Mi1uF5f2FsdBIvy+v7MtsqxD3Xjhd0ARJdwoqqqPtJo=",
"lastModified": 1789457514,
"narHash": "sha256-Aggle++fTyAifBy+QBPxjM+obO5iepKW/8MDxQtgGvI=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "8087ff1f47fff983a1fba70fa88b759f2fd8ae97",
"rev": "89e99bf0778a8f2cd18c9360c3f19c1ee47fc739",
"type": "github"
},
"original": {
+10 -4
View File
@@ -8,9 +8,15 @@ exclude = ["/examples", "/webview-dist", "/webview-src", "/node_modules"]
links = "tauri-plugin-vpnservice"
[dependencies]
tauri = { version = "2.0.0-rc" }
serde = "1.0"
thiserror = "1.0"
tauri.workspace = true
serde.workspace = true
thiserror.workspace = true
[build-dependencies]
tauri-plugin = { version = "2.0.0-rc", features = ["build"] }
tauri-plugin = { version = "2.6.3", features = ["build"] }
[package.metadata.cargo-machete]
ignored = [
# Called by build.rs to generate plugin permissions and bindings.
"tauri-plugin",
]