mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-15 10:25:40 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32b1fe0893 | |||
| 2af3b82e32 | |||
| eca1231831 | |||
| e833c2a28b | |||
| 8b89a037e8 |
@@ -11,7 +11,7 @@ on:
|
|||||||
image_tag:
|
image_tag:
|
||||||
description: 'Tag for this image build'
|
description: 'Tag for this image build'
|
||||||
type: string
|
type: string
|
||||||
default: 'v1.2.0'
|
default: 'v2.2.1'
|
||||||
required: true
|
required: true
|
||||||
mark_latest:
|
mark_latest:
|
||||||
description: 'Mark this image as latest'
|
description: 'Mark this image as latest'
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ on:
|
|||||||
version:
|
version:
|
||||||
description: 'Version for this release'
|
description: 'Version for this release'
|
||||||
type: string
|
type: string
|
||||||
default: 'v2.2.0'
|
default: 'v2.2.1'
|
||||||
required: true
|
required: true
|
||||||
make_latest:
|
make_latest:
|
||||||
description: 'Mark this release as latest'
|
description: 'Mark this release as latest'
|
||||||
|
|||||||
Generated
+14
-4
@@ -1874,7 +1874,7 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "easytier"
|
name = "easytier"
|
||||||
version = "2.2.0"
|
version = "2.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -1968,8 +1968,8 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid",
|
||||||
"wildmatch",
|
"wildmatch",
|
||||||
|
"windows 0.52.0",
|
||||||
"windows-service",
|
"windows-service",
|
||||||
"windows-sys 0.52.0",
|
|
||||||
"winreg 0.52.0",
|
"winreg 0.52.0",
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
"zip",
|
"zip",
|
||||||
@@ -1977,7 +1977,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "easytier-gui"
|
name = "easytier-gui"
|
||||||
version = "2.2.0"
|
version = "2.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -2022,7 +2022,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "easytier-web"
|
name = "easytier-web"
|
||||||
version = "0.1.0"
|
version = "2.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -9061,6 +9061,16 @@ dependencies = [
|
|||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.52.0",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.58.0"
|
version = "0.58.0"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "easytier-gui",
|
"name": "easytier-gui",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.2.0",
|
"version": "2.2.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4",
|
"packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "easytier-gui"
|
name = "easytier-gui"
|
||||||
version = "2.2.0"
|
version = "2.2.1"
|
||||||
description = "EasyTier GUI"
|
description = "EasyTier GUI"
|
||||||
authors = ["you"]
|
authors = ["you"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ fn get_os_hostname() -> Result<String, String> {
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn set_logging_level(level: String) -> Result<(), String> {
|
fn set_logging_level(level: String) -> Result<(), String> {
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
let sender = unsafe { LOGGER_LEVEL_SENDER.as_ref().unwrap() };
|
let sender = unsafe { LOGGER_LEVEL_SENDER.as_ref().unwrap() };
|
||||||
sender.send(level).map_err(|e| e.to_string())?;
|
sender.send(level).map_err(|e| e.to_string())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -188,7 +189,10 @@ pub fn run() {
|
|||||||
let Ok(Some(logger_reinit)) = utils::init_logger(config, true) else {
|
let Ok(Some(logger_reinit)) = utils::init_logger(config, true) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
unsafe { LOGGER_LEVEL_SENDER.replace(logger_reinit) };
|
#[allow(static_mut_refs)]
|
||||||
|
unsafe {
|
||||||
|
LOGGER_LEVEL_SENDER.replace(logger_reinit)
|
||||||
|
};
|
||||||
|
|
||||||
// for tray icon, menu need to be built in js
|
// for tray icon, menu need to be built in js
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"createUpdaterArtifacts": false
|
"createUpdaterArtifacts": false
|
||||||
},
|
},
|
||||||
"productName": "easytier-gui",
|
"productName": "easytier-gui",
|
||||||
"version": "2.2.0",
|
"version": "2.2.1",
|
||||||
"identifier": "com.kkrainbow.easytier",
|
"identifier": "com.kkrainbow.easytier",
|
||||||
"plugins": {},
|
"plugins": {},
|
||||||
"app": {
|
"app": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "easytier-web"
|
name = "easytier-web"
|
||||||
version = "0.1.0"
|
version = "2.2.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
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."
|
||||||
|
|
||||||
|
|||||||
+8
-5
@@ -3,7 +3,7 @@ name = "easytier"
|
|||||||
description = "A full meshed p2p VPN, connecting all your devices in one network with one command."
|
description = "A full meshed p2p VPN, connecting all your devices in one network with one command."
|
||||||
homepage = "https://github.com/EasyTier/EasyTier"
|
homepage = "https://github.com/EasyTier/EasyTier"
|
||||||
repository = "https://github.com/EasyTier/EasyTier"
|
repository = "https://github.com/EasyTier/EasyTier"
|
||||||
version = "2.2.0"
|
version = "2.2.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["kkrainbow"]
|
authors = ["kkrainbow"]
|
||||||
keywords = ["vpn", "p2p", "network", "easytier"]
|
keywords = ["vpn", "p2p", "network", "easytier"]
|
||||||
@@ -204,12 +204,15 @@ netlink-packet-core = { version = "0.7.0" }
|
|||||||
netlink-packet-utils = "0.5.2"
|
netlink-packet-utils = "0.5.2"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows-sys = { version = "0.52", features = [
|
windows = { version = "0.52.0", features = [
|
||||||
"Win32_Networking_WinSock",
|
|
||||||
"Win32_NetworkManagement_IpHelper",
|
|
||||||
"Win32_Foundation",
|
"Win32_Foundation",
|
||||||
|
"Win32_NetworkManagement_WindowsFirewall",
|
||||||
|
"Win32_System_Com",
|
||||||
|
"Win32_Networking",
|
||||||
|
"Win32_System_Ole",
|
||||||
|
"Win32_Networking_WinSock",
|
||||||
"Win32_System_IO",
|
"Win32_System_IO",
|
||||||
] }
|
]}
|
||||||
encoding = "0.2"
|
encoding = "0.2"
|
||||||
winreg = "0.52"
|
winreg = "0.52"
|
||||||
windows-service = "0.7.0"
|
windows-service = "0.7.0"
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ core_clap:
|
|||||||
enable_kcp_proxy:
|
enable_kcp_proxy:
|
||||||
en: "proxy tcp streams with kcp, improving the latency and throughput on the network with udp packet loss."
|
en: "proxy tcp streams with kcp, improving the latency and throughput on the network with udp packet loss."
|
||||||
zh-CN: "使用 KCP 代理 TCP 流,提高在 UDP 丢包网络上的延迟和吞吐量。"
|
zh-CN: "使用 KCP 代理 TCP 流,提高在 UDP 丢包网络上的延迟和吞吐量。"
|
||||||
disable-kcp-input:
|
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."
|
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 连接。"
|
zh-CN: "不允许其他节点使用 KCP 代理 TCP 流到此节点。开启 KCP 代理的节点访问此节点时,依然使用原始 TCP 连接。"
|
||||||
|
|
||||||
|
|||||||
+119
-37
@@ -1,26 +1,27 @@
|
|||||||
use std::{
|
use std::{io, net::SocketAddr, os::windows::io::AsRawSocket};
|
||||||
ffi::c_void,
|
|
||||||
io::{self, ErrorKind},
|
|
||||||
mem,
|
|
||||||
net::SocketAddr,
|
|
||||||
os::windows::io::AsRawSocket,
|
|
||||||
ptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use network_interface::NetworkInterfaceConfig;
|
use network_interface::NetworkInterfaceConfig;
|
||||||
use windows_sys::{
|
use windows::{
|
||||||
core::PCSTR,
|
core::BSTR,
|
||||||
Win32::{
|
Win32::{
|
||||||
Foundation::{BOOL, FALSE},
|
Foundation::{BOOL, FALSE},
|
||||||
|
NetworkManagement::WindowsFirewall::{
|
||||||
|
INetFwPolicy2, INetFwRule, NET_FW_ACTION_ALLOW, NET_FW_PROFILE2_PRIVATE,
|
||||||
|
NET_FW_PROFILE2_PUBLIC, NET_FW_RULE_DIR_IN, NET_FW_RULE_DIR_OUT,
|
||||||
|
},
|
||||||
Networking::WinSock::{
|
Networking::WinSock::{
|
||||||
htonl, setsockopt, WSAGetLastError, WSAIoctl, IPPROTO_IP, IPPROTO_IPV6,
|
htonl, setsockopt, WSAGetLastError, WSAIoctl, IPPROTO_IP, IPPROTO_IPV6,
|
||||||
IPV6_UNICAST_IF, IP_UNICAST_IF, SIO_UDP_CONNRESET, SOCKET, SOCKET_ERROR,
|
IPV6_UNICAST_IF, IP_UNICAST_IF, SIO_UDP_CONNRESET, SOCKET, SOCKET_ERROR,
|
||||||
},
|
},
|
||||||
|
System::Com::{
|
||||||
|
CoCreateInstance, CoInitializeEx, CoUninitialize, CLSCTX_ALL, COINIT_MULTITHREADED,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn disable_connection_reset<S: AsRawSocket>(socket: &S) -> io::Result<()> {
|
pub fn disable_connection_reset<S: AsRawSocket>(socket: &S) -> io::Result<()> {
|
||||||
let handle = socket.as_raw_socket() as SOCKET;
|
let handle = SOCKET(socket.as_raw_socket() as usize);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// Ignoring UdpSocket's WSAECONNRESET error
|
// Ignoring UdpSocket's WSAECONNRESET error
|
||||||
@@ -39,21 +40,18 @@ pub fn disable_connection_reset<S: AsRawSocket>(socket: &S) -> io::Result<()> {
|
|||||||
let ret = WSAIoctl(
|
let ret = WSAIoctl(
|
||||||
handle,
|
handle,
|
||||||
SIO_UDP_CONNRESET,
|
SIO_UDP_CONNRESET,
|
||||||
&enable as *const _ as *const c_void,
|
Some(&enable as *const _ as *const std::ffi::c_void),
|
||||||
mem::size_of_val(&enable) as u32,
|
std::mem::size_of_val(&enable) as u32,
|
||||||
ptr::null_mut(),
|
None,
|
||||||
0,
|
0,
|
||||||
&mut bytes_returned as *mut _,
|
&mut bytes_returned as *mut _,
|
||||||
ptr::null_mut(),
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ret == SOCKET_ERROR {
|
if ret == SOCKET_ERROR {
|
||||||
use std::io::Error;
|
|
||||||
|
|
||||||
// Error occurs
|
|
||||||
let err_code = WSAGetLastError();
|
let err_code = WSAGetLastError();
|
||||||
return Err(Error::from_raw_os_error(err_code));
|
return Err(std::io::Error::from_raw_os_error(err_code.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +61,7 @@ pub fn disable_connection_reset<S: AsRawSocket>(socket: &S) -> io::Result<()> {
|
|||||||
pub fn interface_count() -> io::Result<usize> {
|
pub fn interface_count() -> io::Result<usize> {
|
||||||
let ifaces = network_interface::NetworkInterface::show().map_err(|e| {
|
let ifaces = network_interface::NetworkInterface::show().map_err(|e| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
ErrorKind::NotFound,
|
io::ErrorKind::NotFound,
|
||||||
format!("Failed to get interfaces. error: {}", e),
|
format!("Failed to get interfaces. error: {}", e),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@@ -73,7 +71,7 @@ pub fn interface_count() -> io::Result<usize> {
|
|||||||
pub fn find_interface_index(iface_name: &str) -> io::Result<u32> {
|
pub fn find_interface_index(iface_name: &str) -> io::Result<u32> {
|
||||||
let ifaces = network_interface::NetworkInterface::show().map_err(|e| {
|
let ifaces = network_interface::NetworkInterface::show().map_err(|e| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
ErrorKind::NotFound,
|
io::ErrorKind::NotFound,
|
||||||
format!("Failed to get interfaces. {}, error: {}", iface_name, e),
|
format!("Failed to get interfaces. {}, error: {}", iface_name, e),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@@ -82,7 +80,7 @@ pub fn find_interface_index(iface_name: &str) -> io::Result<u32> {
|
|||||||
}
|
}
|
||||||
tracing::error!("Failed to find interface index for {}", iface_name);
|
tracing::error!("Failed to find interface index for {}", iface_name);
|
||||||
Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
ErrorKind::NotFound,
|
io::ErrorKind::NotFound,
|
||||||
format!("{}", iface_name),
|
format!("{}", iface_name),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -92,7 +90,7 @@ pub fn set_ip_unicast_if<S: AsRawSocket>(
|
|||||||
addr: &SocketAddr,
|
addr: &SocketAddr,
|
||||||
iface: &str,
|
iface: &str,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let handle = socket.as_raw_socket() as SOCKET;
|
let handle = SOCKET(socket.as_raw_socket() as usize);
|
||||||
|
|
||||||
let if_index = find_interface_index(iface)?;
|
let if_index = find_interface_index(iface)?;
|
||||||
|
|
||||||
@@ -100,30 +98,23 @@ pub fn set_ip_unicast_if<S: AsRawSocket>(
|
|||||||
// https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
|
// https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
|
||||||
let ret = match addr {
|
let ret = match addr {
|
||||||
SocketAddr::V4(..) => {
|
SocketAddr::V4(..) => {
|
||||||
// Interface index is in network byte order for IPPROTO_IP.
|
|
||||||
let if_index = htonl(if_index);
|
let if_index = htonl(if_index);
|
||||||
setsockopt(
|
let if_index_bytes = if_index.to_ne_bytes();
|
||||||
handle,
|
setsockopt(handle, IPPROTO_IP.0, IP_UNICAST_IF, Some(&if_index_bytes))
|
||||||
IPPROTO_IP as i32,
|
|
||||||
IP_UNICAST_IF as i32,
|
|
||||||
&if_index as *const _ as PCSTR,
|
|
||||||
mem::size_of_val(&if_index) as i32,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
SocketAddr::V6(..) => {
|
SocketAddr::V6(..) => {
|
||||||
// Interface index is in host byte order for IPPROTO_IPV6.
|
let if_index_bytes = if_index.to_ne_bytes();
|
||||||
setsockopt(
|
setsockopt(
|
||||||
handle,
|
handle,
|
||||||
IPPROTO_IPV6 as i32,
|
IPPROTO_IPV6.0,
|
||||||
IPV6_UNICAST_IF as i32,
|
IPV6_UNICAST_IF,
|
||||||
&if_index as *const _ as PCSTR,
|
Some(&if_index_bytes),
|
||||||
mem::size_of_val(&if_index) as i32,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if ret == SOCKET_ERROR {
|
if ret == SOCKET_ERROR {
|
||||||
let err = io::Error::from_raw_os_error(WSAGetLastError());
|
let err = std::io::Error::from_raw_os_error(WSAGetLastError().0);
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
"set IP_UNICAST_IF / IPV6_UNICAST_IF interface: {}, index: {}, error: {}",
|
"set IP_UNICAST_IF / IPV6_UNICAST_IF interface: {}, index: {}, error: {}",
|
||||||
iface,
|
iface,
|
||||||
@@ -153,3 +144,94 @@ pub fn setup_socket_for_win<S: AsRawSocket>(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ComInitializer;
|
||||||
|
|
||||||
|
impl ComInitializer {
|
||||||
|
fn new() -> windows::core::Result<Self> {
|
||||||
|
unsafe { CoInitializeEx(None, COINIT_MULTITHREADED)? };
|
||||||
|
Ok(Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ComInitializer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_add_self_to_firewall_allowlist(inbound: bool) -> anyhow::Result<()> {
|
||||||
|
let _com = ComInitializer::new()?;
|
||||||
|
// 创建防火墙策略实例
|
||||||
|
let policy: INetFwPolicy2 = unsafe {
|
||||||
|
CoCreateInstance(
|
||||||
|
&windows::Win32::NetworkManagement::WindowsFirewall::NetFwPolicy2,
|
||||||
|
None,
|
||||||
|
CLSCTX_ALL,
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
|
||||||
|
// 创建防火墙规则实例
|
||||||
|
let rule: INetFwRule = unsafe {
|
||||||
|
CoCreateInstance(
|
||||||
|
&windows::Win32::NetworkManagement::WindowsFirewall::NetFwRule,
|
||||||
|
None,
|
||||||
|
CLSCTX_ALL,
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
|
||||||
|
// 设置规则属性
|
||||||
|
let exe_path = std::env::current_exe()
|
||||||
|
.with_context(|| "Failed to get current executable path when adding firewall rule")?
|
||||||
|
.to_string_lossy()
|
||||||
|
.replace(r"\\?\", "");
|
||||||
|
|
||||||
|
let name = BSTR::from(format!(
|
||||||
|
"EasyTier {} ({})",
|
||||||
|
exe_path,
|
||||||
|
if inbound { "Inbound" } else { "Outbound" }
|
||||||
|
));
|
||||||
|
let desc = BSTR::from("Allow EasyTier to do subnet proxy and kcp proxy");
|
||||||
|
let app_path = BSTR::from(&exe_path);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
rule.SetName(&name)?;
|
||||||
|
rule.SetDescription(&desc)?;
|
||||||
|
rule.SetApplicationName(&app_path)?;
|
||||||
|
rule.SetAction(NET_FW_ACTION_ALLOW)?;
|
||||||
|
if inbound {
|
||||||
|
rule.SetDirection(NET_FW_RULE_DIR_IN)?; // 允许入站连接
|
||||||
|
} else {
|
||||||
|
rule.SetDirection(NET_FW_RULE_DIR_OUT)?; // 允许出站连接
|
||||||
|
}
|
||||||
|
rule.SetEnabled(windows::Win32::Foundation::VARIANT_TRUE)?;
|
||||||
|
rule.SetProfiles(NET_FW_PROFILE2_PRIVATE.0 | NET_FW_PROFILE2_PUBLIC.0)?;
|
||||||
|
rule.SetGrouping(&BSTR::from("EasyTier"))?;
|
||||||
|
|
||||||
|
// 获取规则集合并添加新规则
|
||||||
|
let rules = policy.Rules()?;
|
||||||
|
rules.Remove(&name)?; // 先删除同名规则
|
||||||
|
rules.Add(&rule)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_self_to_firewall_allowlist() -> anyhow::Result<()> {
|
||||||
|
do_add_self_to_firewall_allowlist(true)?;
|
||||||
|
do_add_self_to_firewall_allowlist(false)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_self_to_firewall_allowlist() {
|
||||||
|
let res = add_self_to_firewall_allowlist();
|
||||||
|
assert!(res.is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -377,16 +377,18 @@ impl IfConfiguerTrait for NetlinkIfConfiger {
|
|||||||
|
|
||||||
async fn remove_ipv4_route(
|
async fn remove_ipv4_route(
|
||||||
&self,
|
&self,
|
||||||
_name: &str,
|
name: &str,
|
||||||
address: Ipv4Addr,
|
address: Ipv4Addr,
|
||||||
cidr_prefix: u8,
|
cidr_prefix: u8,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let routes = Self::list_routes()?;
|
let routes = Self::list_routes()?;
|
||||||
|
let ifidx = NetlinkIfConfiger::get_interface_index(name)?;
|
||||||
|
|
||||||
for msg in routes {
|
for msg in routes {
|
||||||
let other_route: Route = msg.clone().into();
|
let other_route: Route = msg.clone().into();
|
||||||
if other_route.destination == std::net::IpAddr::V4(address)
|
if other_route.destination == std::net::IpAddr::V4(address)
|
||||||
&& other_route.prefix == cidr_prefix
|
&& other_route.prefix == cidr_prefix
|
||||||
|
&& other_route.ifindex == Some(ifidx)
|
||||||
{
|
{
|
||||||
send_netlink_req_and_wait_one_resp(RouteNetlinkMessage::DelRoute(msg), true)?;
|
send_netlink_req_and_wait_one_resp(RouteNetlinkMessage::DelRoute(msg), true)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ struct Cli {
|
|||||||
|
|
||||||
#[arg(
|
#[arg(
|
||||||
long,
|
long,
|
||||||
help = t!("core_clap.enable_kcp_proxy").to_string(),
|
help = t!("core_clap.disable_kcp_input").to_string(),
|
||||||
default_value = "false"
|
default_value = "false"
|
||||||
)]
|
)]
|
||||||
disable_kcp_input: bool,
|
disable_kcp_input: bool,
|
||||||
|
|||||||
@@ -12,7 +12,12 @@ use kcp_sys::{
|
|||||||
packet_def::KcpPacket,
|
packet_def::KcpPacket,
|
||||||
stream::KcpStream,
|
stream::KcpStream,
|
||||||
};
|
};
|
||||||
use pnet::packet::{ip::IpNextHeaderProtocols, ipv4::Ipv4Packet};
|
use pnet::packet::{
|
||||||
|
ip::IpNextHeaderProtocols,
|
||||||
|
ipv4::Ipv4Packet,
|
||||||
|
tcp::{TcpFlags, TcpPacket},
|
||||||
|
Packet as _,
|
||||||
|
};
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use tokio::{io::copy_bidirectional, task::JoinSet};
|
use tokio::{io::copy_bidirectional, task::JoinSet};
|
||||||
|
|
||||||
@@ -138,7 +143,6 @@ impl NatDstConnector for NatDstKcpConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_packet_from_peer_fast(&self, _cidr_set: &CidrSet, _global_ctx: &GlobalCtx) -> bool {
|
fn check_packet_from_peer_fast(&self, _cidr_set: &CidrSet, _global_ctx: &GlobalCtx) -> bool {
|
||||||
// if kcp is turned off, the filter will not be added to the pipeline
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,10 +150,11 @@ impl NatDstConnector for NatDstKcpConnector {
|
|||||||
&self,
|
&self,
|
||||||
_cidr_set: &CidrSet,
|
_cidr_set: &CidrSet,
|
||||||
_global_ctx: &GlobalCtx,
|
_global_ctx: &GlobalCtx,
|
||||||
_hdr: &PeerManagerHeader,
|
hdr: &PeerManagerHeader,
|
||||||
_ipv4: &Ipv4Packet,
|
_ipv4: &Ipv4Packet,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
true
|
// TODO: how to support net to net kcp proxy?
|
||||||
|
return hdr.from_peer_id == hdr.to_peer_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +206,19 @@ impl NicPacketFilter for TcpProxyForKcpSrc {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if no connection is established, only allow SYN packet
|
||||||
|
let tcp_packet = TcpPacket::new(ip_packet.payload()).unwrap();
|
||||||
|
let is_syn = tcp_packet.get_flags() & TcpFlags::SYN != 0
|
||||||
|
&& tcp_packet.get_flags() & TcpFlags::ACK == 0;
|
||||||
|
if !is_syn
|
||||||
|
&& !self.0.is_tcp_proxy_connection(SocketAddr::new(
|
||||||
|
IpAddr::V4(my_ipv4.address()),
|
||||||
|
tcp_packet.get_source(),
|
||||||
|
))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
zc_packet.mut_peer_manager_header().unwrap().to_peer_id = self.0.get_my_peer_id().into();
|
zc_packet.mut_peer_manager_header().unwrap().to_peer_id = self.0.get_my_peer_id().into();
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -452,7 +452,10 @@ impl<C: NatDstConnector> TcpProxy<C> {
|
|||||||
|
|
||||||
async fn get_proxy_listener(&self) -> Result<ProxyTcpListener> {
|
async fn get_proxy_listener(&self) -> Result<ProxyTcpListener> {
|
||||||
#[cfg(feature = "smoltcp")]
|
#[cfg(feature = "smoltcp")]
|
||||||
if self.global_ctx.get_flags().use_smoltcp || self.global_ctx.no_tun() {
|
if self.global_ctx.get_flags().use_smoltcp
|
||||||
|
|| self.global_ctx.no_tun()
|
||||||
|
|| cfg!(target_os = "android")
|
||||||
|
{
|
||||||
// use smoltcp network stack
|
// use smoltcp network stack
|
||||||
self.local_port
|
self.local_port
|
||||||
.store(8899, std::sync::atomic::Ordering::Relaxed);
|
.store(8899, std::sync::atomic::Ordering::Relaxed);
|
||||||
@@ -795,4 +798,8 @@ impl<C: NatDstConnector> TcpProxy<C> {
|
|||||||
pub fn get_peer_manager(&self) -> &Arc<PeerManager> {
|
pub fn get_peer_manager(&self) -> &Arc<PeerManager> {
|
||||||
&self.peer_manager
|
&self.peer_manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_tcp_proxy_connection(&self, src: SocketAddr) -> bool {
|
||||||
|
self.syn_map.contains_key(&src) || self.addr_conn_map.contains_key(&src)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -382,13 +382,6 @@ impl Instance {
|
|||||||
|
|
||||||
self.run_rpc_server().await?;
|
self.run_rpc_server().await?;
|
||||||
|
|
||||||
// run after tun device created, so listener can bind to tun device, which may be required by win 10
|
|
||||||
self.ip_proxy = Some(IpProxy::new(
|
|
||||||
self.get_global_ctx(),
|
|
||||||
self.get_peer_manager(),
|
|
||||||
)?);
|
|
||||||
self.run_ip_proxy().await?;
|
|
||||||
|
|
||||||
if self.global_ctx.get_flags().enable_kcp_proxy {
|
if self.global_ctx.get_flags().enable_kcp_proxy {
|
||||||
let src_proxy = KcpProxySrc::new(self.get_peer_manager()).await;
|
let src_proxy = KcpProxySrc::new(self.get_peer_manager()).await;
|
||||||
src_proxy.start().await;
|
src_proxy.start().await;
|
||||||
@@ -401,6 +394,13 @@ impl Instance {
|
|||||||
self.kcp_proxy_dst = Some(dst_proxy);
|
self.kcp_proxy_dst = Some(dst_proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// run after tun device created, so listener can bind to tun device, which may be required by win 10
|
||||||
|
self.ip_proxy = Some(IpProxy::new(
|
||||||
|
self.get_global_ctx(),
|
||||||
|
self.get_peer_manager(),
|
||||||
|
)?);
|
||||||
|
self.run_ip_proxy().await?;
|
||||||
|
|
||||||
self.udp_hole_puncher.lock().await.run().await?;
|
self.udp_hole_puncher.lock().await.run().await?;
|
||||||
|
|
||||||
self.peer_center.init().await;
|
self.peer_center.init().await;
|
||||||
|
|||||||
@@ -349,6 +349,15 @@ impl VirtualNic {
|
|||||||
{
|
{
|
||||||
let dev_name = self.global_ctx.get_flags().dev_name;
|
let dev_name = self.global_ctx.get_flags().dev_name;
|
||||||
|
|
||||||
|
match crate::arch::windows::add_self_to_firewall_allowlist() {
|
||||||
|
Ok(_) => tracing::info!("add_self_to_firewall_allowlist successful!"),
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failed to add Easytier to firewall allowlist, Subnet proxy and KCP proxy may not work properly. error: {}", e);
|
||||||
|
println!("You can add firewall rules manually, or use --use-smoltcp to run with user-space TCP/IP stack.");
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match checkreg(&dev_name) {
|
match checkreg(&dev_name) {
|
||||||
Ok(_) => tracing::trace!("delete successful!"),
|
Ok(_) => tracing::trace!("delete successful!"),
|
||||||
Err(e) => tracing::error!("An error occurred: {}", e),
|
Err(e) => tracing::error!("An error occurred: {}", e),
|
||||||
|
|||||||
@@ -366,6 +366,7 @@ pub async fn subnet_proxy_three_node_test(
|
|||||||
#[values(true, false)] relay_by_public_server: bool,
|
#[values(true, false)] relay_by_public_server: bool,
|
||||||
#[values(true, false)] enable_kcp_proxy: bool,
|
#[values(true, false)] enable_kcp_proxy: bool,
|
||||||
#[values(true, false)] disable_kcp_input: bool,
|
#[values(true, false)] disable_kcp_input: bool,
|
||||||
|
#[values(true, false)] dst_enable_kcp_proxy: bool,
|
||||||
) {
|
) {
|
||||||
let insts = init_three_node_ex(
|
let insts = init_three_node_ex(
|
||||||
proto,
|
proto,
|
||||||
@@ -374,6 +375,7 @@ pub async fn subnet_proxy_three_node_test(
|
|||||||
let mut flags = cfg.get_flags();
|
let mut flags = cfg.get_flags();
|
||||||
flags.no_tun = no_tun;
|
flags.no_tun = no_tun;
|
||||||
flags.disable_kcp_input = disable_kcp_input;
|
flags.disable_kcp_input = disable_kcp_input;
|
||||||
|
flags.enable_kcp_proxy = dst_enable_kcp_proxy;
|
||||||
cfg.set_flags(flags);
|
cfg.set_flags(flags);
|
||||||
cfg.add_proxy_cidr("10.1.2.0/24".parse().unwrap());
|
cfg.add_proxy_cidr("10.1.2.0/24".parse().unwrap());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user