Working example
This commit is contained in:
+1
-1
@@ -2,6 +2,6 @@ fn main() {
|
||||
ghostnet_rs::server::run().unwrap();
|
||||
// println!(
|
||||
// "Result: {}",
|
||||
// ghostnet_rs::request("localhost", "github.com")
|
||||
// ghostnet_rs::request("0.0.0.0:3000", "github.com")
|
||||
// );
|
||||
}
|
||||
|
||||
+80
-40
@@ -1,38 +1,23 @@
|
||||
use std::error::Error as StdError;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::TcpListener;
|
||||
use std::sync::Arc;
|
||||
use std::str::FromStr;
|
||||
|
||||
use rustls::Stream;
|
||||
use rustls::pki_types::pem::PemObject;
|
||||
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
|
||||
use reqwest::Version;
|
||||
use reqwest::blocking::Client;
|
||||
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
||||
|
||||
pub fn run() -> Result<(), Box<dyn StdError>> {
|
||||
let cert_file = "cert.pem";
|
||||
let private_key_file = "key.pem";
|
||||
|
||||
let certs = CertificateDer::pem_file_iter(cert_file)
|
||||
.unwrap()
|
||||
.map(|cert| cert.unwrap())
|
||||
.collect();
|
||||
|
||||
let private_key = PrivateKeyDer::from_pem_file(private_key_file).unwrap();
|
||||
|
||||
let config = Arc::new(
|
||||
rustls::ServerConfig::builder()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(certs, private_key)?,
|
||||
);
|
||||
|
||||
let listener = TcpListener::bind(format!("0.0.0.0:{}", 443)).unwrap();
|
||||
pub fn run() -> reqwest::Result<()> {
|
||||
let listener = TcpListener::bind(format!(
|
||||
"0.0.0.0:{}",
|
||||
std::env::var("PORT").unwrap_or_else(|_| "3000".into())
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
let (mut tcp_stream, _) = listener.accept()?;
|
||||
let mut conn = rustls::ServerConnection::new(config.clone())?;
|
||||
let mut tls_stream = rustls::Stream::new(&mut conn, &mut tcp_stream);
|
||||
let (mut stream, _) = listener.accept().unwrap();
|
||||
|
||||
let mut buf = [0; 1024];
|
||||
if let Ok(len) = tls_stream.read(&mut buf) {
|
||||
if let Ok(len) = stream.read(&mut buf) {
|
||||
let buf_str = String::from_utf8_lossy(&buf[..len]).to_string();
|
||||
if buf_str.starts_with("ROUTE") {
|
||||
let addr = buf_str
|
||||
@@ -43,25 +28,80 @@ pub fn run() -> Result<(), Box<dyn StdError>> {
|
||||
.unwrap()
|
||||
.1;
|
||||
let http = buf_str.split_once("\n").unwrap().1;
|
||||
tls_stream
|
||||
.write_all(&send_request(addr, http.as_bytes()))
|
||||
stream
|
||||
.write_all(send_request(addr, http)?.as_bytes())
|
||||
.unwrap();
|
||||
tls_stream.flush()?;
|
||||
stream.flush().unwrap();
|
||||
} else {
|
||||
tls_stream
|
||||
.write_all(&send_request("github.com", buf_str.as_bytes()))
|
||||
stream
|
||||
.write_all(send_request("https://wikipedia.org", "GET / HTTP/1.1")?.as_bytes())
|
||||
.unwrap();
|
||||
tls_stream.flush()?;
|
||||
stream.flush().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn send_request(addr: &str, buf: &[u8]) -> Vec<u8> {
|
||||
let (mut conn, mut tcp) = crate::tls::mask_tls(addr).unwrap();
|
||||
let mut tls = Stream::new(&mut conn, &mut tcp);
|
||||
tls.write_all(buf).unwrap();
|
||||
let mut resp = Vec::new();
|
||||
tls.read_to_end(&mut resp).unwrap();
|
||||
resp
|
||||
fn send_request(url: &str, request: &str) -> reqwest::Result<String> {
|
||||
let client = Client::new();
|
||||
let mut lines = request.lines();
|
||||
|
||||
let request_line = lines.next().unwrap();
|
||||
let mut parts = request_line.split_whitespace();
|
||||
let method = parts.next().unwrap_or("GET");
|
||||
// Ignore version for now
|
||||
|
||||
let mut headers = Vec::new();
|
||||
for line in lines.clone() {
|
||||
if line.is_empty() {
|
||||
break; // end of headers
|
||||
}
|
||||
if let Some((key, value)) = line.split_once(':') {
|
||||
headers.push((
|
||||
HeaderName::from_str(key.trim()).unwrap(),
|
||||
HeaderValue::from_str(value.trim()).unwrap(),
|
||||
));
|
||||
// headers.insert(, );
|
||||
}
|
||||
}
|
||||
|
||||
let body: String = lines.collect::<Vec<_>>().join("\n");
|
||||
|
||||
let builder = match method {
|
||||
"GET" => client.get(url),
|
||||
"POST" => client.post(url).body(body.clone()),
|
||||
"PUT" => client.put(url).body(body.clone()),
|
||||
"DELETE" => client.delete(url),
|
||||
_ => client.get(url),
|
||||
}
|
||||
.headers(HeaderMap::from_iter(headers.into_iter()));
|
||||
|
||||
let resp = builder.send()?;
|
||||
|
||||
let mut http_string = String::new();
|
||||
|
||||
http_string.push_str(&format!(
|
||||
"HTTP/{} {} {}\r\n",
|
||||
match resp.version() {
|
||||
Version::HTTP_09 => "0.9",
|
||||
Version::HTTP_10 => "1.0",
|
||||
Version::HTTP_11 => "1.1",
|
||||
Version::HTTP_2 => "2.0",
|
||||
Version::HTTP_3 => "3.0",
|
||||
_ => "2.0",
|
||||
},
|
||||
resp.status().as_u16(),
|
||||
resp.status().canonical_reason().unwrap_or("")
|
||||
));
|
||||
|
||||
for (key, value) in resp.headers().iter() {
|
||||
http_string.push_str(&format!("{}: {}\r\n", key, value.to_str().unwrap()));
|
||||
}
|
||||
|
||||
http_string.push_str("\r\n");
|
||||
|
||||
let body = resp.text()?;
|
||||
http_string.push_str(&body);
|
||||
|
||||
Ok(http_string)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use rustls::ClientConfig;
|
||||
use rustls::client::ClientConnection;
|
||||
use rustls_native_certs;
|
||||
use std::{net::TcpStream, sync::Arc};
|
||||
|
||||
pub fn mask_tls<'a>(
|
||||
|
||||
Reference in New Issue
Block a user