Merge branch 'blechschmidt:master' into docker_support

This commit is contained in:
Paper-Dragon 2023-09-20 11:10:41 +08:00 committed by GitHub
commit cb20f1b655
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 110 deletions

View file

@ -2,7 +2,7 @@
authors = ["B. Blechschmidt"]
edition = "2021"
name = "tun2proxy"
version = "0.1.6"
version = "0.1.7"
[lib]
crate-type = ["cdylib", "lib"]

View file

@ -406,15 +406,9 @@ impl ConnectionManager for HttpManager {
)?))
}
fn close_connection(&self, _: &ConnectionInfo) {}
fn get_server_addr(&self) -> SocketAddr {
self.server
}
fn get_credentials(&self) -> &Option<UserKey> {
&self.credentials
}
}
impl HttpManager {

View file

@ -4,7 +4,7 @@ use crate::{
socks::SocksProxyManager,
tun2proxy::{ConnectionManager, TunToProxy},
};
use socks5_impl::protocol::{UserKey, Version};
use socks5_impl::protocol::UserKey;
use std::{
net::{SocketAddr, ToSocketAddrs},
rc::Rc,
@ -145,10 +145,10 @@ pub fn tun_to_proxy<'a>(
let mut ttp = TunToProxy::new(interface, options)?;
let credentials = proxy.credentials.clone();
let server = proxy.addr;
#[rustfmt::skip]
use socks5_impl::protocol::Version::{V4, V5};
let mgr = match proxy.proxy_type {
ProxyType::Socks4 => Rc::new(SocksProxyManager::new(server, Version::V4, credentials)) as Rc<dyn ConnectionManager>,
ProxyType::Socks5 => Rc::new(SocksProxyManager::new(server, Version::V5, credentials)) as Rc<dyn ConnectionManager>,
ProxyType::Socks4 => Rc::new(SocksProxyManager::new(server, V4, credentials)) as Rc<dyn ConnectionManager>,
ProxyType::Socks5 => Rc::new(SocksProxyManager::new(server, V5, credentials)) as Rc<dyn ConnectionManager>,
ProxyType::Http => Rc::new(HttpManager::new(server, credentials)) as Rc<dyn ConnectionManager>,
};
ttp.set_connection_manager(Some(mgr));

View file

@ -142,7 +142,7 @@ impl SocksProxyImpl {
let response = handshake::Response::retrieve_from_stream(&mut self.server_inbuf.clone());
if let Err(e) = &response {
if e.kind() == std::io::ErrorKind::UnexpectedEof {
// log::trace!("receive_server_hello_socks5 needs more data \"{}\"...", e);
log::trace!("receive_server_hello_socks5 needs more data \"{}\"...", e);
return Ok(());
} else {
return Err(e.to_string().into());
@ -217,7 +217,7 @@ impl SocksProxyImpl {
let response = protocol::Response::retrieve_from_stream(&mut self.server_inbuf.clone());
if let Err(e) = &response {
if e.kind() == std::io::ErrorKind::UnexpectedEof {
// log::trace!("receive_connection_status needs more data \"{}\"...", e);
log::trace!("receive_connection_status needs more data \"{}\"...", e);
return Ok(());
} else {
return Err(e.to_string().into());
@ -231,7 +231,7 @@ impl SocksProxyImpl {
if self.command == protocol::Command::UdpAssociate {
self.udp_associate = Some(SocketAddr::try_from(&response.address)?);
assert!(self.data_buf.is_empty());
// log::debug!("UDP associate: {}", response.address);
log::trace!("UDP associate recieved address {}", response.address);
}
self.server_outbuf.append(&mut self.data_buf);
@ -274,8 +274,7 @@ impl ProxyHandler for SocksProxyImpl {
}
fn push_data(&mut self, event: IncomingDataEvent<'_>) -> Result<(), Error> {
let direction = event.direction;
let buffer = event.buffer;
let IncomingDataEvent { direction, buffer } = event;
match direction {
IncomingDirection::FromServer => {
self.server_inbuf.extend(buffer.iter());
@ -293,19 +292,17 @@ impl ProxyHandler for SocksProxyImpl {
}
fn consume_data(&mut self, dir: OutgoingDirection, size: usize) {
let buffer = if dir == OutgoingDirection::ToServer {
&mut self.server_outbuf
} else {
&mut self.client_outbuf
let buffer = match dir {
OutgoingDirection::ToServer => &mut self.server_outbuf,
OutgoingDirection::ToClient => &mut self.client_outbuf,
};
buffer.drain(0..size);
}
fn peek_data(&mut self, dir: OutgoingDirection) -> OutgoingDataEvent {
let buffer = if dir == OutgoingDirection::ToServer {
&mut self.server_outbuf
} else {
&mut self.client_outbuf
let buffer = match dir {
OutgoingDirection::ToServer => &mut self.server_outbuf,
OutgoingDirection::ToClient => &mut self.client_outbuf,
};
OutgoingDataEvent {
direction: dir,
@ -353,15 +350,9 @@ impl ConnectionManager for SocksProxyManager {
Ok(Box::new(SocksProxyImpl::new(info, credentials, self.version, command)?))
}
fn close_connection(&self, _: &ConnectionInfo) {}
fn get_server_addr(&self) -> SocketAddr {
self.server
}
fn get_credentials(&self) -> &Option<UserKey> {
&self.credentials
}
}
impl SocksProxyManager {

View file

@ -18,7 +18,7 @@ use smoltcp::{
time::Instant,
wire::{IpCidr, IpProtocol, Ipv4Packet, Ipv6Packet, TcpPacket, UdpPacket, UDP_HEADER_LEN},
};
use socks5_impl::protocol::{Address, StreamOperation, UdpHeader, UserKey};
use socks5_impl::protocol::{Address, StreamOperation, UdpHeader};
use std::collections::LinkedList;
#[cfg(target_family = "unix")]
use std::os::unix::io::AsRawFd;
@ -56,8 +56,7 @@ impl ConnectionInfo {
fn to_named(&self, name: String) -> Self {
let mut result = self.clone();
result.dst = Address::from((name, result.dst.port()));
// let p = self.protocol;
// log::trace!("{p} replace dst \"{}\" -> \"{}\"", self.dst, result.dst);
log::trace!("{} replace dst \"{}\" -> \"{}\"", self.protocol, self.dst, result.dst);
result
}
}
@ -68,31 +67,25 @@ impl std::fmt::Display for ConnectionInfo {
}
}
#[derive(Eq, PartialEq, Debug)]
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub(crate) enum IncomingDirection {
FromServer,
FromClient,
}
#[derive(Eq, PartialEq, Debug)]
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub(crate) enum OutgoingDirection {
ToServer,
ToClient,
}
#[derive(Eq, PartialEq, Debug)]
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub(crate) enum Direction {
Incoming(IncomingDirection),
Outgoing(OutgoingDirection),
}
#[allow(dead_code)]
pub(crate) enum ConnectionEvent<'a> {
NewConnection(&'a ConnectionInfo),
ConnectionClosed(&'a ConnectionInfo),
}
#[derive(Debug)]
#[derive(Clone, Eq, PartialEq, Debug)]
pub(crate) struct DataEvent<'a, T> {
pub(crate) direction: T,
pub(crate) buffer: &'a [u8],
@ -183,17 +176,17 @@ const UDP_ASSO_TIMEOUT: u64 = 10; // seconds
const DNS_PORT: u16 = 53;
struct ConnectionState {
smoltcp_handle: Option<SocketHandle>,
smoltcp_handle: SocketHandle,
mio_stream: TcpStream,
token: Token,
proxy_handler: Box<dyn ProxyHandler>,
close_state: u8,
wait_read: bool,
wait_write: bool,
origin_dst: SocketAddr,
udp_acco_expiry: Option<::std::time::Instant>,
udp_socket: Option<UdpSocket>,
udp_token: Option<Token>,
origin_dst: SocketAddr,
udp_data_cache: LinkedList<Vec<u8>>,
dns_over_tcp_expiry: Option<::std::time::Instant>,
}
@ -211,13 +204,11 @@ pub(crate) trait ProxyHandler {
pub(crate) trait ConnectionManager {
fn new_proxy_handler(&self, info: &ConnectionInfo, udp_associate: bool) -> Result<Box<dyn ProxyHandler>>;
fn close_connection(&self, info: &ConnectionInfo);
fn get_server_addr(&self) -> SocketAddr;
fn get_credentials(&self) -> &Option<UserKey>;
}
const TUN_TOKEN: Token = Token(0);
const EXIT_TOKEN: Token = Token(2);
const EXIT_TOKEN: Token = Token(1);
pub struct TunToProxy<'a> {
#[cfg(any(target_os = "linux", target_os = "android"))]
@ -228,7 +219,7 @@ pub struct TunToProxy<'a> {
iface: Interface,
connection_map: HashMap<ConnectionInfo, ConnectionState>,
connection_manager: Option<Rc<dyn ConnectionManager>>,
next_token: usize,
next_token_seed: usize,
sockets: SocketSet<'a>,
device: VirtualTunDevice,
options: Options,
@ -266,9 +257,8 @@ impl<'a> TunToProxy<'a> {
.register(&mut exit_receiver, EXIT_TOKEN, Interest::READABLE)?;
#[cfg(target_family = "unix")]
#[rustfmt::skip]
let config = match tun.capabilities().medium {
Medium::Ethernet => Config::new(smoltcp::wire::EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]).into()),
Medium::Ethernet => Config::new(smoltcp::wire::EthernetAddress([0x02, 0, 0, 0, 0, 0x01]).into()),
Medium::Ip => Config::new(smoltcp::wire::HardwareAddress::Ip),
Medium::Ieee802154 => todo!(),
};
@ -297,7 +287,7 @@ impl<'a> TunToProxy<'a> {
poll,
iface,
connection_map: HashMap::default(),
next_token: usize::from(EXIT_TOKEN) + 1,
next_token_seed: usize::from(EXIT_TOKEN),
connection_manager: None,
sockets: SocketSet::new([]),
device,
@ -312,9 +302,8 @@ impl<'a> TunToProxy<'a> {
}
fn new_token(&mut self) -> Token {
let token = Token(self.next_token);
self.next_token += 1;
token
self.next_token_seed += 1;
Token(self.next_token_seed)
}
pub(crate) fn set_connection_manager(&mut self, manager: Option<Rc<dyn ConnectionManager>>) {
@ -360,16 +349,15 @@ impl<'a> TunToProxy<'a> {
/// Destroy connection state machine
fn remove_connection(&mut self, info: &ConnectionInfo) -> Result<(), Error> {
if let Some(mut state) = self.connection_map.remove(info) {
_ = state.mio_stream.shutdown(Shutdown::Both);
if let Some(handle) = state.smoltcp_handle {
self.expect_smoltcp_send()?;
{
let handle = state.smoltcp_handle;
let socket = self.sockets.get_mut::<tcp::Socket>(handle);
socket.close();
self.sockets.remove(handle);
}
// FIXME: Does this line should be moved up to the beginning of this function?
self.expect_smoltcp_send()?;
if let Err(e) = self.poll.registry().deregister(&mut state.mio_stream) {
// FIXME: The function `deregister` will frequently fail for unknown reasons.
log::trace!("{}", e);
@ -381,6 +369,10 @@ impl<'a> TunToProxy<'a> {
}
}
if let Err(err) = state.mio_stream.shutdown(Shutdown::Both) {
log::trace!("Shutdown 0 {} error \"{}\"", info, err);
}
log::info!("Close {}", info);
}
Ok(())
@ -405,11 +397,10 @@ impl<'a> TunToProxy<'a> {
.proxy_handler
.have_data(Direction::Outgoing(OutgoingDirection::ToClient))
{
if let Some(handle) = state.smoltcp_handle {
// Close tun interface
let socket = self.sockets.get_mut::<tcp::Socket>(handle);
socket.close();
}
// Close tun interface
let socket = self.sockets.get_mut::<tcp::Socket>(state.smoltcp_handle);
socket.close();
closed_ends += 1;
}
@ -422,7 +413,9 @@ impl<'a> TunToProxy<'a> {
.have_data(Direction::Outgoing(OutgoingDirection::ToServer))
{
// Close remote server
_ = state.mio_stream.shutdown(Shutdown::Write);
if let Err(err) = state.mio_stream.shutdown(Shutdown::Write) {
log::trace!("Shutdown 1 {} error \"{}\"", info, err);
}
closed_ends += 1;
}
@ -441,10 +434,7 @@ impl<'a> TunToProxy<'a> {
Some(state) => state,
None => return Ok(()),
};
let socket = match state.smoltcp_handle {
Some(handle) => self.sockets.get_mut::<tcp::Socket>(handle),
None => return Ok(()),
};
let socket = self.sockets.get_mut::<tcp::Socket>(state.smoltcp_handle);
let mut error = Ok(());
while socket.can_recv() && error.is_ok() {
socket.recv(|data| {
@ -700,49 +690,61 @@ impl<'a> TunToProxy<'a> {
Ok(())
}
fn process_incoming_tcp_packets(
&mut self,
first_packet: bool,
manager: &Rc<dyn ConnectionManager>,
info: &ConnectionInfo,
origin_dst: SocketAddr,
frame: &[u8],
) -> Result<()> {
if first_packet {
let proxy_handler = manager.new_proxy_handler(info, false)?;
let server = manager.get_server_addr();
let state = self.create_new_tcp_connection_state(server, origin_dst, proxy_handler, false)?;
self.connection_map.insert(info.clone(), state);
log::info!("Connect done {} ({})", info, origin_dst);
} else if !self.connection_map.contains_key(info) {
log::trace!("Drop middle session {} ({})", info, origin_dst);
return Ok(());
} else {
log::trace!("Subsequent packet {} ({})", info, origin_dst);
}
// Inject the packet to advance the remote proxy server smoltcp socket state
self.device.inject_packet(frame);
// Having advanced the socket state, we expect the socket to ACK
// Exfiltrate the response packets generated by the socket and inject them
// into the tunnel interface.
self.expect_smoltcp_send()?;
// Read from the smoltcp socket and push the data to the connection handler.
self.tunsocket_read_and_forward(info)?;
// 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(info)?;
Ok(())
}
// A raw packet was received on the tunnel interface.
fn receive_tun(&mut self, frame: &mut [u8]) -> Result<(), Error> {
let mut handler = || -> Result<(), Error> {
let result = connection_tuple(frame);
if let Err(error) = result {
log::info!("{}, ignored", error);
log::debug!("{}, ignored", error);
return Ok(());
}
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 info = self.preprocess_origin_connection_info(info)?;
let manager = self.get_connection_manager().ok_or("get connection manager")?;
if info.protocol == IpProtocol::Tcp {
if _first_packet {
let proxy_handler = manager.new_proxy_handler(&info, false)?;
let server = manager.get_server_addr();
let state = self.create_new_tcp_connection_state(server, origin_dst, proxy_handler, false)?;
self.connection_map.insert(info.clone(), state);
log::info!("Connect done {} ({})", info, origin_dst);
} else if !self.connection_map.contains_key(&info) {
// log::debug!("Drop middle session {} ({})", info, origin_dst);
return Ok(());
} else {
// log::trace!("Subsequent packet {} ({})", info, origin_dst);
}
// Inject the packet to advance the remote proxy server smoltcp socket state
self.device.inject_packet(frame);
// Having advanced the socket state, we expect the socket to ACK
// Exfiltrate the response packets generated by the socket and inject them
// into the tunnel interface.
self.expect_smoltcp_send()?;
// Read from the smoltcp socket and push the data to the connection handler.
self.tunsocket_read_and_forward(&info)?;
// 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(&info)?;
self.process_incoming_tcp_packets(first_packet, &manager, &info, origin_dst, frame)?;
} else if info.protocol == IpProtocol::Udp {
let port = info.dst.port();
let payload = &frame[payload_offset..payload_offset + payload_size];
@ -803,7 +805,7 @@ impl<'a> TunToProxy<'a> {
(None, None)
};
let state = ConnectionState {
smoltcp_handle: Some(handle),
smoltcp_handle: handle,
mio_stream: client,
token,
proxy_handler,
@ -889,15 +891,11 @@ impl<'a> TunToProxy<'a> {
fn write_to_client(&mut self, token: Token, info: &ConnectionInfo) -> Result<(), Error> {
while let Some(state) = self.connection_map.get_mut(info) {
let handle = match state.smoltcp_handle {
Some(handle) => handle,
None => break,
};
let event = state.proxy_handler.peek_data(OutgoingDirection::ToClient);
let buflen = event.buffer.len();
let consumed;
{
let socket = self.sockets.get_mut::<tcp::Socket>(handle);
let socket = self.sockets.get_mut::<tcp::Socket>(state.smoltcp_handle);
if socket.may_send() {
if let Some(virtual_dns) = &mut self.options.virtual_dns {
// Unwrapping is fine because every smoltcp socket is bound to an.
@ -940,8 +938,8 @@ impl<'a> TunToProxy<'a> {
if let Some(connection) = self.find_info_by_token(token) {
let connection = connection.clone();
if let Err(error) = self.write_to_client(token, &connection) {
log::error!("Write to client {}", error);
self.remove_connection(&connection)?;
log::error!("Write to client: {}: ", error);
}
}
}
@ -1059,9 +1057,13 @@ impl<'a> TunToProxy<'a> {
// The handler request for reset the server connection
if state.proxy_handler.reset_connection() {
_ = self.poll.registry().deregister(&mut state.mio_stream);
if let Err(err) = self.poll.registry().deregister(&mut state.mio_stream) {
log::trace!("{}", err);
}
// Closes the connection with the proxy
state.mio_stream.shutdown(Shutdown::Both)?;
if let Err(err) = state.mio_stream.shutdown(Shutdown::Both) {
log::trace!("Shutdown 2 error \"{}\"", err);
}
log::info!("RESET {}", conn_info);
@ -1112,7 +1114,7 @@ impl<'a> TunToProxy<'a> {
loop {
if let Err(err) = self.poll.poll(&mut events, None) {
if err.kind() == std::io::ErrorKind::Interrupted {
log::warn!("Poll interrupted: \"{err}\", ignored, continue polling");
log::debug!("Poll interrupted: \"{err}\", ignored, continue polling");
continue;
}
return Err(err.into());