Working client and server

This commit is contained in:
2025-08-19 14:25:40 +02:00
parent 53449db7c6
commit 7aefdbcc40
3 changed files with 122 additions and 49 deletions
+74 -9
View File
@@ -3,12 +3,27 @@ use std::{
net::TcpStream, net::TcpStream,
}; };
#[derive(Debug)]
pub enum Method {
Get,
Post,
Put,
Delete,
Head,
Options,
Patch,
Connect,
Trace,
}
pub mod server; pub mod server;
pub mod tls; pub mod tls;
#[derive(Debug)]
pub struct Request { pub struct Request {
host: String, host: String,
path: String, path: String,
method: Method,
} }
impl Request { impl Request {
@@ -16,48 +31,98 @@ impl Request {
Self { Self {
host: url.to_string(), host: url.to_string(),
path: String::from("/"), path: String::from("/"),
method: Method::Get,
}
}
pub fn from_str(host: &str, req: &str) -> Self {
let first_line = req.lines().next().unwrap_or_default();
let mut parts = first_line.split_whitespace();
let method = parts.next().unwrap_or_default();
let path = parts.next().unwrap_or("/");
Self {
host: host.to_string(),
path: path.to_string(),
method: match method {
"GET" => Method::Get,
"POST" => Method::Post,
"PUT" => Method::Put,
"DELETE" => Method::Delete,
"HEAD" => Method::Head,
"OPTIONS" => Method::Options,
"PATCH" => Method::Patch,
"CONNECT" => Method::Connect,
"TRACE" => Method::Trace,
_ => Method::Get,
},
} }
} }
} }
impl Request { impl Request {
pub fn send(&self) -> String { pub fn send_bytes(&self) -> Vec<u8> {
let tcp = TcpStream::connect((self.host.as_str(), 443)).unwrap(); let tcp = TcpStream::connect((self.host.as_str(), 443)).unwrap();
send_request(tcp, &self.host, &self.to_string()) send_request(tcp, &self.host, &self.to_string())
} }
pub fn send(&self) -> String {
let tcp = TcpStream::connect((self.host.as_str(), 443)).unwrap();
String::from_utf8(send_request(tcp, &self.host, &self.to_string())).unwrap()
}
pub fn send_routed(&self, router: &str) -> String { pub fn send_routed(&self, router: &str) -> String {
let mut tcp = TcpStream::connect((router, 80)).unwrap(); let mut tcp = TcpStream::connect(router).unwrap();
tcp.write_all(format!("ROUTE {}:443", self.host).as_bytes()) tcp.write_all(format!("ROUTE {}:443", self.host).as_bytes())
.unwrap(); .unwrap();
tcp.read(&mut [0; 32]).unwrap(); tcp.read(&mut [0; 32]).unwrap();
send_request(tcp, &self.host, &self.to_string()) String::from_utf8(send_request(tcp, &self.host, &self.to_string())).unwrap()
} }
pub fn send_routed_secure(&self, router: &str) -> String { pub fn send_routed_secure(&self, router: &str) -> String {
let tcp = TcpStream::connect((router, 443)).unwrap(); let tcp = TcpStream::connect((router, 443)).unwrap();
send_request( send_request(
tcp.try_clone().unwrap(), tcp.try_clone().unwrap(),
&self.host, &router,
&format!("ROUTE {}:443", self.host), &format!("ROUTE {}:443", self.host),
); );
send_request(tcp, &self.host, &self.to_string()) String::from_utf8(send_request(tcp, &self.host, &self.to_string())).unwrap()
} }
pub fn to_string(&self) -> String { pub fn to_string(&self) -> String {
format!( format!(
"GET {} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\nUser-Agent: rustls/0.23\r\n\r\n", "{} {} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\nUser-Agent: rustls/0.23\r\n\r\n",
self.path, self.host self.method, self.path, self.host
) )
} }
} }
pub fn send_request(mut stream: TcpStream, host: &str, send: &str) -> String { pub fn send_request(mut stream: TcpStream, host: &str, send: &str) -> Vec<u8> {
let mut conn = tls::tls13_handshake(&host, &mut stream).unwrap(); let mut conn = tls::tls13_handshake(&host, &mut stream).unwrap();
let mut tls = rustls::Stream::new(&mut conn, &mut stream); let mut tls = rustls::Stream::new(&mut conn, &mut stream);
tls.write_all(send.as_bytes()).unwrap(); tls.write_all(send.as_bytes()).unwrap();
tls.flush().unwrap(); tls.flush().unwrap();
let mut resp = Vec::new(); let mut resp = Vec::new();
tls.read_to_end(&mut resp).unwrap(); tls.read_to_end(&mut resp).unwrap();
String::from_utf8(resp).unwrap() resp
}
impl std::fmt::Display for Method {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Get => "GET",
Self::Post => "POST",
Self::Put => "PUT",
Self::Delete => "DELETE",
Self::Head => "HEAD",
Self::Options => "OPTIONS",
Self::Patch => "PATCH",
Self::Connect => "CONNECT",
Self::Trace => "TRACE",
}
)
}
} }
+4 -5
View File
@@ -1,8 +1,7 @@
use ghostnet_rs::Request;
fn main() { fn main() {
ghostnet_rs::server::run(); ghostnet_rs::server::run();
// println!("{}", Request::new("example.com").send_routed_secure("localhost")); // println!(
// println!("{}", Request::new("example.com").send_routed("localhost")); // "{}",
// println!("{}", Request::new("example.com").send()); // ghostnet_rs::Request::new("example.com").send_routed("localhost:6930")
// );
} }
+44 -35
View File
@@ -3,10 +3,12 @@ use std::{
net::{TcpListener, TcpStream}, net::{TcpListener, TcpStream},
}; };
const DEFAULT_HOST: &str = "osui.netlify.app";
pub fn run() { pub fn run() {
let server = TcpListener::bind(format!( let server = TcpListener::bind(format!(
"0.0.0.0:{}", "0.0.0.0:{}",
std::env::var("PORT").unwrap_or("80".to_string()) std::env::var("PORT").unwrap_or("6930".to_string())
)) ))
.unwrap(); .unwrap();
@@ -14,52 +16,59 @@ pub fn run() {
for stream in server.incoming() { for stream in server.incoming() {
match stream { match stream {
Ok(mut client) => { Ok(mut client) => {
println!("Client connected"); std::thread::spawn(move || {
let mut buf = [0; 1024]; println!("Client connected");
let mut buf = [0; 1024];
let buf_len = client.read(&mut buf).unwrap(); let buf_len = client.read(&mut buf).unwrap();
let req = String::from_utf8_lossy(&buf[..buf_len]); let req = String::from_utf8_lossy(&buf[..buf_len]);
let req = req.lines().collect::<Vec<_>>(); let req = req.lines().collect::<Vec<_>>();
if req.len() == 0 { if req.len() == 0 {
continue; return;
} }
if req[0].starts_with("ROUTE") { if req[0].starts_with("ROUTE") {
println!("Route mode"); println!("Route mode");
let addr = req[0].split_once(' ').unwrap().1; let addr = req[0].split_once(' ').unwrap().1;
println!("Connecting to {addr}"); println!("Connecting to {addr}");
let mut target = TcpStream::connect(addr).unwrap(); let mut target = TcpStream::connect(addr).unwrap();
let mut target_t = target.try_clone().unwrap(); let mut target_t = target.try_clone().unwrap();
let mut client_t = client.try_clone().unwrap(); let mut client_t = client.try_clone().unwrap();
println!("Connected to {addr}"); println!("Connected to {addr}");
client.write_all("CONN EST".as_bytes()).unwrap(); client.write_all("CONN EST".as_bytes()).unwrap();
std::thread::spawn(move || {
loop {
let mut buf = [0; 2048];
let buf_len = client_t.read(&mut buf).unwrap();
if buf_len == 0 {
target_t.shutdown(std::net::Shutdown::Both).unwrap();
break;
}
target_t.write_all(&buf[..buf_len]).unwrap();
}
});
std::thread::spawn(move || {
loop { loop {
let mut buf = [0; 2048]; let mut buf = [0; 2048];
let buf_len = client_t.read(&mut buf).unwrap(); let buf_len = target.read(&mut buf).unwrap();
if buf_len == 0 { if buf_len == 0 {
target_t.shutdown(std::net::Shutdown::Both).unwrap(); client.shutdown(std::net::Shutdown::Both).unwrap();
break; break;
} }
println!("Client -> Target {:?}", &buf[..buf_len]); client.write_all(&buf[..buf_len]).unwrap();
target_t.write_all(&buf[..buf_len]).unwrap();
} }
}); } else {
let req = crate::Request::from_str(
loop { DEFAULT_HOST,
let mut buf = [0; 2048]; &String::from_utf8_lossy(&buf[..buf_len]),
let buf_len = target.read(&mut buf).unwrap(); );
if buf_len == 0 { client.write_all(&req.send_bytes()).unwrap();
client.shutdown(std::net::Shutdown::Both).unwrap(); client.flush().unwrap();
break;
}
println!("Target -> Client {:?}", &buf[..buf_len]);
client.write_all(&buf[..buf_len]).unwrap();
} }
} });
} }
Err(_) => {} Err(_) => {}