mirror of
https://github.com/tun2proxy/tun2proxy.git
synced 2025-06-07 15:17:43 +00:00
commit
9ad22fc419
2 changed files with 44 additions and 5 deletions
25
src/dns.rs
25
src/dns.rs
|
@ -1,6 +1,9 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::{net::IpAddr, str::FromStr};
|
use std::{
|
||||||
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
use trust_dns_proto::{
|
use trust_dns_proto::{
|
||||||
op::{Message, ResponseCode},
|
op::{Message, ResponseCode},
|
||||||
rr::{record_type::RecordType, Name, RData, Record},
|
rr::{record_type::RecordType, Name, RData, Record},
|
||||||
|
@ -47,6 +50,12 @@ pub fn build_dns_response(mut request: Message, domain: &str, ip: IpAddr, ttl: u
|
||||||
Ok(request)
|
Ok(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_ipv6_entries(message: &mut Message) {
|
||||||
|
message
|
||||||
|
.answers_mut()
|
||||||
|
.retain(|answer| !matches!(answer.data(), Some(RData::AAAA(_))));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn extract_ipaddr_from_dns_message(message: &Message) -> Result<IpAddr, String> {
|
pub fn extract_ipaddr_from_dns_message(message: &Message) -> Result<IpAddr, String> {
|
||||||
if message.response_code() != ResponseCode::NoError {
|
if message.response_code() != ResponseCode::NoError {
|
||||||
return Err(format!("{:?}", message.response_code()));
|
return Err(format!("{:?}", message.response_code()));
|
||||||
|
@ -90,3 +99,17 @@ pub fn parse_data_to_dns_message(data: &[u8], used_by_tcp: bool) -> Result<Messa
|
||||||
let message = Message::from_vec(data).map_err(|e| e.to_string())?;
|
let message = Message::from_vec(data).map_err(|e| e.to_string())?;
|
||||||
Ok(message)
|
Ok(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: use IpAddr::is_global() instead when it's stable
|
||||||
|
pub fn addr_is_private(addr: &SocketAddr) -> bool {
|
||||||
|
fn is_benchmarking(addr: &Ipv4Addr) -> bool {
|
||||||
|
addr.octets()[0] == 198 && (addr.octets()[1] & 0xfe) == 18
|
||||||
|
}
|
||||||
|
fn addr_v4_is_private(addr: &Ipv4Addr) -> bool {
|
||||||
|
is_benchmarking(addr) || addr.is_private() || addr.is_loopback() || addr.is_link_local()
|
||||||
|
}
|
||||||
|
match addr {
|
||||||
|
SocketAddr::V4(addr) => addr_v4_is_private(addr.ip()),
|
||||||
|
SocketAddr::V6(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{error::Error, error::Result, virtdevice::VirtualTunDevice, NetworkInterface, Options};
|
use crate::{dns, error::Error, error::Result, virtdevice::VirtualTunDevice, NetworkInterface, Options};
|
||||||
use mio::{event::Event, net::TcpStream, net::UdpSocket, unix::SourceFd, Events, Interest, Poll, Token};
|
use mio::{event::Event, net::TcpStream, net::UdpSocket, unix::SourceFd, Events, Interest, Poll, Token};
|
||||||
use smoltcp::{
|
use smoltcp::{
|
||||||
iface::{Config, Interface, SocketHandle, SocketSet},
|
iface::{Config, Interface, SocketHandle, SocketSet},
|
||||||
|
@ -468,7 +468,15 @@ impl<'a> TunToProxy<'a> {
|
||||||
let (info, _first_packet, payload_offset, payload_size) = result?;
|
let (info, _first_packet, payload_offset, payload_size) = result?;
|
||||||
let origin_dst = SocketAddr::try_from(&info.dst)?;
|
let origin_dst = SocketAddr::try_from(&info.dst)?;
|
||||||
let connection_info = match &mut self.options.virtual_dns {
|
let connection_info = match &mut self.options.virtual_dns {
|
||||||
None => info,
|
None => {
|
||||||
|
let mut info = info;
|
||||||
|
let port = origin_dst.port();
|
||||||
|
if port == 53 && info.protocol == IpProtocol::Udp && dns::addr_is_private(&origin_dst) {
|
||||||
|
let dns_addr: SocketAddr = "8.8.8.8:53".parse()?; // TODO: Configurable
|
||||||
|
info.dst = Address::from(dns_addr);
|
||||||
|
}
|
||||||
|
info
|
||||||
|
}
|
||||||
Some(virtual_dns) => {
|
Some(virtual_dns) => {
|
||||||
let dst_ip = origin_dst.ip();
|
let dst_ip = origin_dst.ip();
|
||||||
virtual_dns.touch_ip(&dst_ip);
|
virtual_dns.touch_ip(&dst_ip);
|
||||||
|
@ -763,9 +771,17 @@ impl<'a> TunToProxy<'a> {
|
||||||
let buf = buf[..packet_size].to_vec();
|
let buf = buf[..packet_size].to_vec();
|
||||||
let header = UdpHeader::retrieve_from_stream(&mut &buf[..])?;
|
let header = UdpHeader::retrieve_from_stream(&mut &buf[..])?;
|
||||||
|
|
||||||
|
let buf = if info.dst.port() == 53 {
|
||||||
|
let mut message = dns::parse_data_to_dns_message(&buf[header.len()..], false)?;
|
||||||
|
dns::remove_ipv6_entries(&mut message); // TODO: Configurable
|
||||||
|
message.to_vec()?
|
||||||
|
} else {
|
||||||
|
buf[header.len()..].to_vec()
|
||||||
|
};
|
||||||
|
|
||||||
// Write to client
|
// Write to client
|
||||||
let src = state.udp_origin_dst.ok_or("udp address")?;
|
let src = state.udp_origin_dst.ok_or("udp address")?;
|
||||||
self.send_udp_packet_to_client(src, info.src, &buf[header.len()..])?;
|
self.send_udp_packet_to_client(src, info.src, &buf)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -798,7 +814,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
Ok(read_result) => read_result,
|
Ok(read_result) => read_result,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
if error.kind() != std::io::ErrorKind::WouldBlock {
|
if error.kind() != std::io::ErrorKind::WouldBlock {
|
||||||
log::error!("Read from proxy: {}", error);
|
log::error!("{} Read from proxy: {}", conn_info.dst, error);
|
||||||
}
|
}
|
||||||
vecbuf.len()
|
vecbuf.len()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue