trust-dns-proto import

This commit is contained in:
ssrlive 2023-08-06 11:42:19 +08:00
parent 4ebd019cb5
commit 5ce2e85919
4 changed files with 128 additions and 2 deletions

View file

@ -25,6 +25,7 @@ prctl = "1.0"
smoltcp = { version = "0.10.0", features = ["std", "phy-tuntap_interface"] }
socks5-impl = { version = "0.5", default-features = false }
thiserror = "1.0"
trust-dns-proto = "0.22"
unicase = "2.6.0"
url = "2.4"

104
src/dns.rs Normal file
View file

@ -0,0 +1,104 @@
#![allow(dead_code)]
use std::{net::IpAddr, str::FromStr};
use trust_dns_proto::{
op::{Message, ResponseCode},
rr::{record_type::RecordType, Name, RData, Record},
};
#[cfg(feature = "use-rand")]
pub fn build_dns_request(
domain: &str,
query_type: RecordType,
used_by_tcp: bool,
) -> Result<Vec<u8>, String> {
// [dependencies]
// rand = "0.8"
use rand::{rngs::StdRng, Rng, SeedableRng};
use trust_dns_proto::op::{header::MessageType, op_code::OpCode, query::Query};
let name = Name::from_str(domain).map_err(|e| e.to_string())?;
let query = Query::query(name, query_type);
let mut msg = Message::new();
msg.add_query(query)
.set_id(StdRng::from_entropy().gen())
.set_op_code(OpCode::Query)
.set_message_type(MessageType::Query)
.set_recursion_desired(true);
let mut msg_buf = msg.to_vec().map_err(|e| e.to_string())?;
if used_by_tcp {
let mut buf = (msg_buf.len() as u16).to_be_bytes().to_vec();
buf.append(&mut msg_buf);
Ok(buf)
} else {
Ok(msg_buf)
}
}
pub fn build_dns_response(
mut request: Message,
domain: &str,
ip: IpAddr,
ttl: u32,
) -> Result<Message, String> {
let record = match ip {
IpAddr::V4(ip) => {
let mut record = Record::with(Name::from_str(domain)?, RecordType::A, ttl);
record.set_data(Some(RData::A(ip)));
record
}
IpAddr::V6(ip) => {
let mut record = Record::with(Name::from_str(domain)?, RecordType::AAAA, ttl);
record.set_data(Some(RData::AAAA(ip)));
record
}
};
request.add_answer(record);
Ok(request)
}
pub fn extract_ipaddr_from_dns_message(message: &Message) -> Result<IpAddr, String> {
if message.response_code() != ResponseCode::NoError {
return Err(format!("{:?}", message.response_code()));
}
let mut cname = None;
for answer in message.answers() {
match answer
.data()
.ok_or("DNS response not contains answer data")?
{
RData::A(addr) => {
return Ok(IpAddr::V4(*addr));
}
RData::AAAA(addr) => {
return Ok(IpAddr::V6(*addr));
}
RData::CNAME(name) => {
cname = Some(name.to_utf8());
}
_ => {}
}
}
if let Some(cname) = cname {
return Err(cname);
}
Err(format!("{:?}", message.answers()))
}
pub fn extract_domain_from_dns_message(message: &Message) -> Result<String, String> {
let query = message.queries().get(0).ok_or("DnsRequest no query body")?;
let name = query.name().to_string();
Ok(name)
}
pub fn parse_data_to_dns_message(data: &[u8], used_by_tcp: bool) -> Result<Message, String> {
if used_by_tcp {
if data.len() < 2 {
return Err("invalid dns data".into());
}
let len = u16::from_be_bytes([data[0], data[1]]) as usize;
let data = data.get(2..len + 2).ok_or("invalid dns data")?;
return parse_data_to_dns_message(data, false);
}
let message = Message::from_vec(data).map_err(|e| e.to_string())?;
Ok(message)
}

View file

@ -7,6 +7,7 @@ use std::{
use tun2proxy::ConnectionManager;
mod android;
mod dns;
pub mod error;
mod http;
pub mod setup;

View file

@ -8,7 +8,6 @@ use std::{
time::{Duration, Instant},
};
const DNS_TTL: u8 = 30; // TTL in DNS replies in seconds
const MAPPING_TIMEOUT: u64 = 60; // Mapping timeout in seconds
#[derive(Eq, PartialEq, Debug)]
@ -57,6 +56,23 @@ impl VirtualDns {
VirtualDns::default()
}
// /*
pub fn receive_query(&mut self, data: &[u8]) -> Option<Vec<u8>> {
use crate::dns;
let mut dns_block = || {
let message = dns::parse_data_to_dns_message(data, false)?;
let qname = dns::extract_domain_from_dns_message(&message)?;
if let Some(ip) = self.allocate_ip(qname.clone()) {
let message = dns::build_dns_response(message, &qname, ip, 5)?;
message.to_vec()
} else {
Err("Virtual IP space for DNS exhausted".into())
}
};
dns_block().ok()
}
// */
/*
pub fn receive_query(&mut self, data: &[u8]) -> Option<Vec<u8>> {
if data.len() < 17 {
return None;
@ -109,6 +125,8 @@ impl VirtualDns {
response[8] = 0;
response[9] = 0;
const DNS_TTL: u8 = 30; // TTL in DNS replies in seconds
// additional section
response[10] = 0;
response[11] = 0;
@ -138,7 +156,7 @@ impl VirtualDns {
}
Some(response)
}
// */
fn increment_ip(addr: IpAddr) -> Option<IpAddr> {
let mut ip_bytes = match addr as IpAddr {
IpAddr::V4(ip) => Vec::<u8>::from(ip.octets()),
@ -239,6 +257,7 @@ impl VirtualDns {
}
}
/*
/// Parse a non-root DNS qname at a specific offset and return the name along with its size.
/// DNS packet parsing should be continued after the name.
fn parse_qname(data: &[u8], mut offset: usize) -> Option<(String, usize)> {
@ -277,4 +296,5 @@ impl VirtualDns {
Some((qname, offset))
}
// */
}