dns over tcp

This commit is contained in:
ssrlive 2023-08-21 19:58:13 +08:00
parent 17566451cf
commit 89aeffe195
3 changed files with 40 additions and 0 deletions

View file

@ -98,6 +98,7 @@ impl std::fmt::Display for ProxyType {
pub struct Options { pub struct Options {
virtual_dns: Option<virtdns::VirtualDns>, virtual_dns: Option<virtdns::VirtualDns>,
mtu: Option<usize>, mtu: Option<usize>,
dns_over_tcp: bool,
} }
impl Options { impl Options {
@ -107,6 +108,13 @@ impl Options {
pub fn with_virtual_dns(mut self) -> Self { pub fn with_virtual_dns(mut self) -> Self {
self.virtual_dns = Some(virtdns::VirtualDns::new()); self.virtual_dns = Some(virtdns::VirtualDns::new());
self.dns_over_tcp = false;
self
}
pub fn with_dns_over_tcp(mut self) -> Self {
self.dns_over_tcp = true;
self.virtual_dns = None;
self self
} }

View file

@ -40,6 +40,10 @@ struct Args {
/// Verbosity level /// Verbosity level
#[arg(short, long, value_name = "level", value_enum, default_value = "info")] #[arg(short, long, value_name = "level", value_enum, default_value = "info")]
verbosity: ArgVerbosity, verbosity: ArgVerbosity,
/// DNS over TCP
#[arg(long)]
dns_over_tcp: bool,
} }
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
@ -79,6 +83,10 @@ fn main() -> ExitCode {
options = options.with_virtual_dns(); options = options.with_virtual_dns();
} }
if args.dns_over_tcp {
options = options.with_dns_over_tcp();
}
let interface = match args.tun_fd { let interface = match args.tun_fd {
None => NetworkInterface::Named(args.tun.clone()), None => NetworkInterface::Named(args.tun.clone()),
Some(fd) => { Some(fd) => {

View file

@ -527,6 +527,30 @@ impl<'a> TunToProxy<'a> {
self.send_udp_packet_to_client(origin_dst, connection_info.src, response.as_slice())?; self.send_udp_packet_to_client(origin_dst, connection_info.src, response.as_slice())?;
} else { } else {
// Another UDP packet // Another UDP packet
if self.options.dns_over_tcp && port == DNS_PORT {
if !self.connection_map.contains_key(&connection_info) {
log::info!("DNS over TCP {} ({})", connection_info, origin_dst);
let tcp_proxy_handler = manager.new_tcp_proxy(&connection_info, false)?;
#[rustfmt::skip]
let state = self.create_new_tcp_connection_state(server_addr, origin_dst, tcp_proxy_handler, false)?;
self.connection_map.insert(connection_info.clone(), state);
} else {
log::trace!("Subsequent dns over tcp packet {} ({})", connection_info, origin_dst);
}
let len = payload.len() as u16;
let mut buf = Vec::with_capacity(2 + len as usize);
buf.extend_from_slice(&len.to_be_bytes());
buf.extend_from_slice(payload);
// TODO: Build an IP packet and inject it into the device.
self.device.inject_packet(&buf);
self.expect_smoltcp_send()?;
self.tunsocket_read_and_forward(&connection_info)?;
self.write_to_server(&connection_info)?;
return Ok(());
}
if !self.connection_map.contains_key(&connection_info) { if !self.connection_map.contains_key(&connection_info) {
log::info!("UDP associate session {} ({})", connection_info, origin_dst); log::info!("UDP associate session {} ({})", connection_info, origin_dst);
let tcp_proxy_handler = manager.new_tcp_proxy(&connection_info, true)?; let tcp_proxy_handler = manager.new_tcp_proxy(&connection_info, true)?;