支持指定dns

This commit is contained in:
lbl8603
2024-04-23 08:21:01 +08:00
parent 12d4fc8e98
commit 5b40a9f147
10 changed files with 118 additions and 137 deletions
+1
View File
@@ -92,6 +92,7 @@ impl Vnt {
config.server_encrypt,
config.device_id.clone(),
config.server_address_str.clone(),
config.name_servers.clone(),
);
let ports = config.ports.as_ref().map_or(vec![0, 0], |v| {
if v.is_empty() {
+24 -12
View File
@@ -1,12 +1,13 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use anyhow::anyhow;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::str::FromStr;
pub use conn::Vnt;
use crate::channel::punch::PunchModel;
use crate::channel::UseChannelType;
use crate::cipher::CipherModel;
use crate::util::RecordPriority;
use crate::util::{address_choose, dns_query_all};
mod conn;
@@ -17,9 +18,9 @@ pub struct Config {
pub token: String,
pub device_id: String,
pub name: String,
pub server_address: SocketAddr,
pub server_address_str: String,
pub name_servers:Vec<SocketAddr>,
pub record_priority:RecordPriority,
pub name_servers: Vec<String>,
pub stun_server: Vec<String>,
pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
pub out_ips: Vec<(u32, u32)>,
@@ -51,8 +52,7 @@ impl Config {
device_id: String,
name: String,
server_address_str: String,
name_servers:Vec<SocketAddr>,
record_priority:RecordPriority,
mut name_servers: Vec<String>,
mut stun_server: Vec<String>,
in_ips: Vec<(u32, u32, Ipv4Addr)>,
out_ips: Vec<(u32, u32)>,
@@ -72,30 +72,42 @@ impl Config {
use_channel_type: UseChannelType,
packet_loss_rate: Option<f64>,
packet_delay: u32,
) -> io::Result<Self> {
) -> anyhow::Result<Self> {
for x in stun_server.iter_mut() {
if !x.contains(":") {
x.push_str(":3478");
}
}
for x in name_servers.iter_mut() {
if Ipv6Addr::from_str(x).is_ok() {
x.push_str(":53");
} else if !x.contains(":") {
x.push_str(":53");
}
}
if token.is_empty() || token.len() > 128 {
return Err(io::Error::new(io::ErrorKind::Other, "token too long"));
return Err(anyhow!("token too long"));
}
if device_id.is_empty() || device_id.len() > 128 {
return Err(io::Error::new(io::ErrorKind::Other, "device_id too long"));
return Err(anyhow!("device_id too long"));
}
if name.is_empty() || name.len() > 128 {
return Err(io::Error::new(io::ErrorKind::Other, "name too long"));
return Err(anyhow!("name too long"));
}
if name_servers.is_empty() {
name_servers.push("8.8.8.8:53".to_string());
}
let server_address =
address_choose(dns_query_all(&server_address_str, name_servers.clone())?)?;
Ok(Self {
#[cfg(any(target_os = "windows", target_os = "linux"))]
tap,
token,
device_id,
name,
server_address,
server_address_str,
name_servers,
record_priority,
stun_server,
in_ips,
out_ips,
+28 -25
View File
@@ -1,5 +1,5 @@
use std::io;
use std::net::{SocketAddr, ToSocketAddrs};
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;
@@ -12,7 +12,7 @@ use crate::channel::sender::AcceptSocketSender;
use crate::handle::callback::{ConnectInfo, ErrorType};
use crate::handle::handshaker::Handshake;
use crate::handle::{BaseConfigInfo, ConnectStatus, CurrentDeviceInfo};
use crate::util::{dns_query_all, Scheduler};
use crate::util::{address_choose, dns_query_all, Scheduler};
use crate::{ErrorInfo, VntCallback};
pub fn idle_route<Call: VntCallback>(
@@ -164,32 +164,35 @@ pub fn domain_request0(
let mut current_dev = current_device.load();
// 探测服务端地址变化
match dns_query_all(&config.server_addr,config.name_servers.clone()) {
Ok(mut addrs) => {
for x in &addrs {
//选出一个能用的地址
if x.is_ipv4(){
}
todo!()
match dns_query_all(&config.server_addr, config.name_servers.clone()) {
Ok(addrs) => {
log::info!(
"domain {} dns {:?} addr {:?}",
config.server_addr,
config.name_servers,
addrs
);
}
if let Some(addr) = addrs.pop() {
if addr != current_dev.connect_server {
let mut tmp = current_dev.clone();
tmp.connect_server = addr;
let rs = current_device.compare_exchange(current_dev, tmp);
log::info!(
"服务端地址变化,旧地址:{},新地址:{},替换结果:{}",
current_dev.connect_server,
addr,
rs.is_ok()
);
if rs.is_ok() {
current_dev.connect_server = addr;
match address_choose(addrs) {
Ok(addr) => {
if addr != current_dev.connect_server {
let mut tmp = current_dev.clone();
tmp.connect_server = addr;
let rs = current_device.compare_exchange(current_dev, tmp);
log::info!(
"服务端地址变化,旧地址:{},新地址:{},替换结果:{}",
current_dev.connect_server,
addr,
rs.is_ok()
);
if rs.is_ok() {
current_dev.connect_server = addr;
}
}
}
} else {
log::error!("域名解析值为空,domain={}", config.server_addr);
Err(e) => {
log::error!("域名地址选择失败:{:?},domain={}", e, config.server_addr);
}
}
}
Err(e) => {
+2 -2
View File
@@ -62,7 +62,7 @@ pub struct BaseConfigInfo {
pub server_secret: bool,
pub device_id: String,
pub server_addr: String,
pub name_servers:Vec<SocketAddr>,
pub name_servers: Vec<String>,
}
impl BaseConfigInfo {
@@ -74,7 +74,7 @@ impl BaseConfigInfo {
server_secret: bool,
device_id: String,
server_addr: String,
name_servers:Vec<SocketAddr>,
name_servers: Vec<String>,
) -> Self {
Self {
name,
+43 -40
View File
@@ -1,38 +1,40 @@
use std::{io, thread};
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket};
use std::str::FromStr;
use std::time::Duration;
use std::{io, thread};
use anyhow::Context;
use trust_dns_proto::op::{Edns, Message, MessageType, OpCode, Query};
use trust_dns_proto::rr::{Name, RecordType};
use trust_dns_proto::xfer::DnsRequestOptions;
/// 解析记录优先级
pub enum RecordPriority{
Ipv4,
Ipv6,
}
impl FromStr for RecordPriority {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().trim() {
"ipv4" => Ok(RecordPriority::Ipv4),
"ipv6" => Ok(RecordPriority::Ipv6),
_ => Err(format!("not match '{}', enum: ipv4/ipv6", s)),
/// 后续实现选择延迟最低的可用地址,需要服务端配合
/// 现在是选择第一个地址,优先ipv6
pub fn address_choose(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
let v4: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv4()).map(|v| *v).collect();
let v6: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv6()).map(|v| *v).collect();
let check_addr = |addrs: &Vec<SocketAddr>| -> anyhow::Result<SocketAddr> {
if !addrs.is_empty() {
let udp = if addrs[0].is_ipv6() {
UdpSocket::bind("[::]:0")?
} else {
UdpSocket::bind("0.0.0.0:0")?
};
for addr in addrs {
if udp.connect(addr).is_ok() {
return Ok(*addr);
}
}
}
Err(anyhow::anyhow!("not connect address"))
};
if let Ok(addr) = check_addr(&v6) {
return Ok(addr);
}
check_addr(&v4)
}
impl Default for RecordPriority {
fn default() -> Self {
RecordPriority::Ipv6
}
}
pub fn dns_query_all(
domain: &str,
name_servers: Vec<SocketAddr>,
) -> anyhow::Result<Vec<SocketAddr>> {
pub fn dns_query_all(domain: &str, name_servers: Vec<String>) -> anyhow::Result<Vec<SocketAddr>> {
match SocketAddr::from_str(domain) {
Ok(addr) => {
return Ok(vec![addr]);
@@ -43,7 +45,7 @@ pub fn dns_query_all(
}
let mut err: Option<anyhow::Error> = None;
for name_server in name_servers {
if let Some(domain) = domain.strip_prefix("txt:") {
if let Some(domain) = domain.to_lowercase().strip_prefix("txt:") {
return txt_dns(domain, name_server);
}
let end_index = domain
@@ -54,10 +56,12 @@ pub fn dns_query_all(
.with_context(|| format!("{:?} not port", domain))?;
let th1 = {
let host = host.to_string();
let name_server = name_server.clone();
thread::spawn(move || a_dns(host, name_server))
};
let th2 = {
let host = host.to_string();
let name_server = name_server.clone();
thread::spawn(move || aaaa_dns(host, name_server))
};
let mut addr = Vec::new();
@@ -68,7 +72,7 @@ pub fn dns_query_all(
}
}
Err(e) => {
err.replace(anyhow::anyhow!("{}",e));
err.replace(anyhow::anyhow!("{}", e));
}
}
match th2.join().unwrap() {
@@ -80,9 +84,9 @@ pub fn dns_query_all(
Err(e) => {
if addr.is_empty() {
if let Some(err) = &mut err {
*err = anyhow::anyhow!("{},{}",err,e);
*err = anyhow::anyhow!("{},{}", err, e);
} else {
err.replace(anyhow::anyhow!("{}",e));
err.replace(anyhow::anyhow!("{}", e));
}
continue;
}
@@ -102,10 +106,6 @@ pub fn dns_query_all(
}
}
pub fn dns_query(domain: &str, name_server: SocketAddr) -> anyhow::Result<Vec<SocketAddr>> {
dns_query_all(domain, vec![name_server])
}
fn query(
udp: &UdpSocket,
domain: &str,
@@ -120,7 +120,7 @@ fn query(
let request = request.to_vec()?;
udp.connect(name_server)
.with_context(|| format!("name server {:?} error ", name_server));
.with_context(|| format!("name server {:?} error ", name_server))?;
let mut count = 0;
let mut buf = [0; 65536];
let len = loop {
@@ -150,8 +150,9 @@ fn query(
Ok(message)
}
pub fn txt_dns(domain: &str, name_server: SocketAddr) -> anyhow::Result<Vec<SocketAddr>> {
let udp = bind_udp(name_server.is_ipv4())?;
pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAddr>> {
let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?;
let message = query(&udp, domain, name_server, RecordType::TXT)?;
let mut rs = Vec::new();
for record in message.answers() {
@@ -166,8 +167,8 @@ pub fn txt_dns(domain: &str, name_server: SocketAddr) -> anyhow::Result<Vec<Sock
Ok(rs)
}
fn bind_udp(is_ipv4: bool) -> io::Result<UdpSocket> {
let udp = if is_ipv4 {
fn bind_udp(name_server: SocketAddr) -> anyhow::Result<UdpSocket> {
let udp = if name_server.is_ipv4() {
UdpSocket::bind("0.0.0.0:0")?
} else {
UdpSocket::bind("[::]:0")?
@@ -176,8 +177,9 @@ fn bind_udp(is_ipv4: bool) -> io::Result<UdpSocket> {
Ok(udp)
}
pub fn a_dns(domain: String, name_server: SocketAddr) -> anyhow::Result<Vec<Ipv4Addr>> {
let udp = bind_udp(name_server.is_ipv4())?;
pub fn a_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv4Addr>> {
let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?;
let message = query(&udp, &domain, name_server, RecordType::A)?;
let mut rs = Vec::new();
for record in message.answers() {
@@ -191,8 +193,9 @@ pub fn a_dns(domain: String, name_server: SocketAddr) -> anyhow::Result<Vec<Ipv4
Ok(rs)
}
pub fn aaaa_dns(domain: String, name_server: SocketAddr) -> anyhow::Result<Vec<Ipv6Addr>> {
let udp = bind_udp(name_server.is_ipv4())?;
pub fn aaaa_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv6Addr>> {
let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?;
let message = query(&udp, &domain, name_server, RecordType::AAAA)?;
let mut rs = Vec::new();
for record in message.answers() {