Skip to main content

transparent_proxy/
http.rs

1use std::{error::Error, io::ErrorKind};
2
3use tap::Tap;
4use tokio::{
5    io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
6    net::TcpStream,
7};
8
9use crate::Flags;
10
11pub async fn handle_client(
12    mut client: tokio::net::TcpStream,
13    flags: Flags,
14) -> Result<(), Box<dyn Error>> {
15    let auth_line = format!(
16        "Proxy-Authorization: Basic {}\r\n",
17        base64::encode(&format!(
18            "{}:{}",
19            flags
20                .username
21                .unwrap_or_default()
22                .replace("%R", fastrand::u32(0..u32::MAX).to_string().as_str())
23                .tap_dbg(|s| println!("username: {}", s)),
24            flags.password.unwrap_or_default()
25        ))
26    );
27    let mut server = TcpStream::connect(flags.target_addr).await?;
28    let (mut reader, mut writer) = client.split();
29    let buf_reader = BufReader::new(&mut reader);
30    let mut lines = buf_reader.lines();
31    let first_line = lines
32        .next_line()
33        .await?
34        .ok_or_else(|| std::io::Error::new(ErrorKind::InvalidData, "missing init data"))?;
35    dbg!(&first_line);
36    server
37        .write_all(format!("{first_line}\r\n{auth_line}\r\n").as_bytes())
38        .await?;
39    let (mut server_reader, mut server_writer) = server.split();
40    let res = tokio::try_join!(
41        tokio::io::copy(&mut reader, &mut server_writer),
42        tokio::io::copy(&mut server_reader, &mut writer)
43    );
44    if cfg!(debug_assertions) {
45        eprintln!("{res:?}");
46    }
47    Ok(())
48}