mirror of
https://mirror.suhoan.cn/https://github.com/EasyTier/EasyTier.git
synced 2025-12-15 22:27:26 +08:00
Add support for IPv6 within VPN (#1061)
* add flake.nix with nix based dev shell * add support for IPv6 * update thunk --------- Co-authored-by: sijie.sun <sijie.sun@smartx.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
net::Ipv4Addr,
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
sync::{Arc, Weak},
|
||||
time::{Instant, SystemTime},
|
||||
};
|
||||
@@ -873,6 +873,43 @@ impl PeerManager {
|
||||
(dst_peers, is_exit_node)
|
||||
}
|
||||
|
||||
pub async fn get_msg_dst_peer_ipv6(&self, ipv6_addr: &Ipv6Addr) -> (Vec<PeerId>, bool) {
|
||||
let mut is_exit_node = false;
|
||||
let mut dst_peers = vec![];
|
||||
let network_length = self
|
||||
.global_ctx
|
||||
.get_ipv6()
|
||||
.map(|x| x.network_length())
|
||||
.unwrap_or(64);
|
||||
let ipv6_inet = cidr::Ipv6Inet::new(*ipv6_addr, network_length).unwrap();
|
||||
if ipv6_addr.is_multicast() || *ipv6_addr == ipv6_inet.last_address() {
|
||||
dst_peers.extend(
|
||||
self.peers
|
||||
.list_routes()
|
||||
.await
|
||||
.iter()
|
||||
.map(|x| x.key().clone()),
|
||||
);
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
(dst_peers, is_exit_node)
|
||||
}
|
||||
|
||||
pub async fn try_compress_and_encrypt(
|
||||
compress_algo: CompressorAlgo,
|
||||
encryptor: &Box<dyn Encryptor>,
|
||||
@@ -887,11 +924,11 @@ impl PeerManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send_msg_ipv4(&self, mut msg: ZCPacket, ipv4_addr: Ipv4Addr) -> Result<(), Error> {
|
||||
pub async fn send_msg_by_ip(&self, mut msg: ZCPacket, ip_addr: IpAddr) -> Result<(), Error> {
|
||||
tracing::trace!(
|
||||
"do send_msg in peer manager, msg: {:?}, ipv4_addr: {}",
|
||||
"do send_msg in peer manager, msg: {:?}, ip_addr: {}",
|
||||
msg,
|
||||
ipv4_addr
|
||||
ip_addr
|
||||
);
|
||||
|
||||
msg.fill_peer_manager_hdr(
|
||||
@@ -911,10 +948,13 @@ impl PeerManager {
|
||||
.await;
|
||||
}
|
||||
|
||||
let (dst_peers, is_exit_node) = self.get_msg_dst_peer(&ipv4_addr).await;
|
||||
let (dst_peers, is_exit_node) = match ip_addr {
|
||||
IpAddr::V4(ipv4_addr) => self.get_msg_dst_peer(&ipv4_addr).await,
|
||||
IpAddr::V6(ipv6_addr) => self.get_msg_dst_peer_ipv6(&ipv6_addr).await,
|
||||
};
|
||||
|
||||
if dst_peers.is_empty() {
|
||||
tracing::info!("no peer id for ipv4: {}", ipv4_addr);
|
||||
tracing::info!("no peer id for ip: {}", ip_addr);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{net::Ipv4Addr, sync::Arc};
|
||||
use std::{net::{Ipv4Addr, Ipv6Addr}, sync::Arc};
|
||||
|
||||
use anyhow::Context;
|
||||
use dashmap::DashMap;
|
||||
@@ -194,6 +194,16 @@ impl PeerMap {
|
||||
None
|
||||
}
|
||||
|
||||
pub async fn get_peer_id_by_ipv6(&self, ipv6: &Ipv6Addr) -> Option<PeerId> {
|
||||
for route in self.routes.read().await.iter() {
|
||||
let peer_id = route.get_peer_id_by_ipv6(ipv6).await;
|
||||
if peer_id.is_some() {
|
||||
return peer_id;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub async fn get_route_peer_info(&self, peer_id: PeerId) -> Option<RoutePeerInfo> {
|
||||
for route in self.routes.read().await.iter() {
|
||||
if let Some(info) = route.get_peer_info(peer_id).await {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{
|
||||
collections::BTreeSet,
|
||||
fmt::Debug,
|
||||
net::Ipv4Addr,
|
||||
net::{Ipv4Addr, Ipv6Addr},
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU32, Ordering},
|
||||
Arc, Weak,
|
||||
@@ -125,6 +125,7 @@ impl RoutePeerInfo {
|
||||
peer_route_id: 0,
|
||||
network_length: 24,
|
||||
quic_port: None,
|
||||
ipv6_addr: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +166,7 @@ impl RoutePeerInfo {
|
||||
.unwrap_or(24),
|
||||
|
||||
quic_port: global_ctx.get_quic_proxy_port().map(|x| x as u32),
|
||||
ipv6_addr: global_ctx.get_ipv6().map(|x| x.into()),
|
||||
};
|
||||
|
||||
let need_update_periodically = if let Ok(Ok(d)) =
|
||||
@@ -221,6 +223,8 @@ impl Into<crate::proto::cli::Route> for RoutePeerInfo {
|
||||
next_hop_peer_id_latency_first: None,
|
||||
cost_latency_first: None,
|
||||
path_latency_latency_first: None,
|
||||
|
||||
ipv6_addr: self.ipv6_addr.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -635,6 +639,7 @@ struct RouteTable {
|
||||
peer_infos: DashMap<PeerId, RoutePeerInfo>,
|
||||
next_hop_map: NextHopMap,
|
||||
ipv4_peer_id_map: DashMap<Ipv4Addr, PeerId>,
|
||||
ipv6_peer_id_map: DashMap<Ipv6Addr, PeerId>,
|
||||
cidr_peer_id_map: DashMap<cidr::IpCidr, PeerId>,
|
||||
next_hop_map_version: AtomicVersion,
|
||||
}
|
||||
@@ -645,6 +650,7 @@ impl RouteTable {
|
||||
peer_infos: DashMap::new(),
|
||||
next_hop_map: DashMap::new(),
|
||||
ipv4_peer_id_map: DashMap::new(),
|
||||
ipv6_peer_id_map: DashMap::new(),
|
||||
cidr_peer_id_map: DashMap::new(),
|
||||
next_hop_map_version: AtomicVersion::new(),
|
||||
}
|
||||
@@ -742,6 +748,10 @@ impl RouteTable {
|
||||
// remove ipv4 map for peers we cannot reach.
|
||||
self.next_hop_map.contains_key(v)
|
||||
});
|
||||
self.ipv6_peer_id_map.retain(|_, v| {
|
||||
// remove ipv6 map for peers we cannot reach.
|
||||
self.next_hop_map.contains_key(v)
|
||||
});
|
||||
self.cidr_peer_id_map.retain(|_, v| {
|
||||
// remove cidr map for peers we cannot reach.
|
||||
self.next_hop_map.contains_key(v)
|
||||
@@ -876,6 +886,17 @@ impl RouteTable {
|
||||
.or_insert(*peer_id);
|
||||
}
|
||||
|
||||
if let Some(ipv6_addr) = info.ipv6_addr.and_then(|x| x.address) {
|
||||
self.ipv6_peer_id_map
|
||||
.entry(ipv6_addr.into())
|
||||
.and_modify(|v| {
|
||||
if *v != *peer_id && is_new_peer_better(*v) {
|
||||
*v = *peer_id;
|
||||
}
|
||||
})
|
||||
.or_insert(*peer_id);
|
||||
}
|
||||
|
||||
for cidr in info.proxy_cidrs.iter() {
|
||||
self.cidr_peer_id_map
|
||||
.entry(cidr.parse().unwrap())
|
||||
@@ -2267,6 +2288,21 @@ impl Route for PeerRoute {
|
||||
None
|
||||
}
|
||||
|
||||
async fn get_peer_id_by_ipv6(&self, ipv6_addr: &Ipv6Addr) -> Option<PeerId> {
|
||||
let route_table = &self.service_impl.route_table;
|
||||
if let Some(peer_id) = route_table.ipv6_peer_id_map.get(ipv6_addr) {
|
||||
return Some(*peer_id);
|
||||
}
|
||||
|
||||
// TODO: Add proxy support for IPv6 similar to IPv4
|
||||
// if let Some(peer_id) = route_table.get_peer_id_for_proxy_ipv6(ipv6_addr) {
|
||||
// return Some(peer_id);
|
||||
// }
|
||||
|
||||
tracing::debug!(?ipv6_addr, "no peer id for ipv6");
|
||||
None
|
||||
}
|
||||
|
||||
async fn set_route_cost_fn(&self, _cost_fn: RouteCostCalculator) {
|
||||
*self.service_impl.cost_calculator.write().unwrap() = Some(_cost_fn);
|
||||
self.service_impl.synced_route_info.version.inc();
|
||||
|
||||
@@ -36,6 +36,11 @@ impl DirectConnectorRpc for DirectConnectorManagerRpcServer {
|
||||
.chain(self.global_ctx.get_running_listeners().into_iter())
|
||||
.map(Into::into)
|
||||
.collect();
|
||||
// remove et ipv6 from the interface ipv6 list
|
||||
if let Some(et_ipv6) = self.global_ctx.get_ipv6() {
|
||||
let et_ipv6: crate::proto::common::Ipv6Addr = et_ipv6.address().into();
|
||||
ret.interface_ipv6s.retain(|x| *x != et_ipv6);
|
||||
}
|
||||
tracing::trace!(
|
||||
"get_ip_list: public_ipv4: {:?}, public_ipv6: {:?}, listeners: {:?}",
|
||||
ret.public_ipv4,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{net::Ipv4Addr, sync::Arc};
|
||||
use std::{net::{Ipv4Addr, Ipv6Addr}, sync::Arc};
|
||||
|
||||
use dashmap::DashMap;
|
||||
|
||||
@@ -82,6 +82,10 @@ pub trait Route {
|
||||
None
|
||||
}
|
||||
|
||||
async fn get_peer_id_by_ipv6(&self, _ipv6: &Ipv6Addr) -> Option<PeerId> {
|
||||
None
|
||||
}
|
||||
|
||||
async fn list_peers_own_foreign_network(
|
||||
&self,
|
||||
_network_identity: &NetworkIdentity,
|
||||
|
||||
Reference in New Issue
Block a user