tun2proxy/src/http.rs

205 lines
6.5 KiB
Rust
Raw Normal View History

use crate::error::Error;
2022-08-01 14:36:58 +00:00
use crate::tun2proxy::{
Connection, ConnectionManager, IncomingDataEvent, IncomingDirection, OutgoingDataEvent,
OutgoingDirection, TcpProxy,
2022-08-01 14:36:58 +00:00
};
use crate::Credentials;
2023-03-22 10:12:32 +01:00
use base64::Engine;
2023-03-23 18:31:09 +08:00
use smoltcp::wire::IpProtocol;
2021-09-02 11:30:23 +02:00
use std::collections::VecDeque;
use std::net::SocketAddr;
2023-03-23 16:31:33 +08:00
use std::rc::Rc;
2021-09-02 11:30:23 +02:00
#[derive(Eq, PartialEq, Debug)]
#[allow(dead_code)]
enum HttpState {
SendRequest,
2021-09-02 21:02:17 +02:00
ExpectStatusCode,
2021-09-02 11:30:23 +02:00
ExpectResponse,
2022-08-01 14:36:58 +00:00
Established,
2021-09-02 11:30:23 +02:00
}
pub struct HttpConnection {
state: HttpState,
client_inbuf: VecDeque<u8>,
server_inbuf: VecDeque<u8>,
client_outbuf: VecDeque<u8>,
server_outbuf: VecDeque<u8>,
data_buf: VecDeque<u8>,
2022-08-01 14:36:58 +00:00
crlf_state: u8,
2021-09-02 11:30:23 +02:00
}
impl HttpConnection {
2023-03-23 16:31:33 +08:00
fn new(connection: &Connection, manager: Rc<dyn ConnectionManager>) -> Self {
2023-03-22 10:12:32 +01:00
let mut server_outbuf: VecDeque<u8> = VecDeque::new();
{
let credentials = manager.get_credentials();
server_outbuf.extend(b"CONNECT ".iter());
server_outbuf.extend(connection.dst.to_string().as_bytes());
server_outbuf.extend(b" HTTP/1.1\r\nHost: ".iter());
server_outbuf.extend(connection.dst.to_string().as_bytes());
server_outbuf.extend(b"\r\n".iter());
if let Some(credentials) = credentials {
2023-03-22 10:12:32 +01:00
server_outbuf.extend(b"Proxy-Authorization: Basic ");
let mut auth_plain = credentials.username.clone();
auth_plain.extend(b":".iter());
auth_plain.extend(&credentials.password);
let auth_b64 = base64::engine::general_purpose::STANDARD.encode(auth_plain);
server_outbuf.extend(auth_b64.as_bytes().iter());
server_outbuf.extend(b"\r\n".iter());
}
server_outbuf.extend(b"\r\n".iter());
}
Self {
2021-09-02 21:02:17 +02:00
state: HttpState::ExpectStatusCode,
2021-09-02 11:30:23 +02:00
client_inbuf: Default::default(),
server_inbuf: Default::default(),
client_outbuf: Default::default(),
2023-03-22 10:12:32 +01:00
server_outbuf,
2021-09-02 11:30:23 +02:00
data_buf: Default::default(),
2022-08-01 14:36:58 +00:00
crlf_state: Default::default(),
2023-03-22 10:12:32 +01:00
}
2021-09-02 11:30:23 +02:00
}
fn state_change(&mut self) -> Result<(), Error> {
2023-03-24 15:57:54 +08:00
let http_len = "HTTP/1.1 200".len();
2021-09-02 11:30:23 +02:00
match self.state {
2023-03-24 15:57:54 +08:00
HttpState::ExpectStatusCode if self.server_inbuf.len() > http_len => {
let status_line: Vec<u8> =
self.server_inbuf.range(0..http_len + 1).copied().collect();
2021-09-02 21:02:17 +02:00
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"
2023-03-24 15:57:54 +08:00
|| self.server_inbuf[http_len] != b' '
2022-08-01 14:36:58 +00:00
{
2023-03-24 15:57:54 +08:00
let status_str = String::from_utf8_lossy(&status_line.as_slice()[0..http_len]);
let e =
format!("Expected success status code. Server replied with {status_str}.");
return Err(e.into());
2021-09-02 21:02:17 +02:00
}
self.state = HttpState::ExpectResponse;
return self.state_change();
}
2021-09-02 11:30:23 +02:00
HttpState::ExpectResponse => {
let mut counter = 0usize;
for b_ref in self.server_inbuf.iter() {
let b = *b_ref;
if b == b'\n' {
self.crlf_state += 1;
} else if b != b'\r' {
self.crlf_state = 0;
}
counter += 1;
if self.crlf_state == 2 {
self.server_inbuf.drain(0..counter);
self.server_outbuf.append(&mut self.data_buf);
self.data_buf.clear();
self.state = HttpState::Established;
2021-09-02 21:02:17 +02:00
return self.state_change();
2021-09-02 11:30:23 +02:00
}
}
self.server_inbuf.drain(0..counter);
}
HttpState::Established => {
self.client_outbuf.extend(self.server_inbuf.iter());
self.server_outbuf.extend(self.client_inbuf.iter());
self.server_inbuf.clear();
self.client_inbuf.clear();
}
2022-08-01 14:36:58 +00:00
_ => {}
2021-09-02 11:30:23 +02:00
}
2021-09-02 21:02:17 +02:00
Ok(())
2021-09-02 11:30:23 +02:00
}
}
impl TcpProxy for HttpConnection {
fn push_data(&mut self, event: IncomingDataEvent<'_>) -> Result<(), Error> {
2021-09-02 11:30:23 +02:00
let direction = event.direction;
let buffer = event.buffer;
match direction {
IncomingDirection::FromServer => {
self.server_inbuf.extend(buffer.iter());
2022-08-01 14:36:58 +00:00
}
2021-09-02 11:30:23 +02:00
IncomingDirection::FromClient => {
if self.state == HttpState::Established {
self.client_inbuf.extend(buffer.iter());
} else {
self.data_buf.extend(buffer.iter());
}
}
}
2021-09-02 21:02:17 +02:00
self.state_change()
2021-09-02 11:30:23 +02:00
}
fn consume_data(&mut self, dir: OutgoingDirection, size: usize) {
2022-08-01 14:36:58 +00:00
let buffer = if dir == OutgoingDirection::ToServer {
2021-09-02 11:30:23 +02:00
&mut self.server_outbuf
} else {
&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
};
2022-08-01 14:36:58 +00:00
OutgoingDataEvent {
2021-09-02 11:30:23 +02:00
direction: dir,
2022-08-01 14:36:58 +00:00
buffer: buffer.make_contiguous(),
}
2021-09-02 11:30:23 +02:00
}
2021-09-02 21:02:17 +02:00
fn connection_established(&self) -> bool {
2022-08-01 14:36:58 +00:00
self.state == HttpState::Established
2021-09-02 21:02:17 +02:00
}
2021-09-02 11:30:23 +02:00
}
pub(crate) struct HttpManager {
2023-03-23 20:00:59 +08:00
server: SocketAddr,
credentials: Option<Credentials>,
2021-09-02 11:30:23 +02:00
}
impl ConnectionManager for HttpManager {
fn handles_connection(&self, connection: &Connection) -> bool {
connection.proto == IpProtocol::Tcp
2021-09-02 11:30:23 +02:00
}
2023-03-22 01:02:27 +01:00
fn new_connection(
&self,
connection: &Connection,
2023-03-23 16:31:33 +08:00
manager: Rc<dyn ConnectionManager>,
2023-03-25 01:39:46 +01:00
) -> Result<Option<Box<dyn TcpProxy>>, Error> {
if connection.proto != IpProtocol::Tcp {
2023-03-25 01:39:46 +01:00
return Ok(None);
2021-09-02 11:30:23 +02:00
}
2023-03-25 01:39:46 +01:00
Ok(Some(Box::new(HttpConnection::new(connection, manager))))
2021-09-02 11:30:23 +02:00
}
2023-03-21 01:08:44 +01:00
fn close_connection(&self, _: &Connection) {}
2021-09-02 11:30:23 +02:00
fn get_server(&self) -> SocketAddr {
self.server
}
2023-03-22 01:02:27 +01:00
fn get_credentials(&self) -> &Option<Credentials> {
2023-03-22 01:02:27 +01:00
&self.credentials
}
2021-09-02 11:30:23 +02:00
}
impl HttpManager {
2023-03-23 16:31:33 +08:00
pub fn new(server: SocketAddr, credentials: Option<Credentials>) -> Rc<Self> {
Rc::new(Self {
2023-03-22 01:02:27 +01:00
server,
credentials,
})
2021-09-02 11:30:23 +02:00
}
2022-08-01 14:36:58 +00:00
}