Browse Source

Merge branch 'ssrlive' into dns-robustness

pull/13/head
B. Blechschmidt 3 years ago
parent
commit
3de8b992d4
  1. 22
      src/http.rs
  2. 4
      src/lib.rs
  3. 24
      src/socks5.rs
  4. 81
      src/tun2proxy.rs

22
src/http.rs

@ -4,8 +4,10 @@ use crate::tun2proxy::{
OutgoingDataEvent, OutgoingDirection, TcpProxy, OutgoingDataEvent, OutgoingDirection, TcpProxy,
}; };
use base64::Engine; use base64::Engine;
use smoltcp::wire::IpProtocol;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::rc::Rc;
#[derive(Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug)]
#[allow(dead_code)] #[allow(dead_code)]
@ -27,7 +29,7 @@ pub struct HttpConnection {
} }
impl HttpConnection { impl HttpConnection {
fn new(connection: &Connection, manager: std::rc::Rc<dyn ConnectionManager>) -> Self { fn new(connection: &Connection, manager: Rc<dyn ConnectionManager>) -> Self {
let mut server_outbuf: VecDeque<u8> = VecDeque::new(); let mut server_outbuf: VecDeque<u8> = VecDeque::new();
{ {
let credentials = manager.get_credentials(); let credentials = manager.get_credentials();
@ -163,26 +165,24 @@ impl TcpProxy for HttpConnection {
} }
pub struct HttpManager { pub struct HttpManager {
server: std::net::SocketAddr, server: SocketAddr,
credentials: Option<Credentials>, credentials: Option<Credentials>,
} }
impl ConnectionManager for HttpManager { impl ConnectionManager for HttpManager {
fn handles_connection(&self, connection: &Connection) -> bool { fn handles_connection(&self, connection: &Connection) -> bool {
connection.proto == smoltcp::wire::IpProtocol::Tcp.into() connection.proto == IpProtocol::Tcp.into()
} }
fn new_connection( fn new_connection(
&self, &self,
connection: &Connection, connection: &Connection,
manager: std::rc::Rc<dyn ConnectionManager>, manager: Rc<dyn ConnectionManager>,
) -> Option<std::boxed::Box<dyn TcpProxy>> { ) -> Option<Box<dyn TcpProxy>> {
if connection.proto != smoltcp::wire::IpProtocol::Tcp.into() { if connection.proto != IpProtocol::Tcp.into() {
return None; return None;
} }
Some(std::boxed::Box::new(HttpConnection::new( Some(Box::new(HttpConnection::new(connection, manager)))
connection, manager,
)))
} }
fn close_connection(&self, _: &Connection) {} fn close_connection(&self, _: &Connection) {}
@ -197,8 +197,8 @@ impl ConnectionManager for HttpManager {
} }
impl HttpManager { impl HttpManager {
pub fn new(server: SocketAddr, credentials: Option<Credentials>) -> std::rc::Rc<Self> { pub fn new(server: SocketAddr, credentials: Option<Credentials>) -> Rc<Self> {
std::rc::Rc::new(Self { Rc::new(Self {
server, server,
credentials, credentials,
}) })

4
src/lib.rs

@ -86,5 +86,7 @@ pub fn main_entry(tun: &str, proxy: Proxy, options: Options) {
ttp.add_connection_manager(HttpManager::new(proxy.addr, proxy.credentials)); ttp.add_connection_manager(HttpManager::new(proxy.addr, proxy.credentials));
} }
} }
ttp.run(); if let Err(e) = ttp.run() {
log::error!("{e}");
}
} }

24
src/socks5.rs

@ -3,8 +3,10 @@ use crate::tun2proxy::{
Connection, ConnectionManager, Credentials, DestinationHost, IncomingDataEvent, Connection, ConnectionManager, Credentials, DestinationHost, IncomingDataEvent,
IncomingDirection, OutgoingDataEvent, OutgoingDirection, TcpProxy, IncomingDirection, OutgoingDataEvent, OutgoingDirection, TcpProxy,
}; };
use smoltcp::wire::IpProtocol;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::net::{IpAddr, SocketAddr}; use std::net::{IpAddr, SocketAddr};
use std::rc::Rc;
#[derive(Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug)]
#[allow(dead_code)] #[allow(dead_code)]
@ -60,11 +62,11 @@ pub(crate) struct SocksConnection {
client_outbuf: VecDeque<u8>, client_outbuf: VecDeque<u8>,
server_outbuf: VecDeque<u8>, server_outbuf: VecDeque<u8>,
data_buf: VecDeque<u8>, data_buf: VecDeque<u8>,
manager: std::rc::Rc<dyn ConnectionManager>, manager: Rc<dyn ConnectionManager>,
} }
impl SocksConnection { impl SocksConnection {
pub fn new(connection: &Connection, manager: std::rc::Rc<dyn ConnectionManager>) -> Self { pub fn new(connection: &Connection, manager: Rc<dyn ConnectionManager>) -> Self {
let mut result = Self { let mut result = Self {
connection: connection.clone(), connection: connection.clone(),
state: SocksState::ServerHello, state: SocksState::ServerHello,
@ -291,26 +293,24 @@ impl TcpProxy for SocksConnection {
} }
pub struct Socks5Manager { pub struct Socks5Manager {
server: std::net::SocketAddr, server: SocketAddr,
credentials: Option<Credentials>, credentials: Option<Credentials>,
} }
impl ConnectionManager for Socks5Manager { impl ConnectionManager for Socks5Manager {
fn handles_connection(&self, connection: &Connection) -> bool { fn handles_connection(&self, connection: &Connection) -> bool {
connection.proto == smoltcp::wire::IpProtocol::Tcp.into() connection.proto == IpProtocol::Tcp.into()
} }
fn new_connection( fn new_connection(
&self, &self,
connection: &Connection, connection: &Connection,
manager: std::rc::Rc<dyn ConnectionManager>, manager: Rc<dyn ConnectionManager>,
) -> Option<std::boxed::Box<dyn TcpProxy>> { ) -> Option<Box<dyn TcpProxy>> {
if connection.proto != smoltcp::wire::IpProtocol::Tcp.into() { if connection.proto != IpProtocol::Tcp.into() {
return None; return None;
} }
Some(std::boxed::Box::new(SocksConnection::new( Some(Box::new(SocksConnection::new(connection, manager)))
connection, manager,
)))
} }
fn close_connection(&self, _: &Connection) {} fn close_connection(&self, _: &Connection) {}
@ -325,8 +325,8 @@ impl ConnectionManager for Socks5Manager {
} }
impl Socks5Manager { impl Socks5Manager {
pub fn new(server: SocketAddr, credentials: Option<Credentials>) -> std::rc::Rc<Self> { pub fn new(server: SocketAddr, credentials: Option<Credentials>) -> Rc<Self> {
std::rc::Rc::new(Self { Rc::new(Self {
server, server,
credentials, credentials,
}) })

81
src/tun2proxy.rs

@ -12,15 +12,17 @@ use smoltcp::phy::{Device, Medium, RxToken, TunTapInterface, TxToken};
use smoltcp::socket::tcp; use smoltcp::socket::tcp;
use smoltcp::time::Instant; use smoltcp::time::Instant;
use smoltcp::wire::{ use smoltcp::wire::{
IpAddress, IpCidr, Ipv4Address, Ipv4Packet, Ipv6Address, Ipv6Packet, TcpPacket, UdpPacket, IpAddress, IpCidr, IpProtocol, Ipv4Address, Ipv4Packet, Ipv6Address, Ipv6Packet, TcpPacket,
UdpPacket,
}; };
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::convert::From; use std::convert::{From, TryFrom};
use std::fmt::{Display, Formatter}; 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;
use std::rc::Rc;
#[derive(Hash, Clone, Eq, PartialEq)] #[derive(Hash, Clone, Eq, PartialEq)]
pub enum DestinationHost { pub enum DestinationHost {
@ -43,17 +45,18 @@ pub(crate) struct Destination {
pub(crate) port: u16, pub(crate) port: u16,
} }
impl From<Destination> for SocketAddr { impl TryFrom<Destination> for SocketAddr {
fn from(value: Destination) -> Self { type Error = Error;
SocketAddr::new( fn try_from(value: Destination) -> Result<Self, Self::Error> {
Ok(SocketAddr::new(
match value.host { match value.host {
DestinationHost::Address(addr) => addr, DestinationHost::Address(addr) => addr,
DestinationHost::Hostname(_) => { DestinationHost::Hostname(e) => {
panic!("Failed to convert hostname destination into socket address") return Err(e.into());
} }
}, },
value.port, value.port,
) ))
} }
} }
@ -94,8 +97,8 @@ impl Display for Destination {
} }
#[derive(Hash, Clone, Eq, PartialEq)] #[derive(Hash, Clone, Eq, PartialEq)]
pub struct Connection { pub(crate) struct Connection {
pub(crate) src: std::net::SocketAddr, pub(crate) src: SocketAddr,
pub(crate) dst: Destination, pub(crate) dst: Destination,
pub(crate) proto: u8, pub(crate) proto: u8,
} }
@ -145,7 +148,7 @@ fn get_transport_info(
transport_offset: usize, transport_offset: usize,
packet: &[u8], packet: &[u8],
) -> Option<((u16, u16), bool, usize, usize)> { ) -> Option<((u16, u16), bool, usize, usize)> {
if proto == smoltcp::wire::IpProtocol::Udp.into() { if proto == IpProtocol::Udp.into() {
match UdpPacket::new_checked(packet) { match UdpPacket::new_checked(packet) {
Ok(result) => Some(( Ok(result) => Some((
(result.src_port(), result.dst_port()), (result.src_port(), result.dst_port()),
@ -155,7 +158,7 @@ fn get_transport_info(
)), )),
Err(_) => None, Err(_) => None,
} }
} else if proto == smoltcp::wire::IpProtocol::Tcp.into() { } else if proto == IpProtocol::Tcp.into() {
match TcpPacket::new_checked(packet) { match TcpPacket::new_checked(packet) {
Ok(result) => Some(( Ok(result) => Some((
(result.src_port(), result.dst_port()), (result.src_port(), result.dst_port()),
@ -230,7 +233,7 @@ struct ConnectionState {
smoltcp_handle: SocketHandle, smoltcp_handle: SocketHandle,
mio_stream: TcpStream, mio_stream: TcpStream,
token: Token, token: Token,
handler: std::boxed::Box<dyn TcpProxy>, handler: Box<dyn TcpProxy>,
smoltcp_socket_state: u8, smoltcp_socket_state: u8,
} }
@ -261,8 +264,8 @@ pub(crate) trait ConnectionManager {
fn new_connection( fn new_connection(
&self, &self,
connection: &Connection, connection: &Connection,
manager: std::rc::Rc<dyn ConnectionManager>, manager: Rc<dyn ConnectionManager>,
) -> Option<std::boxed::Box<dyn TcpProxy>>; ) -> Option<Box<dyn TcpProxy>>;
fn close_connection(&self, connection: &Connection); fn close_connection(&self, connection: &Connection);
fn get_server(&self) -> SocketAddr; fn get_server(&self) -> SocketAddr;
fn get_credentials(&self) -> &Option<Credentials>; fn get_credentials(&self) -> &Option<Credentials>;
@ -283,15 +286,15 @@ impl Options {
self self
} }
} }
const TCP_TOKEN: Token = Token(0);
const UDP_TOKEN: Token = Token(1);
pub(crate) struct TunToProxy<'a> { pub(crate) struct TunToProxy<'a> {
tun: TunTapInterface, tun: TunTapInterface,
poll: Poll, poll: Poll,
tun_token: Token,
udp_token: Token,
iface: Interface, iface: Interface,
connections: HashMap<Connection, ConnectionState>, connections: HashMap<Connection, ConnectionState>,
connection_managers: Vec<std::rc::Rc<dyn ConnectionManager>>, connection_managers: Vec<Rc<dyn ConnectionManager>>,
next_token: usize, next_token: usize,
token_to_connection: HashMap<Token, Connection>, token_to_connection: HashMap<Token, Connection>,
sockets: SocketSet<'a>, sockets: SocketSet<'a>,
@ -302,13 +305,12 @@ pub(crate) struct TunToProxy<'a> {
impl<'a> TunToProxy<'a> { impl<'a> TunToProxy<'a> {
pub(crate) fn new(interface: &str, options: Options) -> Self { pub(crate) fn new(interface: &str, options: Options) -> Self {
let tun_token = Token(0);
let tun = TunTapInterface::new(interface, Medium::Ip).unwrap(); let tun = TunTapInterface::new(interface, Medium::Ip).unwrap();
let poll = Poll::new().unwrap(); let poll = Poll::new().unwrap();
poll.registry() poll.registry()
.register( .register(
&mut SourceFd(&tun.as_raw_fd()), &mut SourceFd(&tun.as_raw_fd()),
tun_token, TCP_TOKEN,
Interest::READABLE, Interest::READABLE,
) )
.unwrap(); .unwrap();
@ -337,8 +339,6 @@ impl<'a> TunToProxy<'a> {
Self { Self {
tun, tun,
poll, poll,
tun_token,
udp_token: Token(1),
iface, iface,
connections: Default::default(), connections: Default::default(),
next_token: 2, next_token: 2,
@ -351,7 +351,7 @@ impl<'a> TunToProxy<'a> {
} }
} }
pub(crate) fn add_connection_manager(&mut self, manager: std::rc::Rc<dyn ConnectionManager>) { pub(crate) fn add_connection_manager(&mut self, manager: Rc<dyn ConnectionManager>) {
self.connection_managers.push(manager); self.connection_managers.push(manager);
} }
@ -383,10 +383,7 @@ impl<'a> TunToProxy<'a> {
info!("CLOSE {}", connection); info!("CLOSE {}", connection);
} }
fn get_connection_manager( fn get_connection_manager(&self, connection: &Connection) -> Option<Rc<dyn ConnectionManager>> {
&self,
connection: &Connection,
) -> Option<std::rc::Rc<dyn ConnectionManager>> {
for manager in self.connection_managers.iter() { for manager in self.connection_managers.iter() {
if manager.handles_connection(connection) { if manager.handles_connection(connection) {
return Some(manager.clone()); return Some(manager.clone());
@ -450,7 +447,7 @@ impl<'a> TunToProxy<'a> {
} }
} }
}; };
if resolved_conn.proto == smoltcp::wire::IpProtocol::Tcp.into() { if resolved_conn.proto == IpProtocol::Tcp.into() {
let cm = self.get_connection_manager(&resolved_conn); let cm = self.get_connection_manager(&resolved_conn);
if cm.is_none() { if cm.is_none() {
return; return;
@ -466,10 +463,8 @@ 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);
let dst = connection.dst; let dst = SocketAddr::try_from(connection.dst).unwrap();
socket socket.listen(dst).unwrap();
.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();
@ -520,7 +515,7 @@ impl<'a> TunToProxy<'a> {
// The connection handler builds up the connection or encapsulates the data. // The connection handler builds up the connection or encapsulates the data.
// Therefore, we now expect it to write data to the server. // Therefore, we now expect it to write data to the server.
self.write_to_server(&resolved_conn); self.write_to_server(&resolved_conn);
} else if resolved_conn.proto == smoltcp::wire::IpProtocol::Udp.into() { } else if resolved_conn.proto == IpProtocol::Udp.into() {
if let Some(virtual_dns) = &mut self.options.virtdns { if let Some(virtual_dns) = &mut self.options.virtdns {
let payload = &frame[_payload_offset.._payload_offset + _payload_size]; let payload = &frame[_payload_offset.._payload_offset + _payload_size];
if let Some(response) = virtual_dns.receive_query(payload) { if let Some(response) = virtual_dns.receive_query(payload) {
@ -533,10 +528,8 @@ impl<'a> TunToProxy<'a> {
vec![0; 4096], vec![0; 4096],
); );
let mut socket = smoltcp::socket::udp::Socket::new(rx_buffer, tx_buffer); let mut socket = smoltcp::socket::udp::Socket::new(rx_buffer, tx_buffer);
let dst = resolved_conn.dst.clone(); let dst = SocketAddr::try_from(connection.dst).unwrap();
socket socket.bind(dst).unwrap();
.bind(<Destination as Into<SocketAddr>>::into(dst))
.unwrap();
socket socket
.send_slice(response.as_slice(), resolved_conn.src.into()) .send_slice(response.as_slice(), resolved_conn.src.into())
.expect("failed to send DNS response"); .expect("failed to send DNS response");
@ -700,18 +693,16 @@ impl<'a> TunToProxy<'a> {
fn udp_event(&mut self, _event: &Event) {} fn udp_event(&mut self, _event: &Event) {}
pub(crate) fn run(&mut self) { pub(crate) fn run(&mut self) -> Result<(), Error> {
let mut events = Events::with_capacity(1024); let mut events = Events::with_capacity(1024);
loop { loop {
self.poll.poll(&mut events, None).unwrap(); self.poll.poll(&mut events, None)?;
for event in events.iter() { for event in events.iter() {
if event.token() == self.tun_token { match event.token() {
self.tun_event(event); TCP_TOKEN => self.tun_event(event),
} else if event.token() == self.udp_token { UDP_TOKEN => self.udp_event(event),
self.udp_event(event); _ => self.mio_socket_event(event),
} else {
self.mio_socket_event(event);
} }
} }
self.send_to_smoltcp(); self.send_to_smoltcp();

Loading…
Cancel
Save