diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml
index 3c7eaec..a10c5bb 100644
--- a/.github/workflows/core.yml
+++ b/.github/workflows/core.yml
@@ -175,14 +175,14 @@ jobs:
fi
if [[ $OS =~ ^ubuntu.*$ && $TARGET =~ ^mips.*$ ]]; then
- cargo +nightly build -r --verbose --target $TARGET -Z build-std=std,panic_abort --no-default-features --features mips --package=easytier
+ cargo +nightly build -r --target $TARGET -Z build-std=std,panic_abort --package=easytier
else
if [[ $OS =~ ^windows.*$ ]]; then
SUFFIX=.exe
fi
- cargo build --release --verbose --target $TARGET --package=easytier-web --features=embed
+ cargo build --release --target $TARGET --package=easytier-web --features=embed
mv ./target/$TARGET/release/easytier-web"$SUFFIX" ./target/$TARGET/release/easytier-web-embed"$SUFFIX"
- cargo build --release --verbose --target $TARGET
+ cargo build --release --target $TARGET
fi
# Copied and slightly modified from @lmq8267 (https://github.com/lmq8267)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 9faa67b..e935731 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -91,6 +91,7 @@ jobs:
- name: Run tests
run: |
- sudo -E env "PATH=$PATH" cargo test --no-default-features --features=full --verbose -- --test-threads=1 --nocapture
+ sudo prlimit --pid $$ --nofile=1048576:1048576
+ sudo -E env "PATH=$PATH" cargo test --no-default-features --features=full --verbose -- --test-threads=1
sudo chown -R $USER:$USER ./target
sudo chown -R $USER:$USER ~/.cargo
diff --git a/Cargo.lock b/Cargo.lock
index fe3eecb..e3ceba8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2383,6 +2383,18 @@ dependencies = [
"pin-project-lite",
]
+[[package]]
+name = "fastbloom"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27cea6e7f512d43b098939ff4d5a5d6fe3db07971e1d05176fe26c642d33f5b8"
+dependencies = [
+ "getrandom 0.3.2",
+ "rand 0.9.1",
+ "siphasher 1.0.1",
+ "wide",
+]
+
[[package]]
name = "fastrand"
version = "2.1.0"
@@ -3923,20 +3935,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "jni"
-version = "0.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec"
-dependencies = [
- "cesu8",
- "combine",
- "jni-sys",
- "log",
- "thiserror 1.0.63",
- "walkdir",
-]
-
[[package]]
name = "jni"
version = "0.21.1"
@@ -4118,7 +4116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -4254,6 +4252,12 @@ dependencies = [
"tracing-subscriber",
]
+[[package]]
+name = "lru-slab"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
+
[[package]]
name = "mac"
version = "0.1.1"
@@ -4504,7 +4508,7 @@ dependencies = [
"openssl-probe",
"openssl-sys",
"schannel",
- "security-framework",
+ "security-framework 2.11.1",
"security-framework-sys",
"tempfile",
]
@@ -6043,38 +6047,45 @@ dependencies = [
[[package]]
name = "quinn"
-version = "0.11.3"
+version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156"
+checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8"
dependencies = [
"bytes",
+ "cfg_aliases",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
"rustc-hash",
"rustls",
"socket2",
- "thiserror 1.0.63",
+ "thiserror 2.0.11",
"tokio",
"tracing",
+ "web-time",
]
[[package]]
name = "quinn-proto"
-version = "0.11.6"
+version = "0.11.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd"
+checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e"
dependencies = [
"bytes",
- "rand 0.8.5",
+ "fastbloom",
+ "getrandom 0.3.2",
+ "lru-slab",
+ "rand 0.9.1",
"ring",
"rustc-hash",
"rustls",
+ "rustls-pki-types",
"rustls-platform-verifier",
"slab",
- "thiserror 1.0.63",
+ "thiserror 2.0.11",
"tinyvec",
"tracing",
+ "web-time",
]
[[package]]
@@ -6694,9 +6705,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.12"
+version = "0.23.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
+checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321"
dependencies = [
"once_cell",
"ring",
@@ -6708,15 +6719,14 @@ dependencies = [
[[package]]
name = "rustls-native-certs"
-version = "0.7.1"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba"
+checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3"
dependencies = [
"openssl-probe",
- "rustls-pemfile",
"rustls-pki-types",
"schannel",
- "security-framework",
+ "security-framework 3.2.0",
]
[[package]]
@@ -6733,26 +6743,29 @@ name = "rustls-pki-types"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
+dependencies = [
+ "web-time",
+]
[[package]]
name = "rustls-platform-verifier"
-version = "0.3.3"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93bda3f493b9abe5b93b3e7e3ecde0df292f2bd28c0296b90586ee0055ff5123"
+checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1"
dependencies = [
- "core-foundation 0.9.4",
+ "core-foundation 0.10.0",
"core-foundation-sys",
- "jni 0.19.0",
+ "jni",
"log",
"once_cell",
"rustls",
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
- "security-framework",
+ "security-framework 3.2.0",
"security-framework-sys",
- "webpki-roots",
- "winapi",
+ "webpki-root-certs 0.26.11",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -6763,9 +6776,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]]
name = "rustls-webpki"
-version = "0.102.6"
+version = "0.103.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e"
+checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435"
dependencies = [
"ring",
"rustls-pki-types",
@@ -7050,15 +7063,27 @@ dependencies = [
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
- "num-bigint",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
+dependencies = [
+ "bitflags 2.8.0",
+ "core-foundation 0.10.0",
+ "core-foundation-sys",
+ "libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
-version = "2.11.1"
+version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf"
+checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
dependencies = [
"core-foundation-sys",
"libc",
@@ -7985,7 +8010,7 @@ dependencies = [
"gdkx11-sys",
"gtk",
"instant",
- "jni 0.21.1",
+ "jni",
"lazy_static",
"libc",
"log",
@@ -8047,7 +8072,7 @@ dependencies = [
"heck 0.5.0",
"http",
"image 0.25.2",
- "jni 0.21.1",
+ "jni",
"libc",
"log",
"mime",
@@ -8288,7 +8313,7 @@ dependencies = [
"dpi",
"gtk",
"http",
- "jni 0.21.1",
+ "jni",
"raw-window-handle",
"serde",
"serde_json",
@@ -8306,7 +8331,7 @@ checksum = "62fa2068e8498ad007b54d5773d03d57c3ff6dd96f8c8ce58beff44d0d5e0d30"
dependencies = [
"gtk",
"http",
- "jni 0.21.1",
+ "jni",
"log",
"objc2",
"objc2-app-kit",
@@ -9445,6 +9470,16 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "web-time"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
[[package]]
name = "webkit2gtk"
version = "2.0.1"
@@ -9499,6 +9534,24 @@ dependencies = [
"untrusted",
]
+[[package]]
+name = "webpki-root-certs"
+version = "0.26.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e"
+dependencies = [
+ "webpki-root-certs 1.0.0",
+]
+
+[[package]]
+name = "webpki-root-certs"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01a83f7e1a9f8712695c03eabe9ed3fbca0feff0152f33f12593e5a6303cb1a4"
+dependencies = [
+ "rustls-pki-types",
+]
+
[[package]]
name = "webpki-roots"
version = "0.26.3"
@@ -10099,7 +10152,7 @@ dependencies = [
"html5ever",
"http",
"javascriptcore-rs",
- "jni 0.21.1",
+ "jni",
"kuchikiki",
"libc",
"ndk",
diff --git a/easytier-web/frontend-lib/src/components/Config.vue b/easytier-web/frontend-lib/src/components/Config.vue
index e38fa3e..3805d3e 100644
--- a/easytier-web/frontend-lib/src/components/Config.vue
+++ b/easytier-web/frontend-lib/src/components/Config.vue
@@ -147,6 +147,8 @@ const bool_flags: BoolFlag[] = [
{ field: 'use_smoltcp', help: 'use_smoltcp_help' },
{ field: 'enable_kcp_proxy', help: 'enable_kcp_proxy_help' },
{ field: 'disable_kcp_input', help: 'disable_kcp_input_help' },
+ { field: 'enable_quic_proxy', help: 'enable_quic_proxy_help' },
+ { field: 'disable_quic_input', help: 'disable_quic_input_help' },
{ field: 'disable_p2p', help: 'disable_p2p_help' },
{ field: 'bind_device', help: 'bind_device_help' },
{ field: 'no_tun', help: 'no_tun_help' },
@@ -200,7 +202,7 @@ const bool_flags: BoolFlag[] = [
+ aria-describedby="network_secret-help" toggleMask :feedback="false" />
@@ -271,7 +273,7 @@ const bool_flags: BoolFlag[] = [
+ :placeholder="t('vpn_portal_client_network')" />
/{{ curNetwork.vpn_portal_client_network_len }}
@@ -279,7 +281,7 @@ const bool_flags: BoolFlag[] = [
+ :min="0" :max="65535" fluid />
@@ -325,11 +327,10 @@ const bool_flags: BoolFlag[] = [
@@ -338,15 +339,15 @@ const bool_flags: BoolFlag[] = [
+ v-tooltip="t('relay_network_whitelist_help')">
-
+
+ :placeholder="t('relay_network_whitelist')" class="w-full" multiple fluid
+ :suggestions="whitelistSuggestions" @complete="searchWhitelistSuggestions" />
@@ -359,12 +360,12 @@ const bool_flags: BoolFlag[] = [
+ :on-label="t('off_text')" :off-label="t('on_text')" class="w-48" />
+ :placeholder="t('chips_placeholder', ['192.168.0.0/16'])" class="w-full" multiple fluid
+ :suggestions="inetSuggestions" @complete="searchInetSuggestions" />
@@ -377,11 +378,11 @@ const bool_flags: BoolFlag[] = [
+ :on-label="t('off_text')" :off-label="t('on_text')" class="w-48" />
+ :format="false" :allow-empty="false" :min="0" :max="65535" class="w-full" />
@@ -394,8 +395,8 @@ const bool_flags: BoolFlag[] = [
+ :placeholder="t('chips_placeholder', ['192.168.8.8'])" class="w-full" multiple fluid
+ :suggestions="exitNodesSuggestions" @complete="searchExitNodesSuggestions" />
@@ -406,8 +407,8 @@ const bool_flags: BoolFlag[] = [
+ :placeholder="t('chips_placeholder', ['tcp://123.123.123.123:11223'])" class="w-full" multiple fluid
+ :suggestions="peerSuggestions" @complete="searchPeerSuggestions" />
diff --git a/easytier-web/frontend-lib/src/locales/cn.yaml b/easytier-web/frontend-lib/src/locales/cn.yaml
index 9c3d241..492bea1 100644
--- a/easytier-web/frontend-lib/src/locales/cn.yaml
+++ b/easytier-web/frontend-lib/src/locales/cn.yaml
@@ -85,6 +85,12 @@ enable_kcp_proxy_help: 将 TCP 流量转为 KCP 流量,降低传输延迟,
disable_kcp_input: 禁用 KCP 输入
disable_kcp_input_help: 禁用 KCP 入站流量,其他开启 KCP 代理的节点仍然使用 TCP 连接到本节点。
+enable_quic_proxy: 启用 QUIC 代理
+enable_quic_proxy_help: 将 TCP 流量转为 QUIC 流量,降低传输延迟,提升传输速度。
+
+disable_quic_input: 禁用 QUIC 输入
+disable_quic_input_help: 禁用 QUIC 入站流量,其他开启 QUIC 代理的节点仍然使用 TCP 连接到本节点。
+
disable_p2p: 禁用 P2P
disable_p2p_help: 禁用 P2P 模式,所有流量通过手动指定的服务器中转。
diff --git a/easytier-web/frontend-lib/src/locales/en.yaml b/easytier-web/frontend-lib/src/locales/en.yaml
index bf9629f..bfef6e5 100644
--- a/easytier-web/frontend-lib/src/locales/en.yaml
+++ b/easytier-web/frontend-lib/src/locales/en.yaml
@@ -84,6 +84,12 @@ enable_kcp_proxy_help: Convert TCP traffic to KCP traffic to reduce latency and
disable_kcp_input: Disable KCP Input
disable_kcp_input_help: Disable inbound KCP traffic, while nodes with KCP proxy enabled continue to connect using TCP.
+enable_quic_proxy: Enable QUIC Proxy
+enable_quic_proxy_help: Convert TCP traffic to QUIC traffic to reduce latency and boost transmission speed.
+
+disable_quic_input: Disable QUIC Input
+disable_quic_input_help: Disable inbound QUIC traffic, while nodes with QUIC proxy enabled continue to connect using TCP.
+
disable_p2p: Disable P2P
disable_p2p_help: Disable P2P mode; route all traffic through a manually specified relay server.
diff --git a/easytier-web/frontend-lib/src/types/network.ts b/easytier-web/frontend-lib/src/types/network.ts
index 421d61f..6487fc7 100644
--- a/easytier-web/frontend-lib/src/types/network.ts
+++ b/easytier-web/frontend-lib/src/types/network.ts
@@ -39,6 +39,8 @@ export interface NetworkConfig {
use_smoltcp?: boolean
enable_kcp_proxy?: boolean
disable_kcp_input?: boolean
+ enable_quic_proxy?: boolean
+ disable_quic_input?: boolean
disable_p2p?: boolean
bind_device?: boolean
no_tun?: boolean
@@ -105,6 +107,8 @@ export function DEFAULT_NETWORK_CONFIG(): NetworkConfig {
use_smoltcp: false,
enable_kcp_proxy: false,
disable_kcp_input: false,
+ enable_quic_proxy: false,
+ disable_quic_input: false,
disable_p2p: false,
bind_device: true,
no_tun: false,
diff --git a/easytier/Cargo.toml b/easytier/Cargo.toml
index dddb50b..69d60ea 100644
--- a/easytier/Cargo.toml
+++ b/easytier/Cargo.toml
@@ -64,7 +64,7 @@ bytes = "1.5.0"
pin-project-lite = "0.2.13"
tachyonix = "0.3.0"
-quinn = { version = "0.11.0", optional = true, features = ["ring"] }
+quinn = { version = "0.11.8", optional = true, features = ["ring"] }
rustls = { version = "0.23.0", features = [
"ring",
], default-features = false, optional = true }
@@ -280,9 +280,8 @@ tokio-socks = "0.5.2"
[features]
-default = ["wireguard", "mimalloc", "websocket", "smoltcp", "tun", "socks5"]
+default = ["wireguard", "mimalloc", "websocket", "smoltcp", "tun", "socks5", "quic"]
full = [
- "quic",
"websocket",
"wireguard",
"mimalloc",
@@ -291,7 +290,6 @@ full = [
"tun",
"socks5",
]
-mips = ["aes-gcm", "mimalloc", "wireguard", "tun", "smoltcp", "socks5"]
wireguard = ["dep:boringtun", "dep:ring"]
quic = ["dep:quinn", "dep:rustls", "dep:rcgen"]
mimalloc = ["dep:mimalloc"]
diff --git a/easytier/locales/app.yml b/easytier/locales/app.yml
index a3e985e..120ffc8 100644
--- a/easytier/locales/app.yml
+++ b/easytier/locales/app.yml
@@ -158,6 +158,12 @@ core_clap:
disable_kcp_input:
en: "do not allow other nodes to use kcp to proxy tcp streams to this node. when a node with kcp proxy enabled accesses this node, the original tcp connection is preserved."
zh-CN: "不允许其他节点使用 KCP 代理 TCP 流到此节点。开启 KCP 代理的节点访问此节点时,依然使用原始 TCP 连接。"
+ enable_quic_proxy:
+ en: "proxy tcp streams with QUIC, improving the latency and throughput on the network with udp packet loss."
+ zh-CN: "使用 QUIC 代理 TCP 流,提高在 UDP 丢包网络上的延迟和吞吐量。"
+ disable_quic_input:
+ en: "do not allow other nodes to use QUIC to proxy tcp streams to this node. when a node with QUIC proxy enabled accesses this node, the original tcp connection is preserved."
+ zh-CN: "不允许其他节点使用 QUIC 代理 TCP 流到此节点。开启 QUIC 代理的节点访问此节点时,依然使用原始 TCP 连接。"
port_forward:
en: "forward local port to remote port in virtual network. e.g.: udp://0.0.0.0:12345/10.126.126.1:23456, means forward local udp port 12345 to 10.126.126.1:23456 in the virtual network. can specify multiple."
zh-CN: "将本地端口转发到虚拟网络中的远程端口。例如:udp://0.0.0.0:12345/10.126.126.1:23456,表示将本地UDP端口12345转发到虚拟网络中的10.126.126.1:23456。可以指定多个。"
diff --git a/easytier/src/common/config.rs b/easytier/src/common/config.rs
index fee9f0e..2276687 100644
--- a/easytier/src/common/config.rs
+++ b/easytier/src/common/config.rs
@@ -39,6 +39,8 @@ pub fn gen_default_flags() -> Flags {
disable_relay_kcp: true,
accept_dns: false,
private_mode: false,
+ enable_quic_proxy: false,
+ disable_quic_input: false,
}
}
@@ -437,7 +439,7 @@ impl ConfigLoader for TomlConfigLoader {
.as_ref()
.unwrap()
.iter()
- .any(|c| c.cidr == cidr)
+ .any(|c| c.cidr == cidr && c.mapped_cidr == mapped_cidr)
{
locked_config
.proxy_network
diff --git a/easytier/src/common/global_ctx.rs b/easytier/src/common/global_ctx.rs
index 556d068..266688e 100644
--- a/easytier/src/common/global_ctx.rs
+++ b/easytier/src/common/global_ctx.rs
@@ -75,6 +75,8 @@ pub struct GlobalCtx {
no_tun: bool,
feature_flags: AtomicCell,
+
+ quic_proxy_port: AtomicCell