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