mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 02:09:06 +00:00
Stun fix (#18)
* make easytier-core a lib * add stun command to easytier cli * fix stun test for musl
This commit is contained in:
@@ -6,6 +6,14 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
tracing = { version = "0.1", features = ["log"] }
|
||||||
|
tracing-subscriber = { version = "0.3", features = [
|
||||||
|
"env-filter",
|
||||||
|
"local-time",
|
||||||
|
"time",
|
||||||
|
] }
|
||||||
|
tracing-appender = "0.2.3"
|
||||||
|
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
use clap::{command, Args, Parser, Subcommand};
|
use clap::{command, Args, Parser, Subcommand};
|
||||||
use easytier_rpc::{
|
use easytier_core::{
|
||||||
connector_manage_rpc_client::ConnectorManageRpcClient,
|
common::stun::{StunInfoCollector, UdpNatTypeDetector},
|
||||||
peer_manage_rpc_client::PeerManageRpcClient, *,
|
rpc::{
|
||||||
|
connector_manage_rpc_client::ConnectorManageRpcClient,
|
||||||
|
peer_manage_rpc_client::PeerManageRpcClient, *,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use humansize::format_size;
|
use humansize::format_size;
|
||||||
use tabled::settings::Style;
|
use tabled::settings::Style;
|
||||||
|
use tracing::level_filters::LevelFilter;
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
@@ -16,13 +21,14 @@ struct Cli {
|
|||||||
instance_name: String,
|
instance_name: String,
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
sub_command: Option<SubCommand>,
|
sub_command: SubCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum SubCommand {
|
enum SubCommand {
|
||||||
Peer(PeerArgs),
|
Peer(PeerArgs),
|
||||||
Connector(ConnectorArgs),
|
Connector(ConnectorArgs),
|
||||||
|
Stun,
|
||||||
Route,
|
Route,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,15 +350,41 @@ impl CommandHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_logger() {
|
||||||
|
// logger to rolling file
|
||||||
|
let file_filter = EnvFilter::builder()
|
||||||
|
.with_default_directive(LevelFilter::INFO.into())
|
||||||
|
.from_env()
|
||||||
|
.unwrap();
|
||||||
|
let file_appender = tracing_appender::rolling::Builder::new()
|
||||||
|
.rotation(tracing_appender::rolling::Rotation::DAILY)
|
||||||
|
.max_log_files(1)
|
||||||
|
.filename_prefix("cli.log")
|
||||||
|
.build("/tmp")
|
||||||
|
.expect("failed to initialize rolling file appender");
|
||||||
|
let mut file_layer = tracing_subscriber::fmt::layer();
|
||||||
|
file_layer.set_ansi(false);
|
||||||
|
let file_layer = file_layer
|
||||||
|
.with_writer(file_appender)
|
||||||
|
.with_filter(file_filter);
|
||||||
|
|
||||||
|
tracing_subscriber::Registry::default()
|
||||||
|
.with(file_layer)
|
||||||
|
.init();
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
#[tracing::instrument]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), Error> {
|
||||||
|
init_logger();
|
||||||
|
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let handler = CommandHandler {
|
let handler = CommandHandler {
|
||||||
addr: "http://127.0.0.1:15888".to_string(),
|
addr: "http://127.0.0.1:15888".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match cli.sub_command {
|
match cli.sub_command {
|
||||||
Some(SubCommand::Peer(peer_args)) => match &peer_args.sub_command {
|
SubCommand::Peer(peer_args) => match &peer_args.sub_command {
|
||||||
Some(PeerSubCommand::Add) => {
|
Some(PeerSubCommand::Add) => {
|
||||||
println!("add peer");
|
println!("add peer");
|
||||||
}
|
}
|
||||||
@@ -370,7 +402,7 @@ async fn main() -> Result<(), Error> {
|
|||||||
handler.handle_peer_list(&peer_args).await?;
|
handler.handle_peer_list(&peer_args).await?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(SubCommand::Connector(conn_args)) => match conn_args.sub_command {
|
SubCommand::Connector(conn_args) => match conn_args.sub_command {
|
||||||
Some(ConnectorSubCommand::Add) => {
|
Some(ConnectorSubCommand::Add) => {
|
||||||
println!("add connector");
|
println!("add connector");
|
||||||
}
|
}
|
||||||
@@ -384,11 +416,12 @@ async fn main() -> Result<(), Error> {
|
|||||||
handler.handle_connector_list().await?;
|
handler.handle_connector_list().await?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(SubCommand::Route) => {
|
SubCommand::Route => {
|
||||||
handler.handle_route_list().await?;
|
handler.handle_route_list().await?;
|
||||||
}
|
}
|
||||||
None => {
|
SubCommand::Stun => {
|
||||||
println!("list peer");
|
let stun = UdpNatTypeDetector::new(StunInfoCollector::get_default_servers());
|
||||||
|
println!("udp type: {:?}", stun.get_udp_nat_type(0).await);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ rust-version = "1.75"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "easytier_rpc"
|
name = "easytier_core"
|
||||||
path = "src/rpc/lib.rs"
|
test = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tracing = { version = "0.1", features = ["log"] }
|
tracing = { version = "0.1", features = ["log"] }
|
||||||
@@ -87,8 +87,15 @@ public-ip = { version = "0.2", features = ["default"] }
|
|||||||
|
|
||||||
clap = { version = "4.4", features = ["derive"] }
|
clap = { version = "4.4", features = ["derive"] }
|
||||||
|
|
||||||
|
async-recursion = "1.0.5"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows-sys = { version = "0.52", features = ["Win32_Networking_WinSock", "Win32_NetworkManagement_IpHelper", "Win32_Foundation", "Win32_System_IO"] }
|
windows-sys = { version = "0.52", features = [
|
||||||
|
"Win32_Networking_WinSock",
|
||||||
|
"Win32_NetworkManagement_IpHelper",
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_System_IO",
|
||||||
|
] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tonic-build = "0.10"
|
tonic-build = "0.10"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::{io::Write, sync::Arc};
|
use std::{io::Write, sync::Arc};
|
||||||
|
|
||||||
|
use crate::rpc::PeerConnInfo;
|
||||||
use crossbeam::atomic::AtomicCell;
|
use crossbeam::atomic::AtomicCell;
|
||||||
use easytier_rpc::PeerConnInfo;
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
config_fs::ConfigFs,
|
config_fs::ConfigFs,
|
||||||
@@ -62,27 +62,6 @@ impl GlobalCtx {
|
|||||||
|
|
||||||
let (event_bus, _) = tokio::sync::broadcast::channel(100);
|
let (event_bus, _) = tokio::sync::broadcast::channel(100);
|
||||||
|
|
||||||
// NOTICE: we may need to choose stun stun server based on geo location
|
|
||||||
// stun server cross nation may return a external ip address with high latency and loss rate
|
|
||||||
let default_stun_servers = vec![
|
|
||||||
"stun.miwifi.com:3478".to_string(),
|
|
||||||
"stun.qq.com:3478".to_string(),
|
|
||||||
"stun.chat.bilibili.com:3478".to_string(),
|
|
||||||
"fwa.lifesizecloud.com:3478".to_string(),
|
|
||||||
"stun.isp.net.au:3478".to_string(),
|
|
||||||
"stun.nextcloud.com:3478".to_string(),
|
|
||||||
"stun.freeswitch.org:3478".to_string(),
|
|
||||||
"stun.voip.blackberry.com:3478".to_string(),
|
|
||||||
"stunserver.stunprotocol.org:3478".to_string(),
|
|
||||||
"stun.sipnet.com:3478".to_string(),
|
|
||||||
"stun.radiojar.com:3478".to_string(),
|
|
||||||
"stun.sonetel.com:3478".to_string(),
|
|
||||||
"stun.voipgate.com:3478".to_string(),
|
|
||||||
"stun.counterpath.com:3478".to_string(),
|
|
||||||
"180.235.108.91:3478".to_string(),
|
|
||||||
"193.22.2.248:3478".to_string(),
|
|
||||||
];
|
|
||||||
|
|
||||||
GlobalCtx {
|
GlobalCtx {
|
||||||
inst_name: inst_name.to_string(),
|
inst_name: inst_name.to_string(),
|
||||||
id,
|
id,
|
||||||
@@ -96,7 +75,7 @@ impl GlobalCtx {
|
|||||||
|
|
||||||
hotname: AtomicCell::new(None),
|
hotname: AtomicCell::new(None),
|
||||||
|
|
||||||
stun_info_collection: Box::new(StunInfoCollector::new(default_stun_servers)),
|
stun_info_collection: Box::new(StunInfoCollector::new_with_default_servers()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +185,7 @@ impl GlobalCtx {
|
|||||||
let ptr = ptr as *mut Box<dyn StunInfoCollectorTrait>;
|
let ptr = ptr as *mut Box<dyn StunInfoCollectorTrait>;
|
||||||
unsafe {
|
unsafe {
|
||||||
std::ptr::drop_in_place(ptr);
|
std::ptr::drop_in_place(ptr);
|
||||||
|
#[allow(invalid_reference_casting)]
|
||||||
std::ptr::write(ptr, collector);
|
std::ptr::write(ptr, collector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
use futures::Future;
|
use futures::Future;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use nix::sched::{setns, CloneFlags};
|
use nix::sched::{setns, CloneFlags};
|
||||||
@@ -12,8 +10,6 @@ pub struct NetNSGuard {
|
|||||||
old_ns: Option<std::fs::File>,
|
old_ns: Option<std::fs::File>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetNSLock = Mutex<()>;
|
|
||||||
static LOCK: Lazy<NetNSLock> = Lazy::new(|| Mutex::new(()));
|
|
||||||
pub static ROOT_NETNS_NAME: &str = "_root_ns";
|
pub static ROOT_NETNS_NAME: &str = "_root_ns";
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::{ops::Deref, sync::Arc};
|
use std::{ops::Deref, sync::Arc};
|
||||||
|
|
||||||
use easytier_rpc::peer::GetIpListResponse;
|
use crate::rpc::peer::GetIpListResponse;
|
||||||
use pnet::datalink::NetworkInterface;
|
use pnet::datalink::NetworkInterface;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
sync::{Mutex, RwLock},
|
sync::{Mutex, RwLock},
|
||||||
@@ -156,7 +156,7 @@ impl IPCollector {
|
|||||||
|
|
||||||
#[tracing::instrument(skip(net_ns))]
|
#[tracing::instrument(skip(net_ns))]
|
||||||
async fn do_collect_ip_addrs(with_public: bool, net_ns: NetNS) -> GetIpListResponse {
|
async fn do_collect_ip_addrs(with_public: bool, net_ns: NetNS) -> GetIpListResponse {
|
||||||
let mut ret = easytier_rpc::peer::GetIpListResponse {
|
let mut ret = crate::rpc::peer::GetIpListResponse {
|
||||||
public_ipv4: "".to_string(),
|
public_ipv4: "".to_string(),
|
||||||
interface_ipv4s: vec![],
|
interface_ipv4s: vec![],
|
||||||
public_ipv6: "".to_string(),
|
public_ipv6: "".to_string(),
|
||||||
|
|||||||
@@ -2,19 +2,50 @@ use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::rpc::{NatType, StunInfo};
|
||||||
use crossbeam::atomic::AtomicCell;
|
use crossbeam::atomic::AtomicCell;
|
||||||
use easytier_rpc::{NatType, StunInfo};
|
|
||||||
use stun_format::Attr;
|
use stun_format::Attr;
|
||||||
use tokio::net::{lookup_host, UdpSocket};
|
use tokio::net::{lookup_host, UdpSocket};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use tokio::task::JoinSet;
|
use tokio::task::JoinSet;
|
||||||
|
use tracing::Level;
|
||||||
|
|
||||||
use crate::common::error::Error;
|
use crate::common::error::Error;
|
||||||
|
|
||||||
struct Stun {
|
struct HostResolverIter {
|
||||||
stun_server: String,
|
hostnames: Vec<String>,
|
||||||
req_repeat: u8,
|
ips: Vec<SocketAddr>,
|
||||||
resp_timeout: Duration,
|
}
|
||||||
|
|
||||||
|
impl HostResolverIter {
|
||||||
|
fn new(hostnames: Vec<String>) -> Self {
|
||||||
|
Self {
|
||||||
|
hostnames,
|
||||||
|
ips: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_recursion::async_recursion]
|
||||||
|
async fn next(&mut self) -> Option<SocketAddr> {
|
||||||
|
if self.ips.is_empty() {
|
||||||
|
if self.hostnames.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let host = self.hostnames.remove(0);
|
||||||
|
match lookup_host(&host).await {
|
||||||
|
Ok(ips) => {
|
||||||
|
self.ips = ips.collect();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!(?host, ?e, "lookup host for stun failed");
|
||||||
|
return self.next().await;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(self.ips.remove(0))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@@ -36,8 +67,15 @@ impl BindRequestResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Stun {
|
||||||
|
stun_server: SocketAddr,
|
||||||
|
req_repeat: u8,
|
||||||
|
resp_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
impl Stun {
|
impl Stun {
|
||||||
pub fn new(stun_server: String) -> Self {
|
pub fn new(stun_server: SocketAddr) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stun_server,
|
stun_server,
|
||||||
req_repeat: 3,
|
req_repeat: 3,
|
||||||
@@ -73,7 +111,7 @@ impl Stun {
|
|||||||
unsafe { std::ptr::copy(udp_buf.as_ptr(), buf.as_ptr() as *mut u8, len) };
|
unsafe { std::ptr::copy(udp_buf.as_ptr(), buf.as_ptr() as *mut u8, len) };
|
||||||
|
|
||||||
let msg = stun_format::Msg::<'a>::from(&buf[..]);
|
let msg = stun_format::Msg::<'a>::from(&buf[..]);
|
||||||
tracing::trace!(b = ?&udp_buf[..len], ?msg, ?tids, ?remote_addr, "recv stun response");
|
tracing::info!(b = ?&udp_buf[..len], ?msg, ?tids, ?remote_addr, ?stun_host, "recv stun response");
|
||||||
|
|
||||||
if msg.typ().is_none() || msg.tid().is_none() {
|
if msg.typ().is_none() || msg.tid().is_none() {
|
||||||
continue;
|
continue;
|
||||||
@@ -151,16 +189,14 @@ impl Stun {
|
|||||||
changed_addr
|
changed_addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(ret, err, level = Level::INFO)]
|
||||||
pub async fn bind_request(
|
pub async fn bind_request(
|
||||||
&self,
|
&self,
|
||||||
source_port: u16,
|
source_port: u16,
|
||||||
change_ip: bool,
|
change_ip: bool,
|
||||||
change_port: bool,
|
change_port: bool,
|
||||||
) -> Result<BindRequestResponse, Error> {
|
) -> Result<BindRequestResponse, Error> {
|
||||||
let stun_host = lookup_host(&self.stun_server)
|
let stun_host = self.stun_server;
|
||||||
.await?
|
|
||||||
.next()
|
|
||||||
.ok_or(Error::NotFound)?;
|
|
||||||
let udp = UdpSocket::bind(format!("0.0.0.0:{}", source_port)).await?;
|
let udp = UdpSocket::bind(format!("0.0.0.0:{}", source_port)).await?;
|
||||||
|
|
||||||
// repeat req in case of packet loss
|
// repeat req in case of packet loss
|
||||||
@@ -218,7 +254,7 @@ impl Stun {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UdpNatTypeDetector {
|
pub struct UdpNatTypeDetector {
|
||||||
stun_servers: Vec<String>,
|
stun_servers: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +263,7 @@ impl UdpNatTypeDetector {
|
|||||||
Self { stun_servers }
|
Self { stun_servers }
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_udp_nat_type(&self, mut source_port: u16) -> NatType {
|
pub async fn get_udp_nat_type(&self, mut source_port: u16) -> NatType {
|
||||||
// Like classic STUN (rfc3489). Detect NAT behavior for UDP.
|
// Like classic STUN (rfc3489). Detect NAT behavior for UDP.
|
||||||
// Modified from rfc3489. Requires at least two STUN servers.
|
// Modified from rfc3489. Requires at least two STUN servers.
|
||||||
let mut ret_test1_1 = None;
|
let mut ret_test1_1 = None;
|
||||||
@@ -241,7 +277,8 @@ impl UdpNatTypeDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut succ = false;
|
let mut succ = false;
|
||||||
for server_ip in &self.stun_servers {
|
let mut ips = HostResolverIter::new(self.stun_servers.clone());
|
||||||
|
while let Some(server_ip) = ips.next().await {
|
||||||
let stun = Stun::new(server_ip.clone());
|
let stun = Stun::new(server_ip.clone());
|
||||||
let ret = stun.bind_request(source_port, false, false).await;
|
let ret = stun.bind_request(source_port, false, false).await;
|
||||||
if ret.is_err() {
|
if ret.is_err() {
|
||||||
@@ -255,13 +292,19 @@ impl UdpNatTypeDetector {
|
|||||||
ret_test1_2 = ret.ok();
|
ret_test1_2 = ret.ok();
|
||||||
let ret = stun.bind_request(source_port, true, true).await;
|
let ret = stun.bind_request(source_port, true, true).await;
|
||||||
if let Ok(resp) = ret {
|
if let Ok(resp) = ret {
|
||||||
if !resp.ip_changed || !resp.port_changed {
|
if !resp.real_ip_changed || !resp.real_port_changed {
|
||||||
|
tracing::info!(
|
||||||
|
?server_ip,
|
||||||
|
?ret,
|
||||||
|
"stun bind request return with unchanged ip and port"
|
||||||
|
);
|
||||||
// Try another STUN server
|
// Try another STUN server
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret_test2 = ret.ok();
|
ret_test2 = ret.ok();
|
||||||
ret_test3 = stun.bind_request(source_port, false, true).await.ok();
|
ret_test3 = stun.bind_request(source_port, false, true).await.ok();
|
||||||
|
tracing::info!(?ret_test3, "stun bind request with changed port");
|
||||||
succ = true;
|
succ = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -340,7 +383,8 @@ impl StunInfoCollectorTrait for StunInfoCollector {
|
|||||||
|
|
||||||
async fn get_udp_port_mapping(&self, local_port: u16) -> Result<SocketAddr, Error> {
|
async fn get_udp_port_mapping(&self, local_port: u16) -> Result<SocketAddr, Error> {
|
||||||
let stun_servers = self.stun_servers.read().await.clone();
|
let stun_servers = self.stun_servers.read().await.clone();
|
||||||
for server in stun_servers.iter() {
|
let mut ips = HostResolverIter::new(stun_servers.clone());
|
||||||
|
while let Some(server) = ips.next().await {
|
||||||
let stun = Stun::new(server.clone());
|
let stun = Stun::new(server.clone());
|
||||||
let Ok(ret) = stun.bind_request(local_port, false, false).await else {
|
let Ok(ret) = stun.bind_request(local_port, false, false).await else {
|
||||||
tracing::warn!(?server, "stun bind request failed");
|
tracing::warn!(?server, "stun bind request failed");
|
||||||
@@ -371,6 +415,33 @@ impl StunInfoCollector {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_with_default_servers() -> Self {
|
||||||
|
Self::new(Self::get_default_servers())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_default_servers() -> Vec<String> {
|
||||||
|
// NOTICE: we may need to choose stun stun server based on geo location
|
||||||
|
// stun server cross nation may return a external ip address with high latency and loss rate
|
||||||
|
vec![
|
||||||
|
"stun.miwifi.com:3478".to_string(),
|
||||||
|
"stun.qq.com:3478".to_string(),
|
||||||
|
// "stun.chat.bilibili.com:3478".to_string(), // bilibili's stun server doesn't repond to change_ip and change_port
|
||||||
|
"fwa.lifesizecloud.com:3478".to_string(),
|
||||||
|
"stun.isp.net.au:3478".to_string(),
|
||||||
|
"stun.nextcloud.com:3478".to_string(),
|
||||||
|
"stun.freeswitch.org:3478".to_string(),
|
||||||
|
"stun.voip.blackberry.com:3478".to_string(),
|
||||||
|
"stunserver.stunprotocol.org:3478".to_string(),
|
||||||
|
"stun.sipnet.com:3478".to_string(),
|
||||||
|
"stun.radiojar.com:3478".to_string(),
|
||||||
|
"stun.sonetel.com:3478".to_string(),
|
||||||
|
"stun.voipgate.com:3478".to_string(),
|
||||||
|
"stun.counterpath.com:3478".to_string(),
|
||||||
|
"180.235.108.91:3478".to_string(),
|
||||||
|
"193.22.2.248:3478".to_string(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
fn start_stun_routine(&mut self) {
|
fn start_stun_routine(&mut self) {
|
||||||
let stun_servers = self.stun_servers.clone();
|
let stun_servers = self.stun_servers.clone();
|
||||||
let udp_nat_type = self.udp_nat_type.clone();
|
let udp_nat_type = self.udp_nat_type.clone();
|
||||||
@@ -412,7 +483,8 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_stun_bind_request() {
|
async fn test_stun_bind_request() {
|
||||||
// miwifi / qq seems not correctly responde to change_ip and change_port, they always try to change the src ip and port.
|
// miwifi / qq seems not correctly responde to change_ip and change_port, they always try to change the src ip and port.
|
||||||
let stun = Stun::new("stun1.l.google.com:19302".to_string());
|
let mut ips = HostResolverIter::new(vec!["stun1.l.google.com:19302".to_string()]);
|
||||||
|
let stun = Stun::new(ips.next().await.unwrap());
|
||||||
// let stun = Stun::new("180.235.108.91:3478".to_string());
|
// let stun = Stun::new("180.235.108.91:3478".to_string());
|
||||||
// let stun = Stun::new("193.22.2.248:3478".to_string());
|
// let stun = Stun::new("193.22.2.248:3478".to_string());
|
||||||
// let stun = Stun::new("stun.chat.bilibili.com:3478".to_string());
|
// let stun = Stun::new("stun.chat.bilibili.com:3478".to_string());
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use crate::{
|
|||||||
peers::{peer_manager::PeerManager, peer_rpc::PeerRpcManager, PeerId},
|
peers::{peer_manager::PeerManager, peer_rpc::PeerRpcManager, PeerId},
|
||||||
};
|
};
|
||||||
|
|
||||||
use easytier_rpc::{peer::GetIpListResponse, PeerConnInfo};
|
use crate::rpc::{peer::GetIpListResponse, PeerConnInfo};
|
||||||
use tokio::{task::JoinSet, time::timeout};
|
use tokio::{task::JoinSet, time::timeout};
|
||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
use std::{collections::BTreeSet, sync::Arc};
|
use std::{collections::BTreeSet, sync::Arc};
|
||||||
|
|
||||||
use dashmap::{DashMap, DashSet};
|
use dashmap::{DashMap, DashSet};
|
||||||
use easytier_rpc::{
|
|
||||||
connector_manage_rpc_server::ConnectorManageRpc, Connector, ConnectorStatus,
|
|
||||||
ListConnectorRequest, ManageConnectorRequest,
|
|
||||||
};
|
|
||||||
use tokio::{
|
use tokio::{
|
||||||
sync::{broadcast::Receiver, mpsc, Mutex},
|
sync::{broadcast::Receiver, mpsc, Mutex},
|
||||||
task::JoinSet,
|
task::JoinSet,
|
||||||
time::timeout,
|
time::timeout,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::rpc as easytier_rpc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{
|
common::{
|
||||||
error::Error,
|
error::Error,
|
||||||
@@ -19,6 +17,10 @@ use crate::{
|
|||||||
},
|
},
|
||||||
connector::set_bind_addr_for_peer_connector,
|
connector::set_bind_addr_for_peer_connector,
|
||||||
peers::peer_manager::PeerManager,
|
peers::peer_manager::PeerManager,
|
||||||
|
rpc::{
|
||||||
|
connector_manage_rpc_server::ConnectorManageRpc, Connector, ConnectorStatus,
|
||||||
|
ListConnectorRequest, ManageConnectorRequest,
|
||||||
|
},
|
||||||
tunnels::{Tunnel, TunnelConnector},
|
tunnels::{Tunnel, TunnelConnector},
|
||||||
use_global_var,
|
use_global_var,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use std::{net::SocketAddr, sync::Arc};
|
|||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use crossbeam::atomic::AtomicCell;
|
use crossbeam::atomic::AtomicCell;
|
||||||
use easytier_rpc::NatType;
|
|
||||||
use rand::{seq::SliceRandom, Rng, SeedableRng};
|
use rand::{seq::SliceRandom, Rng, SeedableRng};
|
||||||
use tokio::{net::UdpSocket, sync::Mutex, task::JoinSet};
|
use tokio::{net::UdpSocket, sync::Mutex, task::JoinSet};
|
||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
@@ -13,6 +12,7 @@ use crate::{
|
|||||||
stun::StunInfoCollectorTrait,
|
stun::StunInfoCollectorTrait,
|
||||||
},
|
},
|
||||||
peers::{peer_manager::PeerManager, PeerId},
|
peers::{peer_manager::PeerManager, PeerId},
|
||||||
|
rpc::NatType,
|
||||||
tunnels::{
|
tunnels::{
|
||||||
common::setup_sokcet2,
|
common::setup_sokcet2,
|
||||||
udp_tunnel::{UdpPacket, UdpTunnelConnector, UdpTunnelListener},
|
udp_tunnel::{UdpPacket, UdpTunnelConnector, UdpTunnelListener},
|
||||||
@@ -459,7 +459,7 @@ impl UdpHolePunchConnector {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use easytier_rpc::{NatType, StunInfo};
|
use crate::rpc::{NatType, StunInfo};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{error::Error, stun::StunInfoCollectorTrait},
|
common::{error::Error, stun::StunInfoCollectorTrait},
|
||||||
|
|||||||
@@ -318,12 +318,12 @@ impl Instance {
|
|||||||
log::info!("[INIT RPC] start rpc server. addr: {}", addr);
|
log::info!("[INIT RPC] start rpc server. addr: {}", addr);
|
||||||
Server::builder()
|
Server::builder()
|
||||||
.add_service(
|
.add_service(
|
||||||
easytier_rpc::peer_manage_rpc_server::PeerManageRpcServer::new(
|
crate::rpc::peer_manage_rpc_server::PeerManageRpcServer::new(
|
||||||
PeerManagerRpcService::new(peer_mgr),
|
PeerManagerRpcService::new(peer_mgr),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_service(
|
.add_service(
|
||||||
easytier_rpc::connector_manage_rpc_server::ConnectorManageRpcServer::new(
|
crate::rpc::connector_manage_rpc_server::ConnectorManageRpcServer::new(
|
||||||
ConnectorManagerRpcService(conn_manager.clone()),
|
ConnectorManagerRpcService(conn_manager.clone()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
pub mod arch;
|
||||||
|
pub mod common;
|
||||||
|
pub mod rpc;
|
||||||
|
pub mod tunnels;
|
||||||
@@ -12,6 +12,7 @@ mod gateway;
|
|||||||
mod instance;
|
mod instance;
|
||||||
mod peer_center;
|
mod peer_center;
|
||||||
mod peers;
|
mod peers;
|
||||||
|
mod rpc;
|
||||||
mod tunnels;
|
mod tunnels;
|
||||||
|
|
||||||
use instance::instance::{Instance, InstanceConfigWriter};
|
use instance::instance::{Instance, InstanceConfigWriter};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::collections::BTreeMap;
|
|||||||
use crate::peers::PeerId;
|
use crate::peers::PeerId;
|
||||||
|
|
||||||
use super::{Digest, Error};
|
use super::{Digest, Error};
|
||||||
use easytier_rpc::PeerInfo;
|
use crate::rpc::PeerInfo;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, serde::Deserialize, serde::Serialize)]
|
#[derive(Debug, Clone, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
pub enum LatencyLevel {
|
pub enum LatencyLevel {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use easytier_rpc::PeerConnInfo;
|
|
||||||
|
|
||||||
use tokio::{
|
use tokio::{
|
||||||
select,
|
select,
|
||||||
@@ -12,12 +11,12 @@ use tokio_util::bytes::Bytes;
|
|||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::peer_conn::PeerConn;
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
error::Error,
|
error::Error,
|
||||||
global_ctx::{ArcGlobalCtx, GlobalCtxEvent},
|
global_ctx::{ArcGlobalCtx, GlobalCtxEvent},
|
||||||
};
|
};
|
||||||
|
use crate::rpc::PeerConnInfo;
|
||||||
use super::peer_conn::PeerConn;
|
|
||||||
|
|
||||||
type ArcPeerConn = Arc<Mutex<PeerConn>>;
|
type ArcPeerConn = Arc<Mutex<PeerConn>>;
|
||||||
type ConnMap = Arc<DashMap<Uuid, ArcPeerConn>>;
|
type ConnMap = Arc<DashMap<Uuid, ArcPeerConn>>;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use std::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use easytier_rpc::{PeerConnInfo, PeerConnStats};
|
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use pnet::datalink::NetworkInterface;
|
use pnet::datalink::NetworkInterface;
|
||||||
|
|
||||||
@@ -26,6 +25,7 @@ use tracing::Instrument;
|
|||||||
use crate::{
|
use crate::{
|
||||||
common::global_ctx::ArcGlobalCtx,
|
common::global_ctx::ArcGlobalCtx,
|
||||||
define_tunnel_filter_chain,
|
define_tunnel_filter_chain,
|
||||||
|
rpc::{PeerConnInfo, PeerConnStats},
|
||||||
tunnels::{
|
tunnels::{
|
||||||
stats::{Throughput, WindowLatency},
|
stats::{Throughput, WindowLatency},
|
||||||
tunnel_filter::StatsRecorderTunnelFilter,
|
tunnel_filter::StatsRecorderTunnelFilter,
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ impl PeerManager {
|
|||||||
self.peers.add_route(arc_route).await;
|
self.peers.add_route(arc_route).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_routes(&self) -> Vec<easytier_rpc::Route> {
|
pub async fn list_routes(&self) -> Vec<crate::rpc::Route> {
|
||||||
self.basic_route.list_routes().await
|
self.basic_route.list_routes().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ use std::{net::Ipv4Addr, sync::Arc};
|
|||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use easytier_rpc::PeerConnInfo;
|
|
||||||
use tokio::sync::{mpsc, RwLock};
|
use tokio::sync::{mpsc, RwLock};
|
||||||
use tokio_util::bytes::Bytes;
|
use tokio_util::bytes::Bytes;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{error::Error, global_ctx::ArcGlobalCtx},
|
common::{error::Error, global_ctx::ArcGlobalCtx},
|
||||||
|
rpc::PeerConnInfo,
|
||||||
tunnels::TunnelError,
|
tunnels::TunnelError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use std::{net::Ipv4Addr, sync::Arc, time::Duration};
|
|||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use easytier_rpc::{NatType, StunInfo};
|
|
||||||
use rkyv::{Archive, Deserialize, Serialize};
|
use rkyv::{Archive, Deserialize, Serialize};
|
||||||
use tokio::{sync::Mutex, task::JoinSet};
|
use tokio::{sync::Mutex, task::JoinSet};
|
||||||
use tokio_util::bytes::Bytes;
|
use tokio_util::bytes::Bytes;
|
||||||
@@ -21,6 +20,7 @@ use crate::{
|
|||||||
route_trait::{Route, RouteInterfaceBox},
|
route_trait::{Route, RouteInterfaceBox},
|
||||||
PeerId,
|
PeerId,
|
||||||
},
|
},
|
||||||
|
rpc::{NatType, StunInfo},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{packet::ArchivedPacketBody, peer_manager::PeerPacketFilter};
|
use super::{packet::ArchivedPacketBody, peer_manager::PeerPacketFilter};
|
||||||
@@ -431,11 +431,11 @@ impl Route for BasicRoute {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_routes(&self) -> Vec<easytier_rpc::Route> {
|
async fn list_routes(&self) -> Vec<crate::rpc::Route> {
|
||||||
let mut routes = Vec::new();
|
let mut routes = Vec::new();
|
||||||
|
|
||||||
let parse_route_info = |real_peer_id: &Uuid, route_info: &SyncPeerInfo| {
|
let parse_route_info = |real_peer_id: &Uuid, route_info: &SyncPeerInfo| {
|
||||||
let mut route = easytier_rpc::Route::default();
|
let mut route = crate::rpc::Route::default();
|
||||||
route.ipv4_addr = if let Some(ipv4_addr) = route_info.ipv4_addr {
|
route.ipv4_addr = if let Some(ipv4_addr) = route_info.ipv4_addr {
|
||||||
ipv4_addr.to_string()
|
ipv4_addr.to_string()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub trait Route {
|
|||||||
async fn close(&self);
|
async fn close(&self);
|
||||||
|
|
||||||
async fn get_next_hop(&self, peer_id: &PeerId) -> Option<PeerId>;
|
async fn get_next_hop(&self, peer_id: &PeerId) -> Option<PeerId>;
|
||||||
async fn list_routes(&self) -> Vec<easytier_rpc::Route>;
|
async fn list_routes(&self) -> Vec<crate::rpc::Route>;
|
||||||
|
|
||||||
async fn get_peer_id_by_ipv4(&self, _ipv4: &Ipv4Addr) -> Option<PeerId> {
|
async fn get_peer_id_by_ipv4(&self, _ipv4: &Ipv4Addr) -> Option<PeerId> {
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use easytier_rpc::cli::PeerInfo;
|
use crate::rpc::{
|
||||||
use easytier_rpc::peer_manage_rpc_server::PeerManageRpc;
|
cli::PeerInfo,
|
||||||
use easytier_rpc::{ListPeerRequest, ListPeerResponse, ListRouteRequest, ListRouteResponse};
|
peer_manage_rpc_server::PeerManageRpc,
|
||||||
|
{ListPeerRequest, ListPeerResponse, ListRouteRequest, ListRouteResponse},
|
||||||
|
};
|
||||||
use tonic::{Request, Response, Status};
|
use tonic::{Request, Response, Status};
|
||||||
|
|
||||||
use super::peer_manager::PeerManager;
|
use super::peer_manager::PeerManager;
|
||||||
@@ -20,7 +22,7 @@ impl PeerManagerRpcService {
|
|||||||
let peers = self.peer_manager.get_peer_map().list_peers().await;
|
let peers = self.peer_manager.get_peer_map().list_peers().await;
|
||||||
let mut peer_infos = Vec::new();
|
let mut peer_infos = Vec::new();
|
||||||
for peer in peers {
|
for peer in peers {
|
||||||
let mut peer_info = easytier_rpc::PeerInfo::default();
|
let mut peer_info = PeerInfo::default();
|
||||||
peer_info.peer_id = peer.to_string();
|
peer_info.peer_id = peer.to_string();
|
||||||
|
|
||||||
if let Some(conns) = self
|
if let Some(conns) = self
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ pub fn enable_log() {
|
|||||||
.init();
|
.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_route(ipv4: &str, dst_peer_id: uuid::Uuid, routes: Vec<easytier_rpc::Route>) {
|
fn check_route(ipv4: &str, dst_peer_id: uuid::Uuid, routes: Vec<crate::rpc::Route>) {
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for r in routes.iter() {
|
for r in routes.iter() {
|
||||||
if r.ipv4_addr == ipv4.to_string() {
|
if r.ipv4_addr == ipv4.to_string() {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ pub mod udp_tunnel;
|
|||||||
|
|
||||||
use std::{fmt::Debug, net::SocketAddr, pin::Pin, sync::Arc};
|
use std::{fmt::Debug, net::SocketAddr, pin::Pin, sync::Arc};
|
||||||
|
|
||||||
|
use crate::rpc::TunnelInfo;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use easytier_rpc::TunnelInfo;
|
|
||||||
use futures::{Sink, SinkExt, Stream};
|
use futures::{Sink, SinkExt, Stream};
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::{
|
|||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
use easytier_rpc::TunnelInfo;
|
use crate::rpc::TunnelInfo;
|
||||||
use futures::{Sink, SinkExt, Stream, StreamExt};
|
use futures::{Sink, SinkExt, Stream, StreamExt};
|
||||||
|
|
||||||
use self::stats::Throughput;
|
use self::stats::Throughput;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use std::{fmt::Debug, pin::Pin, sync::Arc};
|
|||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use easytier_rpc::TunnelInfo;
|
|
||||||
use futures::{stream::FuturesUnordered, SinkExt, StreamExt};
|
use futures::{stream::FuturesUnordered, SinkExt, StreamExt};
|
||||||
use rkyv::{Archive, Deserialize, Serialize};
|
use rkyv::{Archive, Deserialize, Serialize};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
@@ -15,6 +14,7 @@ use tracing::Instrument;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::rkyv_util::{self, encode_to_bytes},
|
common::rkyv_util::{self, encode_to_bytes},
|
||||||
|
rpc::TunnelInfo,
|
||||||
tunnels::{build_url_from_socket_addr, close_tunnel, TunnelConnCounter, TunnelConnector},
|
tunnels::{build_url_from_socket_addr, close_tunnel, TunnelConnCounter, TunnelConnector},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user