设置dns
This commit is contained in:
+1
-1
@@ -474,7 +474,7 @@ fn print_usage(program: &str, _opts: Options) {
|
|||||||
println!(
|
println!(
|
||||||
" --packet-delay <0> 模拟延迟,整数,单位毫秒(ms),程序会按设定的值延迟发包,可用于模拟弱网"
|
" --packet-delay <0> 模拟延迟,整数,单位毫秒(ms),程序会按设定的值延迟发包,可用于模拟弱网"
|
||||||
);
|
);
|
||||||
println!(" --dns <host:port> DNS服务器地址,可使用多个dns,默认使用8.8.8.8:53");
|
println!(" --dns <host:port> DNS服务器地址,可使用多个dns,默认使用114.114.114.114和8.8.8.8");
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
println!(
|
println!(
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ libsm = {git="https://github.com/lbl8603/libsm" ,optional = true}
|
|||||||
mio = {version = "0.8.10",features = ["os-poll","net"]}
|
mio = {version = "0.8.10",features = ["os-poll","net"]}
|
||||||
crossbeam-queue = "0.3.11"
|
crossbeam-queue = "0.3.11"
|
||||||
anyhow = "1.0.82"
|
anyhow = "1.0.82"
|
||||||
trust-dns-proto = "0.23.2"
|
dns-parser = "0.8.0"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
libloading = "0.8.0"
|
libloading = "0.8.0"
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ impl Config {
|
|||||||
return Err(anyhow!("name too long"));
|
return Err(anyhow!("name too long"));
|
||||||
}
|
}
|
||||||
if name_servers.is_empty() {
|
if name_servers.is_empty() {
|
||||||
|
name_servers.push("114.114.114.114:53".to_string());
|
||||||
name_servers.push("8.8.8.8:53".to_string());
|
name_servers.push("8.8.8.8:53".to_string());
|
||||||
}
|
}
|
||||||
let server_address =
|
let server_address =
|
||||||
|
|||||||
+55
-70
@@ -4,9 +4,7 @@ use std::time::Duration;
|
|||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use trust_dns_proto::op::{Edns, Message, MessageType, OpCode, Query};
|
use dns_parser::{Builder, Packet, QueryClass, QueryType, RData, ResponseCode};
|
||||||
use trust_dns_proto::rr::{Name, RecordType};
|
|
||||||
use trust_dns_proto::xfer::DnsRequestOptions;
|
|
||||||
|
|
||||||
/// 后续实现选择延迟最低的可用地址,需要服务端配合
|
/// 后续实现选择延迟最低的可用地址,需要服务端配合
|
||||||
/// 现在是选择第一个地址,优先ipv6
|
/// 现在是选择第一个地址,优先ipv6
|
||||||
@@ -26,7 +24,7 @@ pub fn address_choose(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(anyhow::anyhow!("not connect address"))
|
Err(anyhow::anyhow!("Unable to connect to address {:?}", addrs))
|
||||||
};
|
};
|
||||||
if let Ok(addr) = check_addr(&v6) {
|
if let Ok(addr) = check_addr(&v6) {
|
||||||
return Ok(addr);
|
return Ok(addr);
|
||||||
@@ -100,33 +98,30 @@ pub fn dns_query_all(domain: &str, name_servers: Vec<String>) -> anyhow::Result<
|
|||||||
if let Some(e) = err {
|
if let Some(e) = err {
|
||||||
Err(e)
|
Err(e)
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow::anyhow!("dns query failed"))
|
Err(anyhow::anyhow!("DNS query failed"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query(
|
fn query<'a>(
|
||||||
udp: &UdpSocket,
|
udp: &UdpSocket,
|
||||||
domain: &str,
|
domain: &str,
|
||||||
name_server: SocketAddr,
|
name_server: SocketAddr,
|
||||||
record_type: RecordType,
|
record_type: QueryType,
|
||||||
) -> anyhow::Result<Message> {
|
buf: &'a mut [u8],
|
||||||
let name = Name::from_str(domain).context("domain error")?;
|
) -> anyhow::Result<Packet<'a>> {
|
||||||
let query = Query::query(name.clone(), record_type);
|
let mut builder = Builder::new_query(1, true);
|
||||||
let mut options = DnsRequestOptions::default();
|
builder.add_question(domain, false, record_type, QueryClass::IN);
|
||||||
options.use_edns = true;
|
let packet = builder.build().unwrap();
|
||||||
let request = build_message(query, options);
|
|
||||||
|
|
||||||
let request = request.to_vec()?;
|
|
||||||
udp.connect(name_server)
|
udp.connect(name_server)
|
||||||
.with_context(|| format!("name server {:?} error ", name_server))?;
|
.with_context(|| format!("DNS {:?} error ", name_server))?;
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut buf = [0; 65536];
|
|
||||||
let len = loop {
|
let len = loop {
|
||||||
udp.send(&request)?;
|
udp.send(&packet)?;
|
||||||
|
|
||||||
match udp.recv(&mut buf) {
|
match udp.recv(buf) {
|
||||||
Ok(len) => {
|
Ok(len) => {
|
||||||
break len;
|
break len;
|
||||||
}
|
}
|
||||||
@@ -137,32 +132,47 @@ fn query(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e).with_context(|| format!("name server {:?} recv error ", name_server))?
|
Err(e).with_context(|| format!("DNS {:?} recv error ", name_server))?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let message = Message::from_vec(&buf[..len])
|
let pkt = Packet::parse(&buf[..len])
|
||||||
.with_context(|| format!("name server {:?} data error ", name_server))?;
|
.with_context(|| format!("domain {:?} DNS {:?} data error ", domain, name_server))?;
|
||||||
if message.answers().is_empty() {
|
if pkt.header.response_code != ResponseCode::NoError {
|
||||||
Err(anyhow::anyhow!("{:?} no {} record", domain, record_type))?
|
return Err(anyhow::anyhow!(
|
||||||
|
"response_code {} DNS {:?} domain {:?}",
|
||||||
|
pkt.header.response_code,
|
||||||
|
name_server,
|
||||||
|
domain
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Ok(message)
|
if pkt.answers.len() == 0 {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"No records received DNS {:?} domain {:?}",
|
||||||
|
name_server,
|
||||||
|
domain
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAddr>> {
|
pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAddr>> {
|
||||||
let name_server: SocketAddr = name_server.parse()?;
|
let name_server: SocketAddr = name_server.parse()?;
|
||||||
let udp = bind_udp(name_server)?;
|
let udp = bind_udp(name_server)?;
|
||||||
let message = query(&udp, domain, name_server, RecordType::TXT)?;
|
let mut buf = [0; 65536];
|
||||||
|
let message = query(&udp, domain, name_server, QueryType::TXT, &mut buf)?;
|
||||||
let mut rs = Vec::new();
|
let mut rs = Vec::new();
|
||||||
for record in message.answers() {
|
for record in message.answers {
|
||||||
let txt = record
|
if let RData::TXT(txt) = record.data {
|
||||||
.data()
|
for x in txt.iter() {
|
||||||
.context("data none")?
|
let txt = std::str::from_utf8(x).context("record type txt is not string")?;
|
||||||
.as_txt()
|
let addr = SocketAddr::from_str(&txt.to_string())
|
||||||
.context("record type txt is none")?;
|
.context("record type txt is not SocketAddr")?;
|
||||||
let addr = SocketAddr::from_str(&txt.to_string())?;
|
rs.push(addr);
|
||||||
rs.push(addr);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(rs)
|
Ok(rs)
|
||||||
}
|
}
|
||||||
@@ -180,15 +190,13 @@ fn bind_udp(name_server: SocketAddr) -> anyhow::Result<UdpSocket> {
|
|||||||
pub fn a_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv4Addr>> {
|
pub fn a_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv4Addr>> {
|
||||||
let name_server: SocketAddr = name_server.parse()?;
|
let name_server: SocketAddr = name_server.parse()?;
|
||||||
let udp = bind_udp(name_server)?;
|
let udp = bind_udp(name_server)?;
|
||||||
let message = query(&udp, &domain, name_server, RecordType::A)?;
|
let mut buf = [0; 65536];
|
||||||
|
let message = query(&udp, &domain, name_server, QueryType::A, &mut buf)?;
|
||||||
let mut rs = Vec::new();
|
let mut rs = Vec::new();
|
||||||
for record in message.answers() {
|
for record in message.answers {
|
||||||
let a = record
|
if let RData::A(a) = record.data {
|
||||||
.data()
|
rs.push(a.0);
|
||||||
.context("data none")?
|
}
|
||||||
.as_a()
|
|
||||||
.context("record type A is none")?;
|
|
||||||
rs.push(a.0);
|
|
||||||
}
|
}
|
||||||
Ok(rs)
|
Ok(rs)
|
||||||
}
|
}
|
||||||
@@ -196,36 +204,13 @@ pub fn a_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv4Addr
|
|||||||
pub fn aaaa_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv6Addr>> {
|
pub fn aaaa_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv6Addr>> {
|
||||||
let name_server: SocketAddr = name_server.parse()?;
|
let name_server: SocketAddr = name_server.parse()?;
|
||||||
let udp = bind_udp(name_server)?;
|
let udp = bind_udp(name_server)?;
|
||||||
let message = query(&udp, &domain, name_server, RecordType::AAAA)?;
|
let mut buf = [0; 65536];
|
||||||
|
let message = query(&udp, &domain, name_server, QueryType::AAAA, &mut buf)?;
|
||||||
let mut rs = Vec::new();
|
let mut rs = Vec::new();
|
||||||
for record in message.answers() {
|
for record in message.answers {
|
||||||
let a = record
|
if let RData::AAAA(a) = record.data {
|
||||||
.data()
|
rs.push(a.0);
|
||||||
.context("data none")?
|
}
|
||||||
.as_aaaa()
|
|
||||||
.context("record type AAAA is none")?;
|
|
||||||
rs.push(a.0);
|
|
||||||
}
|
}
|
||||||
Ok(rs)
|
Ok(rs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const MAX_PAYLOAD_LEN: u16 = 1232;
|
|
||||||
|
|
||||||
fn build_message(query: Query, options: DnsRequestOptions) -> Message {
|
|
||||||
// build the message
|
|
||||||
let mut message: Message = Message::new();
|
|
||||||
message
|
|
||||||
.add_query(query)
|
|
||||||
.set_message_type(MessageType::Query)
|
|
||||||
.set_op_code(OpCode::Query)
|
|
||||||
.set_recursion_desired(options.recursion_desired);
|
|
||||||
// Extended dns
|
|
||||||
if options.use_edns {
|
|
||||||
message
|
|
||||||
.extensions_mut()
|
|
||||||
.get_or_insert_with(Edns::new)
|
|
||||||
.set_max_payload(MAX_PAYLOAD_LEN)
|
|
||||||
.set_version(0);
|
|
||||||
}
|
|
||||||
message
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user