修改stun

This commit is contained in:
lbl8603
2024-06-27 21:58:17 +08:00
parent 9e249862dc
commit 916fd8254b
5 changed files with 77 additions and 30 deletions
+4 -4
View File
@@ -156,9 +156,9 @@ pub fn parse_args_config() -> anyhow::Result<Option<(Config, Vec<String>, bool)>
let mut stun_server = matches.opt_strs("e");
if stun_server.is_empty() {
stun_server.push("stun1.l.google.com:19302".to_string());
stun_server.push("stun2.l.google.com:19302".to_string());
stun_server.push("stun.miwifi.com:3478".to_string());
for x in config::PUB_STUN {
stun_server.push(x.to_string());
}
}
let dns = matches.opt_strs("dns");
let in_ip = matches.opt_strs("i");
@@ -340,7 +340,7 @@ fn print_usage(program: &str, _opts: Options) {
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip,注意不能重复");
println!(" -s <server> 注册和中继服务器地址,以'TXT:'开头表示解析TXT记录");
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可使用多个地址,如-e stun1.l.google.com -e stun2.l.google.com");
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可使用多个地址,如-e stun.miwifi.com -e turn.cloudflare.com");
#[cfg(target_os = "windows")]
#[cfg(feature = "integrated_tun")]
println!(
+6 -6
View File
@@ -2,8 +2,8 @@ use anyhow::anyhow;
use std::net::Ipv4Addr;
use std::str::FromStr;
use crate::args_parse;
use crate::config::get_device_id;
use crate::{args_parse, config};
use serde::{Deserialize, Serialize};
use vnt::channel::punch::PunchModel;
use vnt::channel::UseChannelType;
@@ -49,6 +49,10 @@ pub struct FileConfig {
impl Default for FileConfig {
fn default() -> Self {
let mut stun_server = Vec::new();
for x in config::PUB_STUN {
stun_server.push(x.to_string());
}
Self {
#[cfg(target_os = "windows")]
tap: false,
@@ -59,11 +63,7 @@ impl Default for FileConfig {
.unwrap_or("UnknownName")
.to_string(),
server_address: "nat1.wherewego.top:29872".to_string(),
stun_server: vec![
"stun1.l.google.com:19302".to_string(),
"stun2.l.google.com:19302".to_string(),
"stun.miwifi.com:3478".to_string(),
],
stun_server,
dns: vec![],
in_ips: vec![],
out_ips: vec![],
+6
View File
@@ -1,3 +1,9 @@
pub const PUB_STUN: [&'static str; 4] = [
"stun.miwifi.com",
"stun.chat.bilibili.com",
"stun.hitv.com",
"stun.cdnbye.com",
];
#[cfg(feature = "file_config")]
mod file_config;
+54 -9
View File
@@ -8,6 +8,7 @@ use std::time::{Duration, Instant};
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use rand::prelude::SliceRandom;
use rand::Rng;
use crate::channel::punch::{NatInfo, NatType};
@@ -47,12 +48,60 @@ pub fn local_ipv6_() -> io::Result<Ipv6Addr> {
pub fn local_ipv6() -> Option<Ipv6Addr> {
match local_ipv6_() {
Ok(ipv6) => Some(ipv6),
Ok(ipv6) => {
if is_ipv6_global(&ipv6) {
return Some(ipv6);
}
}
Err(e) => {
log::warn!("获取ipv6失败:{:?}", e);
None
}
}
None
}
pub const fn is_ipv4_global(ipv4: &Ipv4Addr) -> bool {
!(ipv4.octets()[0] == 0 // "This network"
|| ipv4.is_private()
|| ipv4.octets()[0] == 100 && (ipv4.octets()[1] & 0b1100_0000 == 0b0100_0000)//ipv4.is_shared()
|| ipv4.is_loopback()
|| ipv4.is_link_local()
// addresses reserved for future protocols (`192.0.0.0/24`)
// .9 and .10 are documented as globally reachable so they're excluded
|| (
ipv4.octets()[0] == 192 && ipv4.octets()[1] == 0 && ipv4.octets()[2] == 0
&& ipv4.octets()[3] != 9 && ipv4.octets()[3] != 10
)
|| ipv4.is_documentation()
|| ipv4.octets()[0] == 198 && (ipv4.octets()[1] & 0xfe) == 18//ipv4.is_benchmarking()
|| ipv4.octets()[0] & 240 == 240 && !ipv4.is_broadcast()//ipv4.is_reserved()
|| ipv4.is_broadcast())
}
pub const fn is_ipv6_global(ipv6addr: &Ipv6Addr) -> bool {
!(ipv6addr.is_unspecified()
|| ipv6addr.is_loopback()
// IPv4-mapped Address (`::ffff:0:0/96`)
|| matches!(ipv6addr.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
// IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
|| matches!(ipv6addr.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
// Discard-Only Address Block (`100::/64`)
|| matches!(ipv6addr.segments(), [0x100, 0, 0, 0, _, _, _, _])
// IETF Protocol Assignments (`2001::/23`)
|| (matches!(ipv6addr.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
&& !(
// Port Control Protocol Anycast (`2001:1::1`)
u128::from_be_bytes(ipv6addr.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
// Traversal Using Relays around NAT Anycast (`2001:1::2`)
|| u128::from_be_bytes(ipv6addr.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
// AMT (`2001:3::/32`)
|| matches!(ipv6addr.segments(), [0x2001, 3, _, _, _, _, _, _])
// AS112-v6 (`2001:4:112::/48`)
|| matches!(ipv6addr.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
// ORCHIDv2 (`2001:20::/28`)
|| matches!(ipv6addr.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F)
))
|| (ipv6addr.segments()[0] == 0x2001) && (ipv6addr.segments()[1] == 0xdb8)//ipv6addr.is_documentation()
|| (ipv6addr.segments()[0] & 0xfe00) == 0xfc00//ipv6addr.is_unique_local()
|| (ipv6addr.segments()[0] & 0xffc0) == 0xfe80) //ipv6addr.is_unicast_link_local())
}
#[derive(Clone)]
@@ -92,7 +141,9 @@ impl NatTest {
tcp_port: u16,
) -> NatTest {
if stun_server.len() > 5 {
stun_server.shuffle(&mut rand::thread_rng());
stun_server.truncate(5);
log::info!("stun_server truncate {:?}", stun_server);
}
let ports = vec![0; udp_ports.len()];
let nat_info = NatInfo::new(
@@ -266,13 +317,7 @@ impl NatTest {
}
}
if !check_fail {
let ip = addr.ip();
if !ip.is_multicast()
&& !ip.is_broadcast()
&& !ip.is_unspecified()
&& !ip.is_loopback()
&& !ip.is_private()
{
if is_ipv4_global(addr.ip()) {
if self.update_addr(index, *addr.ip(), addr.port()) {
log::info!("回应地址{:?},来源stun {:?}", addr, source_addr)
}
+7 -11
View File
@@ -9,17 +9,12 @@ use std::net::UdpSocket;
use stun_format::Attr;
pub fn stun_test_nat(stun_servers: Vec<String>) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
let mut th = Vec::new();
for _ in 0..2 {
let stun_servers = stun_servers.clone();
let handle = std::thread::spawn(move || stun_test_nat0(stun_servers));
th.push(handle);
}
let mut nat_type = NatType::Cone;
let mut port_range = 0;
let mut hash_set = HashSet::new();
for x in th {
match x.join().unwrap() {
for _ in 0..2 {
let stun_servers = stun_servers.clone();
match stun_test_nat0(stun_servers) {
Ok((nat_type_t, ip_list_t, port_range_t)) => {
if nat_type_t == NatType::Symmetric {
nat_type = NatType::Symmetric;
@@ -86,13 +81,13 @@ fn test_nat(udp: &UdpSocket, stun_server: &String) -> io::Result<HashSet<SocketA
udp.connect(stun_server)?;
let tid = rand::thread_rng().next_u64() as u128;
let mut addr = HashSet::new();
let (mapped_addr1, changed_addr1) = test_nat_(&udp, true, true, tid)?;
let (mapped_addr1, changed_addr1) = test_nat_(&udp, stun_server, true, true, tid)?;
if mapped_addr1.is_ipv4() {
addr.insert(mapped_addr1);
}
if let Some(changed_addr1) = changed_addr1 {
if udp.connect(changed_addr1).is_ok() {
match test_nat_(&udp, false, false, tid + 1) {
match test_nat_(&udp, stun_server, false, false, tid + 1) {
Ok((mapped_addr2, _)) => {
if mapped_addr2.is_ipv4() {
addr.insert(mapped_addr1);
@@ -116,6 +111,7 @@ fn test_nat(udp: &UdpSocket, stun_server: &String) -> io::Result<HashSet<SocketA
fn test_nat_(
udp: &UdpSocket,
stun_server: &String,
change_ip: bool,
change_port: bool,
tid: u128,
@@ -134,7 +130,7 @@ fn test_nat_(
let (len, _addr) = match udp.recv_from(&mut buf) {
Ok(rs) => rs,
Err(e) => {
log::warn!("stun error {:?}", e);
log::warn!("stun {} error {:?}", stun_server, e);
continue;
}
};