From 26b55f7d1e26de6c70c6651e6a5797dd5805c7fe Mon Sep 17 00:00:00 2001 From: int 80h Date: Sun, 10 May 2020 17:18:14 -0400 Subject: [PATCH] Revproxy is working. Added example cgi script --- Cargo.toml | 3 ++ cgi-scripts/agena-cgi/Cargo.toml | 9 ++++ cgi-scripts/agena-cgi/src/main.rs | 15 ++++++ src/config.rs | 11 ++--- src/main.rs | 8 +++- src/revproxy.rs | 76 ++++++++++++++++++++----------- 6 files changed, 85 insertions(+), 37 deletions(-) create mode 100644 cgi-scripts/agena-cgi/Cargo.toml create mode 100644 cgi-scripts/agena-cgi/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index e8d0c7d..d12635d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,6 @@ url = "*" chrono = "0.4" mime_guess = "2.0.3" mime = "0.3.16" + +[workspace] +members = [ "cgi-scripts/agena-cgi" ] diff --git a/cgi-scripts/agena-cgi/Cargo.toml b/cgi-scripts/agena-cgi/Cargo.toml new file mode 100644 index 0000000..867d9b4 --- /dev/null +++ b/cgi-scripts/agena-cgi/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "agena-cgi" +version = "0.1.0" +authors = ["int 80h "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/cgi-scripts/agena-cgi/src/main.rs b/cgi-scripts/agena-cgi/src/main.rs new file mode 100644 index 0000000..54931f5 --- /dev/null +++ b/cgi-scripts/agena-cgi/src/main.rs @@ -0,0 +1,15 @@ +use std::env; + +// Base url of agena proxy +const BASE: &'static str = "gemini://example.com/"; + +fn main() { + let query = match env::var("QUERY_STRING") { + Ok(q) => q, + _ => { + println!("10\tGopher url:\r\n"); + return; + }, + }; + println!("30\t{}{}\r\n", BASE, query); +} diff --git a/src/config.rs b/src/config.rs index 7d49e3c..f45c974 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,7 +20,7 @@ pub struct Server { pub cert: String, pub cgi: Option, pub usrdir: Option, - pub proxy: Option>, + pub proxy: Option>, } #[derive(Debug, Clone)] @@ -54,12 +54,7 @@ impl Config { }; let mut pmap = HashMap::new(); match &srv.proxy { - Some(pr) => { - for p in pr { - let p: Vec<&str> = p.split("=").collect(); - pmap.insert(p[0].trim().to_string(), p[1].trim().to_string()); - } - }, + Some(pr) => pmap = pr.clone(), None => {}, }; map.insert(srv.hostname.clone(), ServerCfg { @@ -70,7 +65,7 @@ impl Config { cgi: cgi, usrdir: usrdir, port: self.port.clone(), - proxy: pmap, + proxy: pmap.clone(), }); } map diff --git a/src/main.rs b/src/main.rs index 89e38b8..add880f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -124,9 +124,13 @@ async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) - }; if srv.proxy.len() != 0 { - match srv.proxy.get(url.path()) { + let seg = match url.path_segments().map(|c| c.collect::>()) { + Some(s) => s, + None => return Ok(()), + }; + match srv.proxy.get(seg[0]) { Some(p) => { - revproxy::proxy(p.to_string(), url).await?; + revproxy::proxy(p.to_string(), url, con).await?; return Ok(()); }, None => {}, diff --git a/src/revproxy.rs b/src/revproxy.rs index 3b65d48..299834c 100644 --- a/src/revproxy.rs +++ b/src/revproxy.rs @@ -1,37 +1,59 @@ -use std::io; -use std::fs::File; -use std::sync::Arc; -use std::net::ToSocketAddrs; -use std::io::BufReader; use futures_util::future; +use std::fs::File; +use std::io; +use std::io::Read; +use std::io::BufReader; +use std::net::ToSocketAddrs; +use std::sync::Arc; +use tokio::io::{copy, split, AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpStream; -use tokio::io::{ - AsyncWriteExt, - copy, split, -}; -use tokio_rustls::{ TlsConnector, rustls::ClientConfig, webpki::DNSNameRef }; +use openssl::ssl::{SslConnector, SslMethod}; use url::Url; -pub async fn proxy(addr: String, _u: url::Url) -> Result<(), io::Error> { - let addr = addr.to_socket_addrs()? +use crate::conn; +use crate::status; + +pub async fn proxy(addr: String, u: url::Url, mut con: conn::Connection) -> Result<(), io::Error> { + let p: Vec<&str> = u.path().trim_start_matches("/").splitn(2, "/").collect(); + if p.len() == 1 { + con.send_status(status::Status::NotFound, "Not Found").await?; + return Ok(()); + } + if p[1] == "" || p[1] == "/" { + con.send_status(status::Status::NotFound, "Not Found").await?; + return Ok(()) + } + let addr = addr + .to_socket_addrs()? .next() .ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?; - let mut config = ClientConfig::new(); - let mut pem = BufReader::new(File::open("cafile")?); - config.root_store.add_pem_file(&mut pem) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert"))?; - - let connector = TlsConnector::from(Arc::new(config)); - let stream = TcpStream::connect(&addr).await?; - - let domain = DNSNameRef::try_from_ascii_str("cbook.lan") - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname"))?; - - println!("Connecting to agena..."); - let mut stream = connector.connect(domain, stream).await?; - //stream.write_all(b"gopher://gopher.club/\r\n").await?; - //stream.flush().await?; + let mut connector = SslConnector::builder(SslMethod::tls()).unwrap(); + connector.set_verify(openssl::ssl::SslVerifyMode::NONE); + let config = connector.build().configure().unwrap(); + let stream = match TcpStream::connect(&addr).await { + Ok(s) => s, + Err(_) => { + eprintln!("Error connecting to proxy"); + con.send_status(status::Status::ProxyError, "Error Connecting to proxy").await?; + return Ok(()) + }, + }; + let mut stream = match tokio_openssl::connect(config, "localhost", stream).await { + Ok(s) => s, + Err(_) => { + eprintln!("Error connecting to proxy"); + con.send_status(status::Status::ProxyError, "Error Connecting to proxy").await?; + return Ok(()) + }, + }; + stream.write_all(p[1].as_bytes()).await?; + stream.flush().await?; + + let mut buf = vec![]; + stream.read_to_end(&mut buf).await?; + // let req = String::from_utf8(buf[..].to_vec()).unwrap(); + con.send_raw(&buf).await?; Ok(()) }