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