From 8d408bbe769dfcde7327b458bfd6ec737b7a71ab Mon Sep 17 00:00:00 2001 From: Elvis Gallagher Date: Mon, 1 Aug 2022 14:36:58 +0000 Subject: [PATCH] Cleaning and update --- .gitignore | 3 +- CHANGELOG.md | 12 ++ Cargo.toml | 13 +- src/http.rs | 65 +++++----- src/main.rs | 62 ++++----- src/socks5.rs | 58 +++++---- src/tun2proxy.rs | 313 ++++++++++++++++++++++++---------------------- src/virtdevice.rs | 21 ++-- 8 files changed, 295 insertions(+), 252 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.gitignore b/.gitignore index 4b664f2..96ef6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /target -/.idea -/*.iml +Cargo.lock diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..fa6f162 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog for Tun2Proxy + +## 0.1.1 + +- Updated dependencies: + - `chrono`: v0.4, ready for next planned release ; + - `clap`: last version ; + - `mio`: v0.8 + rename renamed feature (os-util became os-ext) + some fixes due to removal of `TcpSocket` type ; + - `smoltcp`: set v0.8 but from crates.io, plus old reference could not work. +- Fixes: + - Removed typo from Cargo.toml ; + - Clippy. diff --git a/Cargo.toml b/Cargo.toml index cb20b62..efc702c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,11 @@ [package] -name = "tun2proxy" -version = "0.1.0" authors = ["B. Blechschmidt"] edition = "2018" - +name = "tun2proxy" +version = "0.1.1" [dependencies] -smoltcp = { version="0.8.0", git="https://github.com/smoltcp-rs/smoltcp", features = ["std"], rev="cb1828cbe6d19b10cb50d3e4323fa8c5ca25e5e4" } -mio = { version="0.7", features = ["os-poll", "net", "os-util"]} -clap = { version = "2.33.3" } -chrono = {version = "" } \ No newline at end of file +chrono = "0.4" +clap = "3.2" +mio = { version = "0.8", features = ["os-poll", "net", "os-ext"] } +smoltcp = { version = "0.8", features = ["std"] } diff --git a/src/http.rs b/src/http.rs index f5268eb..14c6c17 100644 --- a/src/http.rs +++ b/src/http.rs @@ -1,4 +1,7 @@ -use crate::tun2proxy::{Connection, TcpProxy, IncomingDirection, OutgoingDirection, OutgoingDataEvent, IncomingDataEvent, ConnectionManager, ProxyError}; +use crate::tun2proxy::{ + Connection, ConnectionManager, IncomingDataEvent, IncomingDirection, OutgoingDataEvent, + OutgoingDirection, ProxyError, TcpProxy, +}; use std::collections::VecDeque; use std::net::SocketAddr; @@ -8,7 +11,7 @@ enum HttpState { SendRequest, ExpectStatusCode, ExpectResponse, - Established + Established, } pub struct HttpConnection { @@ -18,7 +21,7 @@ pub struct HttpConnection { client_outbuf: VecDeque, server_outbuf: VecDeque, data_buf: VecDeque, - crlf_state: u8 + crlf_state: u8, } impl HttpConnection { @@ -30,14 +33,17 @@ impl HttpConnection { client_outbuf: Default::default(), server_outbuf: Default::default(), data_buf: Default::default(), - crlf_state: Default::default() + crlf_state: Default::default(), }; - result.server_outbuf.extend(b"CONNECT ".iter()); - result.server_outbuf.extend(connection.dst.to_string().as_bytes()); + result + .server_outbuf + .extend(connection.dst.to_string().as_bytes()); result.server_outbuf.extend(b" HTTP/1.1\r\nHost: ".iter()); - result.server_outbuf.extend(connection.dst.to_string().as_bytes()); + result + .server_outbuf + .extend(connection.dst.to_string().as_bytes()); result.server_outbuf.extend(b"\r\n\r\n".iter()); result @@ -46,12 +52,22 @@ impl HttpConnection { fn state_change(&mut self) -> Result<(), ProxyError> { match self.state { HttpState::ExpectStatusCode if self.server_inbuf.len() >= "HTTP/1.1 200 ".len() => { - let status_line: Vec = self.server_inbuf.range(0.."HTTP/1.1 200 ".len()).map(|&x| x).collect(); + let status_line: Vec = self + .server_inbuf + .range(0.."HTTP/1.1 200 ".len()) + .copied() + .collect(); let slice = &status_line.as_slice()[0.."HTTP/1.1 2".len()]; if slice != b"HTTP/1.1 2" && slice != b"HTTP/1.0 2" - || self.server_inbuf["HTTP/1.1 200 ".len() - 1] != b' '{ - let status_str = String::from_utf8_lossy(&status_line.as_slice()[0.."HTTP/1.1 200".len()]); - return Err(ProxyError::new("Expected success status code. Server replied with ".to_owned() + &*status_str + ".")); + || self.server_inbuf["HTTP/1.1 200 ".len() - 1] != b' ' + { + let status_str = + String::from_utf8_lossy(&status_line.as_slice()[0.."HTTP/1.1 200".len()]); + return Err(ProxyError::new( + "Expected success status code. Server replied with ".to_owned() + + &*status_str + + ".", + )); } self.state = HttpState::ExpectResponse; return self.state_change(); @@ -86,14 +102,12 @@ impl HttpConnection { self.server_inbuf.clear(); self.client_inbuf.clear(); } - _ => { - } + _ => {} } Ok(()) } } - impl TcpProxy for HttpConnection { fn push_data(&mut self, event: IncomingDataEvent<'_>) -> Result<(), ProxyError> { let direction = event.direction; @@ -101,7 +115,7 @@ impl TcpProxy for HttpConnection { match direction { IncomingDirection::FromServer => { self.server_inbuf.extend(buffer.iter()); - }, + } IncomingDirection::FromClient => { if self.state == HttpState::Established { self.client_inbuf.extend(buffer.iter()); @@ -112,12 +126,10 @@ impl TcpProxy for HttpConnection { } self.state_change() - } fn consume_data(&mut self, dir: OutgoingDirection, size: usize) { - let buffer = if dir == OutgoingDirection::ToServer - { + let buffer = if dir == OutgoingDirection::ToServer { &mut self.server_outbuf } else { &mut self.client_outbuf @@ -131,15 +143,14 @@ impl TcpProxy for HttpConnection { } else { &mut self.client_outbuf }; - let event = OutgoingDataEvent { + OutgoingDataEvent { direction: dir, - buffer: buffer.make_contiguous() - }; - return event; + buffer: buffer.make_contiguous(), + } } fn connection_established(&self) -> bool { - return self.state == HttpState::Established + self.state == HttpState::Established } } @@ -156,7 +167,7 @@ impl ConnectionManager for HttpManager { if connection.proto != smoltcp::wire::IpProtocol::Tcp.into() { return None; } - Some(std::boxed::Box::new(HttpConnection::new(&connection))) + Some(std::boxed::Box::new(HttpConnection::new(connection))) } fn close_connection(&mut self, _: &Connection) {} @@ -168,8 +179,6 @@ impl ConnectionManager for HttpManager { impl HttpManager { pub fn new(server: SocketAddr) -> Self { - Self { - server, - } + Self { server } } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 14a3401..4f04c8a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,43 +1,45 @@ -#![feature(deque_make_contiguous)] -#![feature(deque_range)] - -mod virtdevice; -mod socks5; mod http; +mod socks5; mod tun2proxy; +mod virtdevice; -use socks5::*; use crate::http::HttpManager; use crate::tun2proxy::TunToProxy; +use socks5::*; use std::net::ToSocketAddrs; fn main() { let matches = clap::App::new(env!("CARGO_PKG_NAME")) .version(env!("CARGO_PKG_VERSION")) .about("Tunnel interface to proxy.") - .arg(clap::Arg::with_name("tun") - .short("t") - .long("tun") - .value_name("TUN") - .help("Name of the tun interface") - .required(true) - .takes_value(true)) - .arg(clap::Arg::with_name("socks5_server") - .help("SOCKS5 server to use") - .short("s") - .long("socks5") - .value_name("IP:PORT")) - .arg(clap::Arg::with_name("http_server") - .help("HTTP server to use") - .short("h") - .long("http") - .value_name("IP:PORT")) + .arg( + clap::Arg::with_name("tun") + .short('t') + .long("tun") + .value_name("TUN") + .help("Name of the tun interface") + .required(true) + .takes_value(true), + ) + .arg( + clap::Arg::with_name("socks5_server") + .help("SOCKS5 server to use") + .short('s') + .long("socks5") + .value_name("IP:PORT"), + ) + .arg( + clap::Arg::with_name("http_server") + .help("HTTP server to use") + .short('h') + .long("http") + .value_name("IP:PORT"), + ) .get_matches(); - if matches.value_of("socks5_server").is_some() - && matches.value_of("http_server").is_some() - || matches.value_of("socks5_server").is_none() - && matches.value_of("http_server").is_none() { + if matches.value_of("socks5_server").is_some() && matches.value_of("http_server").is_some() + || matches.value_of("socks5_server").is_none() && matches.value_of("http_server").is_none() + { eprintln!("You need to specify exactly one server."); return; } @@ -45,8 +47,7 @@ fn main() { let tun_name = matches.value_of("tun").unwrap(); let mut ttp = TunToProxy::new(tun_name); if let Some(addr) = matches.value_of("socks5_server") { - if let Ok(mut servers) = addr.to_socket_addrs() - { + if let Ok(mut servers) = addr.to_socket_addrs() { let server = servers.next().unwrap(); println!("SOCKS5 server: {}", server); ttp.add_connection_manager(Box::new(Socks5Manager::new(server))); @@ -57,8 +58,7 @@ fn main() { } if let Some(addr) = matches.value_of("http_server") { - if let Ok(mut servers) = addr.to_socket_addrs() - { + if let Ok(mut servers) = addr.to_socket_addrs() { let server = servers.next().unwrap(); println!("HTTP server: {}", server); ttp.add_connection_manager(Box::new(HttpManager::new(server))); diff --git a/src/socks5.rs b/src/socks5.rs index bbae431..1006750 100644 --- a/src/socks5.rs +++ b/src/socks5.rs @@ -1,4 +1,7 @@ -use crate::tun2proxy::{Connection, OutgoingDirection, OutgoingDataEvent, IncomingDirection, IncomingDataEvent, ConnectionManager, TcpProxy, ProxyError}; +use crate::tun2proxy::{ + Connection, ConnectionManager, IncomingDataEvent, IncomingDirection, OutgoingDataEvent, + OutgoingDirection, ProxyError, TcpProxy, +}; use std::collections::VecDeque; use std::net::{IpAddr, SocketAddr}; @@ -9,7 +12,7 @@ enum SocksState { ServerHello, SendRequest, ReceiveResponse, - Established + Established, } #[allow(dead_code)] @@ -18,14 +21,14 @@ enum SocksState { enum SocksAddressType { Ipv4 = 1, DomainName = 3, - Ipv6 = 4 + Ipv6 = 4, } #[allow(dead_code)] #[repr(u8)] enum SocksAuthentication { None = 0, - Password = 2 + Password = 2, } #[allow(dead_code)] @@ -39,7 +42,7 @@ enum SocksReplies { ConnectionRefused, TtlExpired, CommandUnsupported, - AddressUnsupported + AddressUnsupported, } impl std::fmt::Display for SocksReplies { @@ -77,20 +80,20 @@ impl SocksConnection { pub fn state_change(&mut self) -> Result<(), ProxyError> { let dst_ip = self.connection.dst.ip(); - match self.state { SocksState::ServerHello if self.server_inbuf.len() >= 2 => { if self.server_inbuf[0] != 5 { return Err(ProxyError::new( - "SOCKS server replied with an unexpected version.".into())); + "SOCKS server replied with an unexpected version.".into(), + )); } if self.server_inbuf[1] != 0 { return Err(ProxyError::new( - "SOCKS server requires an unsupported authentication method.".into())); + "SOCKS server requires an unsupported authentication method.".into(), + )); } - self.server_inbuf.drain(0..2); let cmd = if dst_ip.is_ipv4() { 1 } else { 4 }; @@ -101,7 +104,7 @@ impl SocksConnection { }; self.server_outbuf.extend(&[ (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; @@ -115,7 +118,9 @@ impl SocksConnection { let atyp = self.server_inbuf[3]; if ver != 5 { - return Err(ProxyError::new("SOCKS server replied with an unexpected version.".into())); + return Err(ProxyError::new( + "SOCKS server replied with an unexpected version.".into(), + )); } if rep != 0 { @@ -124,8 +129,11 @@ impl SocksConnection { if atyp != SocksAddressType::Ipv4 as u8 && atyp != SocksAddressType::Ipv6 as u8 - && atyp != SocksAddressType::DomainName as u8 { - return Err(ProxyError::new("SOCKS server replied with unrecognized address type.".into())); + && atyp != SocksAddressType::DomainName as u8 + { + return Err(ProxyError::new( + "SOCKS server replied with unrecognized address type.".into(), + )); } if atyp == SocksAddressType::DomainName as u8 && self.server_inbuf.len() < 5 { @@ -133,7 +141,8 @@ impl SocksConnection { } if atyp == SocksAddressType::DomainName as u8 - && self.server_inbuf.len() < 7 + (self.server_inbuf[4] as usize) { + && self.server_inbuf.len() < 7 + (self.server_inbuf[4] as usize) + { return Ok(()); } @@ -173,7 +182,7 @@ impl TcpProxy for SocksConnection { match direction { IncomingDirection::FromServer => { self.server_inbuf.extend(buffer.iter()); - }, + } IncomingDirection::FromClient => { if self.state == SocksState::Established { self.client_inbuf.extend(buffer.iter()); @@ -184,12 +193,10 @@ impl TcpProxy for SocksConnection { } self.state_change() - } fn consume_data(&mut self, dir: OutgoingDirection, size: usize) { - let buffer = if dir == OutgoingDirection::ToServer - { + let buffer = if dir == OutgoingDirection::ToServer { &mut self.server_outbuf } else { &mut self.client_outbuf @@ -203,15 +210,14 @@ impl TcpProxy for SocksConnection { } else { &mut self.client_outbuf }; - let event = OutgoingDataEvent { + OutgoingDataEvent { direction: dir, - buffer: buffer.make_contiguous() - }; - return event; + buffer: buffer.make_contiguous(), + } } fn connection_established(&self) -> bool { - return self.state == SocksState::Established + self.state == SocksState::Established } } @@ -231,7 +237,7 @@ impl ConnectionManager for Socks5Manager { if connection.proto != smoltcp::wire::IpProtocol::Tcp.into() { return None; } - Some(std::boxed::Box::new(SocksConnection::new(&connection))) + Some(std::boxed::Box::new(SocksConnection::new(connection))) } fn close_connection(&mut self, _: &Connection) {} @@ -247,7 +253,7 @@ impl Socks5Manager { server, authentication: SocksAuthentication::None, username: Default::default(), - password: Default::default() + password: Default::default(), } } @@ -258,4 +264,4 @@ impl Socks5Manager { self.username = Vec::from(username); self.password = Vec::from(password); } -} \ No newline at end of file +} diff --git a/src/tun2proxy.rs b/src/tun2proxy.rs index c72b45c..e127b55 100644 --- a/src/tun2proxy.rs +++ b/src/tun2proxy.rs @@ -1,30 +1,27 @@ +use crate::virtdevice::VirtualTunDevice; +use mio::event::Event; +use mio::net::TcpStream; +use mio::unix::SourceFd; +use mio::{Events, Interest, Poll, Token}; +use smoltcp::iface::{Interface, InterfaceBuilder, Routes, SocketHandle}; +use smoltcp::phy::{Device, Medium, RxToken, TunTapInterface, TxToken}; +use smoltcp::socket::{TcpSocket, TcpSocketBuffer}; +use smoltcp::time::Instant; +use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Packet, Ipv6Packet, TcpPacket, UdpPacket}; use std::collections::{BTreeMap, HashMap}; use std::convert::From; use std::io::{Read, Write}; -use std::net::{IpAddr, SocketAddr, Shutdown}; +use std::net::Shutdown::Both; +use std::net::{IpAddr, Shutdown, SocketAddr}; use std::os::unix::io::AsRawFd; -use mio::{Events, Interest, Poll, Token}; -use mio::event::Event; -use mio::net::{TcpSocket as MioTcp, TcpStream}; -use mio::unix::SourceFd; -use smoltcp::iface::{Interface, InterfaceBuilder, Routes}; -use smoltcp::phy::{Device, Medium, RxToken, TunTapInterface, TxToken}; -use smoltcp::socket::{SocketHandle, SocketSet, TcpSocket, TcpSocketBuffer}; -use smoltcp::time::Instant; -use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Packet, TcpPacket, UdpPacket, Ipv6Packet}; -use crate::virtdevice::VirtualTunDevice; -use std::net::Shutdown::Both; - pub struct ProxyError { - message: String + message: String, } impl ProxyError { pub fn new(message: String) -> Self { - Self { - message - } + Self { message } } pub fn message(&self) -> String { @@ -32,11 +29,11 @@ impl ProxyError { } } -#[derive(Hash, Clone, Copy)] +#[derive(Hash, Clone, Copy, Eq, PartialEq)] pub struct Connection { pub src: std::net::SocketAddr, pub dst: std::net::SocketAddr, - pub proto: u8 + pub proto: u8, } impl std::fmt::Display for Connection { @@ -45,93 +42,92 @@ impl std::fmt::Display for Connection { } } -impl Eq for Connection {} - -impl PartialEq for Connection { - fn eq(&self, other: &Self) -> bool { - return other.src == self.src && other.dst == self.dst && other.proto == self.proto; - } -} - #[derive(Eq, PartialEq, Debug)] pub(crate) enum IncomingDirection { FromServer, - FromClient + FromClient, } #[derive(Eq, PartialEq, Debug)] pub(crate) enum OutgoingDirection { ToServer, - ToClient + ToClient, } #[allow(dead_code)] pub(crate) enum ConnectionEvent<'a> { NewConnection(&'a Connection), - ConnectionClosed(&'a Connection) + ConnectionClosed(&'a Connection), } pub(crate) struct DataEvent<'a, T> { pub(crate) direction: T, - pub(crate) buffer: &'a [u8] + pub(crate) buffer: &'a [u8], } pub(crate) type IncomingDataEvent<'a> = DataEvent<'a, IncomingDirection>; pub(crate) type OutgoingDataEvent<'a> = DataEvent<'a, OutgoingDirection>; -fn get_transport_info(proto: u8, transport_offset: usize, packet: &[u8]) -> Option<((u16, u16), bool, usize, usize)> { +fn get_transport_info( + proto: u8, + transport_offset: usize, + packet: &[u8], +) -> Option<((u16, u16), bool, usize, usize)> { if proto == smoltcp::wire::IpProtocol::Udp.into() { match UdpPacket::new_checked(packet) { - Ok(result) => { - Some(((result.src_port(), result.dst_port()), false, transport_offset + 8, packet.len() - 8)) - }, - Err(_) => None + Ok(result) => Some(( + (result.src_port(), result.dst_port()), + false, + transport_offset + 8, + packet.len() - 8, + )), + Err(_) => None, } } else if proto == smoltcp::wire::IpProtocol::Tcp.into() { match TcpPacket::new_checked(packet) { - Ok(result) => { - Some(((result.src_port(), result.dst_port()), result.syn() && !result.ack(), - transport_offset + result.header_len() as usize, packet.len())) - }, - Err(_) => None + Ok(result) => Some(( + (result.src_port(), result.dst_port()), + result.syn() && !result.ack(), + transport_offset + result.header_len() as usize, + packet.len(), + )), + Err(_) => None, } - } - else { + } else { None } } fn connection_tuple(frame: &[u8]) -> Option<(Connection, bool, usize, usize)> { - match Ipv4Packet::new_checked(frame) { - Ok(packet) => { - let proto:u8 = packet.protocol().into(); + if let Ok(packet) = Ipv4Packet::new_checked(frame) { + let proto: u8 = packet.protocol().into(); - let mut a: [u8; 4] = Default::default(); - a.copy_from_slice(packet.src_addr().as_bytes()); - let src_addr = IpAddr::from(a); - a.copy_from_slice(packet.dst_addr().as_bytes()); - let dst_addr = IpAddr::from(a); - - if let Some((ports, first_packet, payload_offset, payload_size)) - = get_transport_info(proto,packet.header_len().into(), &frame[packet.header_len().into()..]) { - let connection = Connection { - src: SocketAddr::new(src_addr, ports.0), - dst: SocketAddr::new(dst_addr, ports.1), - proto - }; - return Some((connection, first_packet, payload_offset, payload_size)); - } else { - return None; - } + let mut a: [u8; 4] = Default::default(); + a.copy_from_slice(packet.src_addr().as_bytes()); + let src_addr = IpAddr::from(a); + a.copy_from_slice(packet.dst_addr().as_bytes()); + let dst_addr = IpAddr::from(a); + if let Some((ports, first_packet, payload_offset, payload_size)) = get_transport_info( + proto, + packet.header_len().into(), + &frame[packet.header_len().into()..], + ) { + let connection = Connection { + src: SocketAddr::new(src_addr, ports.0), + dst: SocketAddr::new(dst_addr, ports.1), + proto, + }; + return Some((connection, first_packet, payload_offset, payload_size)); + } else { + return None; } - _ => { } } match Ipv6Packet::new_checked(frame) { Ok(packet) => { // TODO: Support extension headers. - let proto:u8 = packet.next_header().into(); + let proto: u8 = packet.next_header().into(); let mut a: [u8; 16] = Default::default(); a.copy_from_slice(packet.src_addr().as_bytes()); @@ -139,20 +135,20 @@ fn connection_tuple(frame: &[u8]) -> Option<(Connection, bool, usize, usize)> { a.copy_from_slice(packet.dst_addr().as_bytes()); let dst_addr = IpAddr::from(a); - if let Some((ports, first_packet, payload_offset, payload_size)) - = get_transport_info(proto,packet.header_len().into(), &frame[packet.header_len().into()..]) { + if let Some((ports, first_packet, payload_offset, payload_size)) = + get_transport_info(proto, packet.header_len(), &frame[packet.header_len()..]) + { let connection = Connection { src: SocketAddr::new(src_addr, ports.0), dst: SocketAddr::new(dst_addr, ports.1), - proto + proto, }; Some((connection, first_packet, payload_offset, payload_size)) } else { None } - } - _ => None + _ => None, } } @@ -160,7 +156,7 @@ struct ConnectionState { smoltcp_handle: SocketHandle, mio_stream: TcpStream, token: Token, - handler: std::boxed::Box + handler: std::boxed::Box, } pub(crate) trait TcpProxy { @@ -187,30 +183,35 @@ pub(crate) struct TunToProxy<'a> { connection_managers: Vec>, next_token: usize, token_to_connection: HashMap, - socketset: SocketSet<'a> } impl<'a> TunToProxy<'a> { - pub(crate) fn new(interface: &str) -> Self { let tun_token = Token(0); let tun = TunTapInterface::new(interface, Medium::Ip).unwrap(); let poll = Poll::new().unwrap(); - poll.registry().register(&mut SourceFd(&tun.as_raw_fd()), tun_token, Interest::READABLE).unwrap(); + poll.registry() + .register( + &mut SourceFd(&tun.as_raw_fd()), + tun_token, + Interest::READABLE, + ) + .unwrap(); let virt = VirtualTunDevice::new(tun.capabilities()); - let builder = InterfaceBuilder::new(virt); - let ip_addrs = [ - IpCidr::new(IpAddress::v4(0, 0, 0, 1), 0), - ]; + let builder = InterfaceBuilder::new(virt, vec![]); + let ip_addrs = [IpCidr::new(IpAddress::v4(0, 0, 0, 1), 0)]; let mut routes = Routes::new(BTreeMap::new()); - routes.add_default_ipv4_route(Ipv4Address::new(0, 0, 0, 1)).unwrap(); - - - let iface = builder.any_ip(true) - .ip_addrs(ip_addrs).routes(routes).finalize(); + routes + .add_default_ipv4_route(Ipv4Address::new(0, 0, 0, 1)) + .unwrap(); + let iface = builder + .any_ip(true) + .ip_addrs(ip_addrs) + .routes(routes) + .finalize(); Self { tun, @@ -221,8 +222,7 @@ impl<'a> TunToProxy<'a> { connections: Default::default(), next_token: 2, token_to_connection: Default::default(), - socketset: SocketSet::new([]), - connection_managers: Default::default() + connection_managers: Default::default(), } } @@ -231,30 +231,37 @@ impl<'a> TunToProxy<'a> { } fn expect_smoltcp_send(&mut self) { - self.iface.poll(&mut self.socketset, Instant::now()).unwrap(); + self.iface.poll(Instant::now()).unwrap(); while let Some(vec) = self.iface.device_mut().exfiltrate_packet() { let slice = vec.as_slice(); // TODO: Actual write. Replace. - self.tun.transmit().unwrap().consume(Instant::now(), slice.len(), |buf| { - buf[..].clone_from_slice(slice); - Ok(()) - }).unwrap(); + self.tun + .transmit() + .unwrap() + .consume(Instant::now(), slice.len(), |buf| { + buf[..].clone_from_slice(slice); + Ok(()) + }) + .unwrap(); } } fn remove_connection(&mut self, connection: &Connection) { let mut connection_state = self.connections.remove(connection).unwrap(); self.token_to_connection.remove(&connection_state.token); - self.poll.registry().deregister(&mut connection_state.mio_stream).unwrap(); + self.poll + .registry() + .deregister(&mut connection_state.mio_stream) + .unwrap(); println!("[{:?}] CLOSE {}", chrono::offset::Local::now(), connection); } - fn get_connection_manager(&self, connection: &Connection) -> Option<&Box>{ + fn get_connection_manager(&self, connection: &Connection) -> Option<&dyn ConnectionManager> { for manager in self.connection_managers.iter() { if manager.handles_connection(connection) { - return Some(manager); + return Some(manager.as_ref()); } } None @@ -265,46 +272,51 @@ impl<'a> TunToProxy<'a> { } fn tunsocket_read_and_forward(&mut self, connection: &Connection) { - if let Some(state) = self.connections.get_mut(&connection) { + if let Some(state) = self.connections.get_mut(connection) { let closed = { - let mut socket = self.socketset.get::(state.smoltcp_handle); + let socket = self.iface.get_socket::(state.smoltcp_handle); let mut error = Ok(()); while socket.can_recv() && error.is_ok() { - socket.recv(|data| { - let event = IncomingDataEvent { - direction: IncomingDirection::FromClient, - buffer: data, + socket + .recv(|data| { + let event = IncomingDataEvent { + direction: IncomingDirection::FromClient, + buffer: data, + }; + error = state.handler.push_data(event); - }; - error = state.handler.push_data(event); - - (data.len(), ()) - }).unwrap(); + (data.len(), ()) + }) + .unwrap(); } - if error.is_err() { - Self::print_error(error.unwrap_err()); - true - } else { - socket.state() == smoltcp::socket::TcpState::CloseWait + match error { + Ok(_) => socket.state() == smoltcp::socket::TcpState::CloseWait, + Err(e) => { + Self::print_error(e); + true + } } }; if closed { - let connection_state = self.connections.get_mut(&connection).unwrap(); - connection_state.mio_stream.shutdown(Shutdown::Both).unwrap(); - self.remove_connection(&connection); - return; + let connection_state = self.connections.get_mut(connection).unwrap(); + connection_state + .mio_stream + .shutdown(Shutdown::Both) + .unwrap(); + self.remove_connection(connection); } } } fn receive_tun(&mut self, frame: &mut [u8]) { - if let Some((connection, first_packet, _payload_offset, _payload_size)) = connection_tuple(frame) { - + if let Some((connection, first_packet, _payload_offset, _payload_size)) = + connection_tuple(frame) + { if connection.proto == smoltcp::wire::IpProtocol::Tcp.into() { let cm = self.get_connection_manager(&connection); - if !cm.is_some() { + if cm.is_none() { return; } let server = cm.unwrap().get_server(); @@ -313,17 +325,13 @@ impl<'a> TunToProxy<'a> { if let Some(handler) = manager.new_connection(&connection) { let mut socket = TcpSocket::new( TcpSocketBuffer::new(vec![0; 4096]), - TcpSocketBuffer::new(vec![0; 4096])); + TcpSocketBuffer::new(vec![0; 4096]), + ); socket.set_ack_delay(None); socket.listen(connection.dst).unwrap(); - let handle = self.socketset.add(socket); + let handle = self.iface.add_socket(socket); - let socket = if server.is_ipv4() { - MioTcp::new_v4().unwrap() - } else { - MioTcp::new_v6().unwrap() - }; - let client = socket.connect(server).unwrap(); + let client = TcpStream::connect(server).unwrap(); let token = Token(self.next_token); self.next_token += 1; @@ -332,18 +340,26 @@ impl<'a> TunToProxy<'a> { smoltcp_handle: handle, mio_stream: client, token, - handler + handler, }; self.token_to_connection.insert(token, connection); - self.poll.registry().register(&mut state.mio_stream, token, Interest::READABLE | Interest::WRITABLE).unwrap(); + self.poll + .registry() + .register( + &mut state.mio_stream, + token, + Interest::READABLE | Interest::WRITABLE, + ) + .unwrap(); self.connections.insert(connection, state); - - - - println!("[{:?}] CONNECT {}", chrono::offset::Local::now(), connection); + println!( + "[{:?}] CONNECT {}", + chrono::offset::Local::now(), + connection + ); break; } } @@ -365,8 +381,7 @@ impl<'a> TunToProxy<'a> { // The connection handler builds up the connection or encapsulates the data. // Therefore, we now expect it to write data to the server. self.write_to_server(&connection); - } - else if connection.proto == smoltcp::wire::IpProtocol::Udp.into() { + } else if connection.proto == smoltcp::wire::IpProtocol::Udp.into() { /* // UDP is not yet supported. if payload_offset > frame.len() || payload_offset + payload_offset > frame.len() { return; @@ -377,17 +392,19 @@ impl<'a> TunToProxy<'a> { } fn write_to_server(&mut self, connection: &Connection) { - if let Some(state) = self.connections.get_mut(&connection) { + if let Some(state) = self.connections.get_mut(connection) { let event = state.handler.peek_data(OutgoingDirection::ToServer); - if event.buffer.len() == 0 { + if event.buffer.is_empty() { return; } let result = state.mio_stream.write(event.buffer); match result { Ok(consumed) => { - state.handler.consume_data(OutgoingDirection::ToServer, consumed); + state + .handler + .consume_data(OutgoingDirection::ToServer, consumed); } - Err(error) if error.kind() != std::io::ErrorKind::WouldBlock => { + Err(error) if error.kind() != std::io::ErrorKind::WouldBlock => { panic!("Error: {:?}", error); } _ => { @@ -398,12 +415,14 @@ impl<'a> TunToProxy<'a> { } fn write_to_client(&mut self, connection: &Connection) { - if let Some(state) = self.connections.get_mut(&connection) { + if let Some(state) = self.connections.get_mut(connection) { let event = state.handler.peek_data(OutgoingDirection::ToClient); - let socket = &mut self.socketset.get::(state.smoltcp_handle); + let socket = &mut self.iface.get_socket::(state.smoltcp_handle); if socket.may_send() { let consumed = socket.send_slice(event.buffer).unwrap(); - state.handler.consume_data(OutgoingDirection::ToClient, consumed); + state + .handler + .consume_data(OutgoingDirection::ToClient, consumed); } } } @@ -433,7 +452,9 @@ impl<'a> TunToProxy<'a> { if read == 0 { { - let mut socket = self.socketset.get::(self.connections.get(&connection).unwrap().smoltcp_handle); + let socket = self.iface.get_socket::( + self.connections.get(&connection).unwrap().smoltcp_handle, + ); socket.close(); } self.expect_smoltcp_send(); @@ -444,12 +465,13 @@ impl<'a> TunToProxy<'a> { let event = IncomingDataEvent { direction: IncomingDirection::FromServer, buffer: &buf[0..read], - }; if let Err(error) = state.handler.push_data(event) { state.mio_stream.shutdown(Both).unwrap(); { - let mut socket = self.socketset.get::(self.connections.get(&connection).unwrap().smoltcp_handle); + let socket = self.iface.get_socket::( + self.connections.get(&connection).unwrap().smoltcp_handle, + ); socket.close(); } self.expect_smoltcp_send(); @@ -471,12 +493,9 @@ impl<'a> TunToProxy<'a> { } } - fn udp_event(&mut self, _event: &Event) { - - } + fn udp_event(&mut self, _event: &Event) {} pub(crate) fn run(&mut self) { - let mut events = Events::with_capacity(1024); loop { @@ -492,4 +511,4 @@ impl<'a> TunToProxy<'a> { } } } -} \ No newline at end of file +} diff --git a/src/virtdevice.rs b/src/virtdevice.rs index dfd485f..6811ace 100644 --- a/src/virtdevice.rs +++ b/src/virtdevice.rs @@ -6,17 +6,16 @@ use smoltcp::time::Instant; pub struct VirtualTunDevice { capabilities: DeviceCapabilities, inbuf: Vec>, - outbuf: Vec> + outbuf: Vec>, } - impl VirtualTunDevice { - pub fn inject_packet(self: &mut Self, buffer: &[u8]) { + pub fn inject_packet(&mut self, buffer: &[u8]) { let vec = Vec::from(buffer); self.inbuf.push(vec); } - pub fn exfiltrate_packet(self: &mut Self, ) -> Option> { + pub fn exfiltrate_packet(&mut self) -> Option> { self.outbuf.pop() } } @@ -27,8 +26,8 @@ pub struct VirtRxToken { impl phy::RxToken for VirtRxToken { fn consume(mut self, _timestamp: Instant, f: F) -> smoltcp::Result - where - F: FnOnce(&mut [u8]) -> smoltcp::Result, + where + F: FnOnce(&mut [u8]) -> smoltcp::Result, { f(&mut self.buffer[..]) } @@ -38,12 +37,12 @@ pub struct VirtTxToken<'a>(&'a mut VirtualTunDevice); impl<'a> phy::TxToken for VirtTxToken<'a> { fn consume(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result - where - F: FnOnce(&mut [u8]) -> smoltcp::Result, + where + F: FnOnce(&mut [u8]) -> smoltcp::Result, { let mut buffer = vec![0; len]; let result = f(&mut buffer); - self.0.outbuf.push(Vec::from(buffer)); + self.0.outbuf.push(buffer); result } } @@ -70,11 +69,11 @@ impl<'a> Device<'a> for VirtualTunDevice { } } -impl<'a> VirtualTunDevice { +impl VirtualTunDevice { pub fn new(capabilities: DeviceCapabilities) -> Self { Self { capabilities, ..Default::default() } } -} \ No newline at end of file +}