mirror of
https://github.com/tun2proxy/tun2proxy.git
synced 2025-04-19 13:29:09 +00:00
Prepare DNS support
This commit is contained in:
parent
ca3aadcf1a
commit
1a5eeece6f
2 changed files with 93 additions and 27 deletions
|
@ -1,7 +1,7 @@
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::tun2proxy::{
|
use crate::tun2proxy::{
|
||||||
Connection, ConnectionManager, Credentials, IncomingDataEvent, IncomingDirection,
|
Connection, ConnectionManager, Credentials, DestinationHost, IncomingDataEvent,
|
||||||
OutgoingDataEvent, OutgoingDirection, TcpProxy,
|
IncomingDirection, OutgoingDataEvent, OutgoingDirection, TcpProxy,
|
||||||
};
|
};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::net::{IpAddr, SocketAddr};
|
use std::net::{IpAddr, SocketAddr};
|
||||||
|
@ -18,7 +18,6 @@ enum SocksState {
|
||||||
Established,
|
Established,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum SocksAddressType {
|
enum SocksAddressType {
|
||||||
|
@ -28,7 +27,6 @@ enum SocksAddressType {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[repr(u8)]
|
|
||||||
enum SocksAuthentication {
|
enum SocksAuthentication {
|
||||||
None = 0,
|
None = 0,
|
||||||
Password = 2,
|
Password = 2,
|
||||||
|
@ -68,7 +66,7 @@ pub(crate) struct SocksConnection {
|
||||||
impl SocksConnection {
|
impl SocksConnection {
|
||||||
pub fn new(connection: &Connection, manager: std::rc::Rc<dyn ConnectionManager>) -> Self {
|
pub fn new(connection: &Connection, manager: std::rc::Rc<dyn ConnectionManager>) -> Self {
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
connection: *connection,
|
connection: connection.clone(),
|
||||||
state: SocksState::ServerHello,
|
state: SocksState::ServerHello,
|
||||||
client_inbuf: Default::default(),
|
client_inbuf: Default::default(),
|
||||||
server_inbuf: Default::default(),
|
server_inbuf: Default::default(),
|
||||||
|
@ -84,9 +82,11 @@ impl SocksConnection {
|
||||||
fn send_client_hello(&mut self) {
|
fn send_client_hello(&mut self) {
|
||||||
let credentials = self.manager.get_credentials();
|
let credentials = self.manager.get_credentials();
|
||||||
if credentials.is_some() {
|
if credentials.is_some() {
|
||||||
self.server_outbuf.extend(&[5u8, 1, 2]);
|
self.server_outbuf
|
||||||
|
.extend(&[5u8, 1, SocksAuthentication::Password as u8]);
|
||||||
} else {
|
} else {
|
||||||
self.server_outbuf.extend(&[5u8, 1, 0]);
|
self.server_outbuf
|
||||||
|
.extend(&[5u8, 1, SocksAuthentication::None as u8]);
|
||||||
}
|
}
|
||||||
self.state = SocksState::ServerHello;
|
self.state = SocksState::ServerHello;
|
||||||
}
|
}
|
||||||
|
@ -191,16 +191,28 @@ impl SocksConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_request(&mut self) -> Result<(), Error> {
|
fn send_request(&mut self) -> Result<(), Error> {
|
||||||
let dst_ip = self.connection.dst.ip();
|
self.server_outbuf.extend(&[5u8, 1, 0]);
|
||||||
let cmd = if dst_ip.is_ipv4() { 1 } else { 4 };
|
match &self.connection.dst.host {
|
||||||
self.server_outbuf.extend(&[5u8, 1, 0, cmd]);
|
DestinationHost::Address(dst_ip) => {
|
||||||
match dst_ip {
|
let cmd = if dst_ip.is_ipv4() {
|
||||||
IpAddr::V4(ip) => self.server_outbuf.extend(ip.octets().as_ref()),
|
SocksAddressType::Ipv4
|
||||||
IpAddr::V6(ip) => self.server_outbuf.extend(ip.octets().as_ref()),
|
} else {
|
||||||
};
|
SocksAddressType::Ipv6
|
||||||
|
};
|
||||||
|
self.server_outbuf.extend(&[cmd as u8]);
|
||||||
|
match dst_ip {
|
||||||
|
IpAddr::V4(ip) => self.server_outbuf.extend(ip.octets().as_ref()),
|
||||||
|
IpAddr::V6(ip) => self.server_outbuf.extend(ip.octets().as_ref()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
DestinationHost::Hostname(_) => {
|
||||||
|
self.server_outbuf
|
||||||
|
.extend(&[SocksAddressType::DomainName as u8]);
|
||||||
|
}
|
||||||
|
}
|
||||||
self.server_outbuf.extend(&[
|
self.server_outbuf.extend(&[
|
||||||
(self.connection.dst.port() >> 8) as u8,
|
(self.connection.dst.port >> 8) as u8,
|
||||||
(self.connection.dst.port() & 0xff) as u8,
|
(self.connection.dst.port & 0xff) as u8,
|
||||||
]);
|
]);
|
||||||
self.state = SocksState::ReceiveResponse;
|
self.state = SocksState::ReceiveResponse;
|
||||||
self.state_change()
|
self.state_change()
|
||||||
|
|
|
@ -14,16 +14,67 @@ use smoltcp::wire::{
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::net::Shutdown::Both;
|
use std::net::Shutdown::Both;
|
||||||
use std::net::{IpAddr, Shutdown, SocketAddr};
|
use std::net::{IpAddr, Shutdown, SocketAddr};
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
#[derive(Hash, Clone, Copy, Eq, PartialEq)]
|
#[derive(Hash, Clone, Eq, PartialEq)]
|
||||||
pub struct Connection {
|
pub enum DestinationHost {
|
||||||
pub src: std::net::SocketAddr,
|
Address(IpAddr),
|
||||||
pub dst: std::net::SocketAddr,
|
Hostname(String),
|
||||||
pub proto: u8,
|
}
|
||||||
|
|
||||||
|
impl ToString for DestinationHost {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
DestinationHost::Address(addr) => addr.to_string(),
|
||||||
|
DestinationHost::Hostname(name) => name.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Hash, Clone, Eq, PartialEq)]
|
||||||
|
pub(crate) struct Destination {
|
||||||
|
pub(crate) host: DestinationHost,
|
||||||
|
pub(crate) port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Destination> for SocketAddr {
|
||||||
|
fn from(value: Destination) -> Self {
|
||||||
|
SocketAddr::new(
|
||||||
|
match value.host {
|
||||||
|
DestinationHost::Address(addr) => addr,
|
||||||
|
DestinationHost::Hostname(_) => {
|
||||||
|
panic!("Failed to convert hostname destination into socket address")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value.port,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SocketAddr> for Destination {
|
||||||
|
fn from(addr: SocketAddr) -> Self {
|
||||||
|
Self {
|
||||||
|
host: DestinationHost::Address(addr.ip()),
|
||||||
|
port: addr.port(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Destination {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}:{}", self.host.to_string(), self.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Hash, Clone, Eq, PartialEq)]
|
||||||
|
pub(crate) struct Connection {
|
||||||
|
pub(crate) src: std::net::SocketAddr,
|
||||||
|
pub(crate) dst: Destination,
|
||||||
|
pub(crate) proto: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Connection {
|
impl std::fmt::Display for Connection {
|
||||||
|
@ -105,7 +156,7 @@ fn connection_tuple(frame: &[u8]) -> Option<(Connection, bool, usize, usize)> {
|
||||||
) {
|
) {
|
||||||
let connection = Connection {
|
let connection = Connection {
|
||||||
src: SocketAddr::new(src_addr, ports.0),
|
src: SocketAddr::new(src_addr, ports.0),
|
||||||
dst: SocketAddr::new(dst_addr, ports.1),
|
dst: SocketAddr::new(dst_addr, ports.1).into(),
|
||||||
proto,
|
proto,
|
||||||
};
|
};
|
||||||
return Some((connection, first_packet, payload_offset, payload_size));
|
return Some((connection, first_packet, payload_offset, payload_size));
|
||||||
|
@ -130,7 +181,7 @@ fn connection_tuple(frame: &[u8]) -> Option<(Connection, bool, usize, usize)> {
|
||||||
{
|
{
|
||||||
let connection = Connection {
|
let connection = Connection {
|
||||||
src: SocketAddr::new(src_addr, ports.0),
|
src: SocketAddr::new(src_addr, ports.0),
|
||||||
dst: SocketAddr::new(dst_addr, ports.1),
|
dst: SocketAddr::new(dst_addr, ports.1).into(),
|
||||||
proto,
|
proto,
|
||||||
};
|
};
|
||||||
Some((connection, first_packet, payload_offset, payload_size))
|
Some((connection, first_packet, payload_offset, payload_size))
|
||||||
|
@ -348,7 +399,10 @@ impl<'a> TunToProxy<'a> {
|
||||||
smoltcp::socket::tcp::SocketBuffer::new(vec![0; 4096]),
|
smoltcp::socket::tcp::SocketBuffer::new(vec![0; 4096]),
|
||||||
);
|
);
|
||||||
socket.set_ack_delay(None);
|
socket.set_ack_delay(None);
|
||||||
socket.listen(connection.dst).unwrap();
|
let dst = connection.dst.clone();
|
||||||
|
socket
|
||||||
|
.listen(<Destination as Into<SocketAddr>>::into(dst))
|
||||||
|
.unwrap();
|
||||||
let handle = self.sockets.add(socket);
|
let handle = self.sockets.add(socket);
|
||||||
|
|
||||||
let client = TcpStream::connect(server).unwrap();
|
let client = TcpStream::connect(server).unwrap();
|
||||||
|
@ -363,7 +417,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
handler,
|
handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.token_to_connection.insert(token, connection);
|
self.token_to_connection.insert(token, connection.clone());
|
||||||
self.poll
|
self.poll
|
||||||
.registry()
|
.registry()
|
||||||
.register(
|
.register(
|
||||||
|
@ -373,7 +427,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
self.connections.insert(connection, state);
|
self.connections.insert(connection.clone(), state);
|
||||||
|
|
||||||
info!("CONNECT {}", connection,);
|
info!("CONNECT {}", connection,);
|
||||||
break;
|
break;
|
||||||
|
@ -456,7 +510,7 @@ impl<'a> TunToProxy<'a> {
|
||||||
|
|
||||||
fn mio_socket_event(&mut self, event: &Event) {
|
fn mio_socket_event(&mut self, event: &Event) {
|
||||||
if let Some(conn_ref) = self.token_to_connection.get(&event.token()) {
|
if let Some(conn_ref) = self.token_to_connection.get(&event.token()) {
|
||||||
let connection = *conn_ref;
|
let connection = conn_ref.clone();
|
||||||
if event.is_readable() {
|
if event.is_readable() {
|
||||||
{
|
{
|
||||||
let state = self.connections.get_mut(&connection).unwrap();
|
let state = self.connections.get_mut(&connection).unwrap();
|
||||||
|
|
Loading…
Add table
Reference in a new issue