WIP adaptations
This commit is contained in:
83
src/main.rs
83
src/main.rs
@@ -13,7 +13,7 @@ use tokio::net::TcpStream;
|
||||
use tokio_rustls::TlsConnector;
|
||||
use tokio_rustls::rustls::{ClientConfig, RootCertStore};
|
||||
|
||||
/// Simple program that proxify requests and save responses
|
||||
/// Simple program that redirect requests to a given server in request
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct Args {
|
||||
@@ -21,31 +21,23 @@ struct Args {
|
||||
#[arg(short, long, default_value = "0.0.0.0:8000")]
|
||||
listen_address: String,
|
||||
|
||||
/// Upstream address this server will connect to
|
||||
#[arg(short, long, default_value = "communiquons.org")]
|
||||
upstream_dns: String,
|
||||
/// The name of the header that contain target host and port
|
||||
#[arg(short, long, default_value = "x-target-host")]
|
||||
target_host_port_header: String,
|
||||
|
||||
/// Upstream address this server will connect to
|
||||
#[arg(short('I'), long, default_value = "10.0.1.10:443")]
|
||||
upstream_ip: String,
|
||||
|
||||
/// The path on the server this server will save requests and responses
|
||||
#[arg(short, long, default_value = "storage")]
|
||||
storage_path: String,
|
||||
|
||||
/// Only forward requests that match a given prefix
|
||||
#[arg(short, long)]
|
||||
prefix: Option<String>,
|
||||
/// Name of optional header that contains path to add to the request
|
||||
#[arg(short, long, default_value = "x-path-prefix")]
|
||||
path_prefix_heder: String,
|
||||
}
|
||||
|
||||
/// Get the current time since epoch
|
||||
pub fn time() -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs()
|
||||
lazy_static::lazy_static! {
|
||||
static ref ARGS: Args = {
|
||||
Args::parse()
|
||||
};
|
||||
}
|
||||
|
||||
const ERR_NOT_PROXIFIALBE: &[u8; 44] = b"HTTP/1.1 400 Forbidden\r\n\r\nNot proxifiable.\r\n";
|
||||
|
||||
pub fn rand_str(len: usize) -> String {
|
||||
Alphanumeric.sample_string(&mut rand::rng(), len)
|
||||
}
|
||||
@@ -54,56 +46,23 @@ pub fn rand_str(len: usize) -> String {
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
log::info!("Will start to listen on {}", args.listen_address);
|
||||
let listener = TcpListener::bind(&args.listen_address).await?;
|
||||
|
||||
std::fs::create_dir_all(Path::new(args.storage_path.as_str())).unwrap();
|
||||
log::info!("Will start to listen on {}", ARGS.listen_address);
|
||||
let listener = TcpListener::bind(&ARGS.listen_address).await?;
|
||||
|
||||
loop {
|
||||
// Asynchronously wait for an inbound socket.
|
||||
let (mut client_socket, _) = listener.accept().await?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
let conn_id = rand_str(10);
|
||||
let conn_id = rand_str(5);
|
||||
|
||||
log::info!(
|
||||
"[{conn_id}] Start new connection from {}",
|
||||
log::debug!(
|
||||
"Handle new connection from {}",
|
||||
client_socket.peer_addr().unwrap()
|
||||
);
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
let base_file_name = format!(
|
||||
"{}-{}-{}",
|
||||
client_socket.peer_addr().unwrap().ip(),
|
||||
time(),
|
||||
conn_id
|
||||
);
|
||||
|
||||
let mut req_file = OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(Path::new(&args.storage_path).join(format!("{base_file_name}-req")))
|
||||
.expect("Failed to create req file");
|
||||
let mut res_file = OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(Path::new(&args.storage_path).join(format!("{base_file_name}-res")))
|
||||
.expect("Failed to create req file");
|
||||
|
||||
let mut root_cert_store = RootCertStore::empty();
|
||||
root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
||||
let config = ClientConfig::builder()
|
||||
.with_root_certificates(root_cert_store)
|
||||
.with_no_client_auth();
|
||||
let connector = TlsConnector::from(Arc::new(config));
|
||||
let dnsname = ServerName::try_from(args.upstream_dns.to_string()).unwrap();
|
||||
|
||||
let stream = TcpStream::connect(args.upstream_ip)
|
||||
let stream = TcpStream::connect(TODO)
|
||||
.await
|
||||
.expect("Failed to connect to upstream");
|
||||
let mut upstream = connector
|
||||
@@ -139,7 +98,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
// Check for URL prefix
|
||||
if let Some(prefix) = &args.prefix
|
||||
&& !String::from_utf8_lossy(&buf_client[..count]).split_once('\n').map(|l|l.0).unwrap_or("").contains(&format!(" {prefix}")) {
|
||||
client_write.write_all(b"HTTP/1.1 401 Forbidden\r\n\r\nNot proxifiable.\r\n").await.expect("Failed to respond to client");
|
||||
client_write.write_all(ERR_NOT_PROXIFIABLE).await.expect("Failed to respond to client");
|
||||
client_write.flush().await.expect("Failed to flush response to client!");
|
||||
return;
|
||||
}
|
||||
@@ -152,7 +111,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
};
|
||||
|
||||
upstream.write_all(&buff).await.unwrap_or_else(|_| panic!("[{conn_id}] Failed to write to upstream"));
|
||||
req_file.write_all(&buff).unwrap_or_else(|_| panic!("[{conn_id}] Failed to write to req"));
|
||||
}
|
||||
|
||||
count = upstream.read(&mut buf_server) => {
|
||||
@@ -172,7 +130,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
log::info!("[{conn_id}] Got a new upstream read {count} - {base_file_name}");
|
||||
client_write.write_all(&buf_server[..count]).await.expect("Failed to write to client");
|
||||
res_file.write_all(&buf_server[..count]).expect("Failed to write to res");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user