Compare commits

...

5 Commits

Author SHA1 Message Date
sijie.sun 32b1fe0893 netlink shoud remove route only when ifidx is same 2025-02-06 19:23:00 +08:00
sijie.sun 2af3b82e32 bump version to 2.2.1 2025-02-06 16:54:49 +08:00
sijie.sun eca1231831 fix help msg of kcp 2025-02-06 16:54:49 +08:00
sijie.sun e833c2a28b improve experience of subnet/kcp proxy
1. add self to windows firewall on windows
2. android always use smoltcp
2025-02-06 16:54:49 +08:00
Sijie.Sun 8b89a037e8 fix tcp incoming failure when kcp proxy is enabled (#601) 2025-02-06 09:08:34 +08:00
18 changed files with 206 additions and 69 deletions
+1 -1
View File
@@ -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'
+1 -1
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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"
+5 -1
View File
@@ -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"))]
+1 -1
View File
@@ -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 -1
View File
@@ -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."
+7 -4
View File
@@ -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,10 +204,13 @@ 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"
+1 -1
View File
@@ -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
View File
@@ -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());
}
}
+3 -1
View File
@@ -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(());
+1 -1
View File
@@ -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,
+22 -4
View File
@@ -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
+8 -1
View File
@@ -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)
}
} }
+7 -7
View File
@@ -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;
+9
View File
@@ -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),
+2
View File
@@ -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());
} }