mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-09-20 03:22:05 +00:00
Generated
+2887
-2934
File diff suppressed because it is too large
Load Diff
+70
@@ -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
|
||||
|
||||
@@ -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,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",
|
||||
] }
|
||||
|
||||
@@ -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
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"
|
||||
|
||||
@@ -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
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
@@ -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,4 +1,4 @@
|
||||
use hmac::{Hmac, Mac};
|
||||
use hmac::{Hmac, KeyInit, Mac};
|
||||
use prost::Message;
|
||||
use sha2::Sha256;
|
||||
#[cfg(feature = "api")]
|
||||
|
||||
+44
-37
@@ -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::*;
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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,3 +1,4 @@
|
||||
use openidconnect::reqwest;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user