mirror of
https://mirror.suhoan.cn/https://github.com/EasyTier/EasyTier.git
synced 2025-12-12 12:47:25 +08:00
fix ipv6 packet routing and avoid route looping
properly handle ipv6 link local address and exit node.
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -1979,7 +1979,7 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||
|
||||
[[package]]
|
||||
name = "easytier"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"anyhow",
|
||||
@@ -2112,7 +2112,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "easytier-gui"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@@ -2162,7 +2162,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "easytier-web"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
net::{Ipv4Addr, SocketAddr},
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
u64,
|
||||
@@ -107,8 +107,8 @@ pub trait ConfigLoader: Send + Sync {
|
||||
fn get_flags(&self) -> Flags;
|
||||
fn set_flags(&self, flags: Flags);
|
||||
|
||||
fn get_exit_nodes(&self) -> Vec<Ipv4Addr>;
|
||||
fn set_exit_nodes(&self, nodes: Vec<Ipv4Addr>);
|
||||
fn get_exit_nodes(&self) -> Vec<IpAddr>;
|
||||
fn set_exit_nodes(&self, nodes: Vec<IpAddr>);
|
||||
|
||||
fn get_routes(&self) -> Option<Vec<cidr::Ipv4Cidr>>;
|
||||
fn set_routes(&self, routes: Option<Vec<cidr::Ipv4Cidr>>);
|
||||
@@ -283,7 +283,7 @@ struct Config {
|
||||
network_identity: Option<NetworkIdentity>,
|
||||
listeners: Option<Vec<url::Url>>,
|
||||
mapped_listeners: Option<Vec<url::Url>>,
|
||||
exit_nodes: Option<Vec<Ipv4Addr>>,
|
||||
exit_nodes: Option<Vec<IpAddr>>,
|
||||
|
||||
peer: Option<Vec<PeerConfig>>,
|
||||
proxy_network: Option<Vec<ProxyNetworkConfig>>,
|
||||
@@ -624,7 +624,7 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
self.config.lock().unwrap().flags_struct = Some(flags);
|
||||
}
|
||||
|
||||
fn get_exit_nodes(&self) -> Vec<Ipv4Addr> {
|
||||
fn get_exit_nodes(&self) -> Vec<IpAddr> {
|
||||
self.config
|
||||
.lock()
|
||||
.unwrap()
|
||||
@@ -633,7 +633,7 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn set_exit_nodes(&self, nodes: Vec<Ipv4Addr>) {
|
||||
fn set_exit_nodes(&self, nodes: Vec<IpAddr>) {
|
||||
self.config.lock().unwrap().exit_nodes = Some(nodes);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
extern crate rust_i18n;
|
||||
|
||||
use std::{
|
||||
net::{Ipv4Addr, SocketAddr},
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::PathBuf,
|
||||
process::ExitCode,
|
||||
sync::Arc,
|
||||
@@ -333,7 +333,7 @@ struct NetworkOptions {
|
||||
help = t!("core_clap.exit_nodes").to_string(),
|
||||
num_args = 0..
|
||||
)]
|
||||
exit_nodes: Vec<Ipv4Addr>,
|
||||
exit_nodes: Vec<IpAddr>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
|
||||
@@ -711,12 +711,20 @@ impl NicCtx {
|
||||
tracing::info!("[USER_PACKET] not ipv6 packet: {:?}", ipv6);
|
||||
return;
|
||||
}
|
||||
let src_ipv6 = ipv6.get_source();
|
||||
let dst_ipv6 = ipv6.get_destination();
|
||||
tracing::trace!(
|
||||
?ret,
|
||||
"[USER_PACKET] recv new packet from tun device and forward to peers."
|
||||
);
|
||||
|
||||
if src_ipv6.is_unicast_link_local()
|
||||
&& Some(src_ipv6) != mgr.get_global_ctx().get_ipv6().map(|x| x.address())
|
||||
{
|
||||
// do not route link local packet to other nodes unless the address is assigned by user
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: use zero-copy
|
||||
let send_ret = mgr.send_msg_by_ip(ret, IpAddr::V6(dst_ipv6)).await;
|
||||
if send_ret.is_err() {
|
||||
|
||||
@@ -627,7 +627,7 @@ impl NetworkConfig {
|
||||
}
|
||||
|
||||
if self.exit_nodes.len() > 0 {
|
||||
let mut exit_nodes = Vec::<std::net::Ipv4Addr>::with_capacity(self.exit_nodes.len());
|
||||
let mut exit_nodes = Vec::<std::net::IpAddr>::with_capacity(self.exit_nodes.len());
|
||||
for node in self.exit_nodes.iter() {
|
||||
exit_nodes.push(
|
||||
node.parse()
|
||||
@@ -891,7 +891,7 @@ impl NetworkConfig {
|
||||
mod tests {
|
||||
use crate::common::config::ConfigLoader;
|
||||
use rand::Rng;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
|
||||
fn gen_default_config() -> crate::common::config::TomlConfigLoader {
|
||||
let config = crate::common::config::TomlConfigLoader::default();
|
||||
@@ -1073,7 +1073,19 @@ mod tests {
|
||||
rng.gen_range(0..255),
|
||||
rng.gen_range(1..254),
|
||||
);
|
||||
nodes.push(ip);
|
||||
nodes.push(IpAddr::V4(ip));
|
||||
// gen ipv6
|
||||
let ip = Ipv6Addr::new(
|
||||
rng.gen_range(0..65535),
|
||||
rng.gen_range(0..65535),
|
||||
rng.gen_range(0..65535),
|
||||
rng.gen_range(0..65535),
|
||||
rng.gen_range(0..65535),
|
||||
rng.gen_range(0..65535),
|
||||
rng.gen_range(0..65535),
|
||||
rng.gen_range(0..65535),
|
||||
);
|
||||
nodes.push(IpAddr::V6(ip));
|
||||
}
|
||||
config.set_exit_nodes(nodes);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ pub struct PeerManager {
|
||||
encryptor: Arc<Box<dyn Encryptor>>,
|
||||
data_compress_algo: CompressorAlgo,
|
||||
|
||||
exit_nodes: Vec<Ipv4Addr>,
|
||||
exit_nodes: Vec<IpAddr>,
|
||||
|
||||
reserved_my_peer_id_map: DashMap<String, PeerId>,
|
||||
|
||||
@@ -948,6 +948,9 @@ impl PeerManager {
|
||||
dst_peers.push(peer_id);
|
||||
} else {
|
||||
for exit_node in &self.exit_nodes {
|
||||
let IpAddr::V4(exit_node) = exit_node else {
|
||||
continue;
|
||||
};
|
||||
if let Some(peer_id) = self.peers.get_peer_id_by_ipv4(exit_node).await {
|
||||
dst_peers.push(peer_id);
|
||||
is_exit_node = true;
|
||||
@@ -985,18 +988,17 @@ impl PeerManager {
|
||||
);
|
||||
} else if let Some(peer_id) = self.peers.get_peer_id_by_ipv6(&ipv6_addr).await {
|
||||
dst_peers.push(peer_id);
|
||||
} else {
|
||||
// For IPv6, we'll need to implement exit node support later
|
||||
// For now, just try to find any available peer for routing
|
||||
if dst_peers.is_empty() {
|
||||
dst_peers.extend(
|
||||
self.peers
|
||||
.list_routes()
|
||||
.await
|
||||
.iter()
|
||||
.map(|x| x.key().clone()),
|
||||
);
|
||||
is_exit_node = true;
|
||||
} else if !ipv6_addr.is_unicast_link_local() {
|
||||
// NOTE: never route link local address to exit node.
|
||||
for exit_node in &self.exit_nodes {
|
||||
let IpAddr::V6(exit_node) = exit_node else {
|
||||
continue;
|
||||
};
|
||||
if let Some(peer_id) = self.peers.get_peer_id_by_ipv6(exit_node).await {
|
||||
dst_peers.push(peer_id);
|
||||
is_exit_node = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user