Browse Source

Prevent connection error bubbling from terminating the app

pull/19/head
B. Blechschmidt 3 years ago
parent
commit
86e7af0398
  1. 306
      src/tun2proxy.rs

306
src/tun2proxy.rs

@ -384,101 +384,113 @@ impl<'a> TunToProxy<'a> {
} }
} }
}; };
if resolved_conn.proto == IpProtocol::Tcp { let dst = connection.dst;
let cm = self.get_connection_manager(&resolved_conn); (|| -> Result<(), Error> {
if cm.is_none() { if resolved_conn.proto == IpProtocol::Tcp {
return Ok(()); let cm = self.get_connection_manager(&resolved_conn);
} if cm.is_none() {
let server = cm.ok_or("no connect manager")?.get_server(); return Ok(());
if first_packet { }
for manager in self.connection_managers.iter_mut() { let server = cm.ok_or("no connect manager")?.get_server();
if let Some(handler) = if first_packet {
manager.new_connection(&resolved_conn, manager.clone())? for manager in self.connection_managers.iter_mut() {
{ if let Some(handler) =
let mut socket = tcp::Socket::new( manager.new_connection(&resolved_conn, manager.clone())?
tcp::SocketBuffer::new(vec![0; 4096]), {
tcp::SocketBuffer::new(vec![0; 4096]), let mut socket = tcp::Socket::new(
); tcp::SocketBuffer::new(vec![0; 4096]),
socket.set_ack_delay(None); tcp::SocketBuffer::new(vec![0; 4096]),
let dst = SocketAddr::try_from(connection.dst)?; );
socket.listen(dst)?; socket.set_ack_delay(None);
let handle = self.sockets.add(socket); let dst = SocketAddr::try_from(dst)?;
socket.listen(dst)?;
let client = TcpStream::connect(server)?; let handle = self.sockets.add(socket);
let token = Token(self.next_token); let client = TcpStream::connect(server)?;
self.next_token += 1;
let token = Token(self.next_token);
let mut state = ConnectionState { self.next_token += 1;
smoltcp_handle: handle,
mio_stream: client, let mut state = ConnectionState {
token, smoltcp_handle: handle,
handler, mio_stream: client,
smoltcp_socket_state: 0, token,
}; handler,
smoltcp_socket_state: 0,
};
self.token_to_connection
.insert(token, resolved_conn.clone());
self.poll.registry().register(
&mut state.mio_stream,
token,
Interest::READABLE | Interest::WRITABLE,
)?;
self.connections.insert(resolved_conn.clone(), state);
info!("CONNECT {}", resolved_conn,);
break;
}
}
} else if !self.connections.contains_key(&resolved_conn) {
return Ok(());
}
self.token_to_connection // Inject the packet to advance the smoltcp socket state
.insert(token, resolved_conn.clone()); self.device.inject_packet(frame);
self.poll.registry().register(
&mut state.mio_stream,
token,
Interest::READABLE | Interest::WRITABLE,
)?;
self.connections.insert(resolved_conn.clone(), state); // 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()?;
info!("CONNECT {}", resolved_conn,); // Read from the smoltcp socket and push the data to the connection handler.
break; self.tunsocket_read_and_forward(&resolved_conn)?;
// 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(&resolved_conn)?;
} else if resolved_conn.proto == IpProtocol::Udp && resolved_conn.dst.port == 53 {
if let Some(virtual_dns) = &mut self.options.virtdns {
let payload = &frame[_payload_offset.._payload_offset + _payload_size];
if let Some(response) = virtual_dns.receive_query(payload) {
let rx_buffer = udp::PacketBuffer::new(
vec![udp::PacketMetadata::EMPTY],
vec![0; 4096],
);
let tx_buffer = udp::PacketBuffer::new(
vec![udp::PacketMetadata::EMPTY],
vec![0; 4096],
);
let mut socket = udp::Socket::new(rx_buffer, tx_buffer);
let dst = SocketAddr::try_from(dst)?;
socket.bind(dst)?;
socket
.send_slice(response.as_slice(), resolved_conn.src.into())
.expect("failed to send DNS response");
let handle = self.sockets.add(socket);
self.expect_smoltcp_send()?;
self.sockets.remove(handle);
} }
} }
} else if !self.connections.contains_key(&resolved_conn) { // Otherwise, UDP is not yet supported.
return Ok(());
} }
Ok(())
// Inject the packet to advance the smoltcp socket state })()
self.device.inject_packet(frame); .or_else(|error| {
log::error! {"{error}"}
// Having advanced the socket state, we expect the socket to ACK Ok::<(), Error>(())
// 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(&resolved_conn)?;
// 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(&resolved_conn);
} else if resolved_conn.proto == IpProtocol::Udp && resolved_conn.dst.port == 53 {
if let Some(virtual_dns) = &mut self.options.virtdns {
let payload = &frame[_payload_offset.._payload_offset + _payload_size];
if let Some(response) = virtual_dns.receive_query(payload) {
let rx_buffer =
udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 4096]);
let tx_buffer =
udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 4096]);
let mut socket = udp::Socket::new(rx_buffer, tx_buffer);
let dst = SocketAddr::try_from(connection.dst)?;
socket.bind(dst)?;
socket
.send_slice(response.as_slice(), resolved_conn.src.into())
.expect("failed to send DNS response");
let handle = self.sockets.add(socket);
self.expect_smoltcp_send()?;
self.sockets.remove(handle);
}
}
// Otherwise, UDP is not yet supported.
}
} }
Ok(()) Ok(())
} }
fn write_to_server(&mut self, connection: &Connection) { fn write_to_server(&mut self, connection: &Connection) -> Result<(), Error> {
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); let event = state.handler.peek_data(OutgoingDirection::ToServer);
if event.buffer.is_empty() { if event.buffer.is_empty() {
return; return Ok(());
} }
let result = state.mio_stream.write(event.buffer); let result = state.mio_stream.write(event.buffer);
match result { match result {
@ -488,13 +500,12 @@ impl<'a> TunToProxy<'a> {
.consume_data(OutgoingDirection::ToServer, consumed); .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); return Err(error.into());
}
_ => {
// println!("{:?}", result);
} }
_ => {}
} }
} }
Ok(())
} }
fn write_to_client(&mut self, token: Token, connection: &Connection) -> Result<(), Error> { fn write_to_client(&mut self, token: Token, connection: &Connection) -> Result<(), Error> {
@ -556,7 +567,11 @@ impl<'a> TunToProxy<'a> {
let cloned = self.write_sockets.clone(); let cloned = self.write_sockets.clone();
for token in cloned.iter() { for token in cloned.iter() {
if let Some(connection) = self.token_to_connection.get(token) { if let Some(connection) = self.token_to_connection.get(token) {
self.write_to_client(*token, &connection.clone())?; let connection = connection.clone();
if let Err(error) = self.write_to_client(*token, &connection) {
self.remove_connection(&connection)?;
log::error!("Write to client: {}: ", error);
}
} }
} }
Ok(()) Ok(())
@ -565,70 +580,75 @@ impl<'a> TunToProxy<'a> {
fn mio_socket_event(&mut self, event: &Event) -> Result<(), Error> { fn mio_socket_event(&mut self, event: &Event) -> Result<(), Error> {
let e = "connection not found"; let e = "connection not found";
let conn_ref = self.token_to_connection.get(&event.token()); let conn_ref = self.token_to_connection.get(&event.token());
if conn_ref.is_none() {
return Ok(());
}
let connection = conn_ref.ok_or(e)?.clone(); let connection = conn_ref.ok_or(e)?.clone();
if event.is_readable() || event.is_read_closed() {
{ (|| -> Result<(), Error> {
let state = self.connections.get_mut(&connection).ok_or(e)?; if event.is_readable() || event.is_read_closed() {
{
// TODO: Move this reading process to its own function. let state = self.connections.get_mut(&connection).ok_or(e)?;
let mut vecbuf = Vec::<u8>::new();
let read_result = state.mio_stream.read_to_end(&mut vecbuf); // TODO: Move this reading process to its own function.
let read = match read_result { let mut vecbuf = Vec::<u8>::new();
Ok(read_result) => read_result, let read_result = state.mio_stream.read_to_end(&mut vecbuf);
Err(error) => { let read = match read_result {
if error.kind() != std::io::ErrorKind::WouldBlock { Ok(read_result) => read_result,
error!("READ from proxy: {}", error); Err(error) => {
if error.kind() != std::io::ErrorKind::WouldBlock {
error!("Read from proxy: {}", error);
}
vecbuf.len()
} }
vecbuf.len() };
}
};
if read == 0 { if read == 0 {
{ {
let socket = self.sockets.get_mut::<tcp::Socket>( let socket = self.sockets.get_mut::<tcp::Socket>(
self.connections.get(&connection).ok_or(e)?.smoltcp_handle, self.connections.get(&connection).ok_or(e)?.smoltcp_handle,
); );
socket.close(); socket.close();
}
self.expect_smoltcp_send()?;
self.remove_connection(&connection.clone())?;
return Ok(());
} }
self.expect_smoltcp_send()?;
self.remove_connection(&connection.clone())?;
return Ok(());
}
let data = vecbuf.as_slice(); let data = vecbuf.as_slice();
let data_event = IncomingDataEvent { let data_event = IncomingDataEvent {
direction: IncomingDirection::FromServer, direction: IncomingDirection::FromServer,
buffer: &data[0..read], buffer: &data[0..read],
}; };
if let Err(error) = state.handler.push_data(data_event) { if let Err(error) = state.handler.push_data(data_event) {
state.mio_stream.shutdown(Both)?; state.mio_stream.shutdown(Both)?;
{ {
let socket = self.sockets.get_mut::<tcp::Socket>( let socket = self.sockets.get_mut::<tcp::Socket>(
self.connections.get(&connection).ok_or(e)?.smoltcp_handle, self.connections.get(&connection).ok_or(e)?.smoltcp_handle,
); );
socket.close(); socket.close();
}
self.expect_smoltcp_send()?;
log::error! {"{error}"}
self.remove_connection(&connection.clone())?;
return Ok(());
}
if event.is_read_closed() {
state.smoltcp_socket_state |= WRITE_CLOSED;
} }
self.expect_smoltcp_send()?;
log::error! {"{error}"}
self.remove_connection(&connection.clone())?;
return Ok(());
}
if event.is_read_closed() {
state.smoltcp_socket_state |= WRITE_CLOSED;
} }
}
// We have read from the proxy server and pushed the data to the connection handler. // We have read from the proxy server and pushed the data to the connection handler.
// Thus, expect data to be processed (e.g. decapsulated) and forwarded to the client. // Thus, expect data to be processed (e.g. decapsulated) and forwarded to the client.
self.write_to_client(event.token(), &connection)?; self.write_to_client(event.token(), &connection)?;
} }
if event.is_writable() { if event.is_writable() {
self.write_to_server(&connection); self.write_to_server(&connection)?;
} }
Ok(()) Ok(())
})()
.or_else(|error| {
self.remove_connection(&connection)?;
log::error! {"{error}"}
Ok(())
})
} }
fn udp_event(&mut self, _event: &Event) {} fn udp_event(&mut self, _event: &Event) {}

Loading…
Cancel
Save