mirror of
https://github.com/tun2proxy/tun2proxy.git
synced 2025-06-05 06:10:15 +00:00
trust-dns-proto import
This commit is contained in:
parent
4ebd019cb5
commit
5ce2e85919
4 changed files with 128 additions and 2 deletions
|
@ -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
104
src/dns.rs
Normal 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)
|
||||
}
|
|
@ -7,6 +7,7 @@ use std::{
|
|||
use tun2proxy::ConnectionManager;
|
||||
|
||||
mod android;
|
||||
mod dns;
|
||||
pub mod error;
|
||||
mod http;
|
||||
pub mod setup;
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
// */
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue