Files
smartdns/rust/crates/rustdns-client/src/resolver_doh.rs
T

76 lines
2.3 KiB
Rust

use crate::ipc_types::{ResolveParams, ResolveResult};
use crate::resolver_udp::decode_answers;
use rustdns_protocol::packet::{DnsPacket, DnsQuestion};
use rustdns_protocol::types::{QClass, QType, EDNS_DO_BIT, FLAG_RD};
use std::time::Duration;
use tracing::debug;
/// Resolve a DNS query via DNS-over-HTTPS (RFC 8484 wire format).
pub async fn resolve_doh(
params: &ResolveParams,
http_client: &reqwest::Client,
) -> Result<ResolveResult, String> {
let qtype = QType::from_str(&params.record_type);
let id: u16 = rand::random();
// Build query packet (same as UDP)
let mut query = DnsPacket::new_query(id);
query.flags = FLAG_RD;
query.questions.push(DnsQuestion {
name: params.name.clone(),
qtype,
qclass: QClass::IN,
});
// Add OPT record with DO bit for DNSSEC
query.additionals.push(rustdns_protocol::packet::DnsRecord {
name: ".".to_string(),
rtype: QType::OPT,
rclass: QClass::from_u16(4096),
ttl: 0,
rdata: vec![],
opt_flags: Some(EDNS_DO_BIT),
});
let query_bytes = query.encode();
let timeout = Duration::from_millis(params.timeout_ms);
let response = http_client
.post(&params.doh_url)
.header("Content-Type", "application/dns-message")
.header("Accept", "application/dns-message")
.body(query_bytes)
.timeout(timeout)
.send()
.await
.map_err(|e| format!("DoH request failed: {}", e))?;
if !response.status().is_success() {
return Err(format!("DoH server returned status {}", response.status()));
}
let response_bytes = response
.bytes()
.await
.map_err(|e| format!("Failed to read DoH response body: {}", e))?;
let dns_response = DnsPacket::parse(&response_bytes)
.map_err(|e| format!("Failed to parse DoH response: {}", e))?;
debug!(
"DoH response: id={}, rcode={}, answers={}, ad={}",
dns_response.id,
dns_response.rcode(),
dns_response.answers.len(),
dns_response.has_ad_flag()
);
let answers = decode_answers(&dns_response.answers, &response_bytes);
Ok(ResolveResult {
answers,
ad_flag: dns_response.has_ad_flag(),
rcode: dns_response.rcode(),
})
}