Working example
This commit is contained in:
Generated
+1139
-48
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -7,6 +7,7 @@ edition = "2024"
|
|||||||
name = "ghostnet-rs"
|
name = "ghostnet-rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rcgen = "0.14.3"
|
reqwest = { version = "0.12.23", features = ["blocking"] }
|
||||||
rustls = "0.23.31"
|
rustls = "0.23.31"
|
||||||
rustls-native-certs = "0.8.1"
|
rustls-native-certs = "0.8.1"
|
||||||
|
rustls-pki-types = "1.12.0"
|
||||||
|
|||||||
@@ -24,4 +24,10 @@ A router manages the clients and routes messages from one client to another to e
|
|||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
- End-To-End Encryption
|
- End-To-End Encryption
|
||||||
- Mask the communications like **HTTPS**
|
- Mask the communications like **HTTPS**
|
||||||
|
|
||||||
|
## Common install issues on linux
|
||||||
|
```bash
|
||||||
|
sudo apt install pkg-config -y
|
||||||
|
sudo apt install libssl-dev -y
|
||||||
|
```
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEETCCAvmgAwIBAgIUWwIPF1mmJWJhEqSg6mKOUPHnHIQwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwgZcxCzAJBgNVBAYTAkFMMQ8wDQYDVQQIDAZUaXJhbmExDzANBgNVBAcMBlRp
|
|
||||||
cmFuYTENMAsGA1UECgwET3J1czERMA8GA1UECwwIZ2hvc3RuZXQxGzAZBgNVBAMM
|
|
||||||
Ekdob3N0TmV0IEdhdGV3YXkgMTEnMCUGCSqGSIb3DQEJARYYa2xlc3Quc2VsaW1h
|
|
||||||
eUBpY2xvdWQuY29tMB4XDTI1MDgxNDE5MDg0MVoXDTI2MDgxNDE5MDg0MVowgZcx
|
|
||||||
CzAJBgNVBAYTAkFMMQ8wDQYDVQQIDAZUaXJhbmExDzANBgNVBAcMBlRpcmFuYTEN
|
|
||||||
MAsGA1UECgwET3J1czERMA8GA1UECwwIZ2hvc3RuZXQxGzAZBgNVBAMMEkdob3N0
|
|
||||||
TmV0IEdhdGV3YXkgMTEnMCUGCSqGSIb3DQEJARYYa2xlc3Quc2VsaW1heUBpY2xv
|
|
||||||
dWQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuq8OgFXwW9Jz
|
|
||||||
TRA9D/NKohcYh7RINljUamp9n95kNkCsq+SDJTw9PIO7wAD7feKQwXxeHV3bcE9F
|
|
||||||
TMt2fXY20pWDkypEVFJVq4SLU25uQ6ufbjJJ9f/YEkV2dwAOdLz9j9QSkS3tEzCr
|
|
||||||
b4XAT/5Wh2AU8vbwA6MR/zQxq6qoa9UMuyLvMgJxwpx2SI7Nupfb4J2QJzVV0wKh
|
|
||||||
aXwBDBmHrd2q4Yr78mdAx/ILQKehFGsrYG4w9op9jYGid3Gh8D3dpzBS+T3PKxGk
|
|
||||||
b5NPQN2TYMFY5wcLs8f01WWVKSE4G/GgF1XKlPyu93uKZS/coJKHCu8r6ZdriuST
|
|
||||||
UyyqrxtBYwIDAQABo1MwUTAdBgNVHQ4EFgQU/hD7pMQLE9fDB1zhRfoJ1b7NfcIw
|
|
||||||
HwYDVR0jBBgwFoAU/hD7pMQLE9fDB1zhRfoJ1b7NfcIwDwYDVR0TAQH/BAUwAwEB
|
|
||||||
/zANBgkqhkiG9w0BAQsFAAOCAQEAse9YdXfbGkD/jbegh6D+I1zymm7OMZJ8OXiQ
|
|
||||||
v0Aj8tvrHxK6vlxu/niTXaTRLNt0RAlft+fsF2dm1Nv629n/iPkoNTIA1TAXE5qY
|
|
||||||
jQTcJwWRxBB1ueqbltAuft2hcsULgXnNM7Dq9I+rq4ekT0DSIkjK6ku58F0QiL3a
|
|
||||||
wC8i4ISO4y2agKixPgtigKIBs7wpanSos8COvQPZYQXQgrJvGJmgqubEXcbO4Fiv
|
|
||||||
Dh/8xAW/MkiqltfvRj3IUtwZ3ZHLnFrkvxorikH1uSvo721bDobLTM+Cv5q+sSY1
|
|
||||||
4/FO+Twcs1zQeU+DOjZKfa9qf0Lc1kJ6lv7WFQ1KIslWQbNkbA==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6rw6AVfBb0nNN
|
|
||||||
ED0P80qiFxiHtEg2WNRqan2f3mQ2QKyr5IMlPD08g7vAAPt94pDBfF4dXdtwT0VM
|
|
||||||
y3Z9djbSlYOTKkRUUlWrhItTbm5Dq59uMkn1/9gSRXZ3AA50vP2P1BKRLe0TMKtv
|
|
||||||
hcBP/laHYBTy9vADoxH/NDGrqqhr1Qy7Iu8yAnHCnHZIjs26l9vgnZAnNVXTAqFp
|
|
||||||
fAEMGYet3arhivvyZ0DH8gtAp6EUaytgbjD2in2NgaJ3caHwPd2nMFL5Pc8rEaRv
|
|
||||||
k09A3ZNgwVjnBwuzx/TVZZUpITgb8aAXVcqU/K73e4plL9ygkocK7yvpl2uK5JNT
|
|
||||||
LKqvG0FjAgMBAAECggEAVpowFXwImWgrIfRnB1e7Zy9kq0uIdmHGBKnrJjdScNKW
|
|
||||||
59UFu8fStph8CCnMgU0SDxhFRsVML7Euel4m1TP6Yb2HgMVKVn2tjXha8/TWRSFA
|
|
||||||
QCwnIG40C+Haf4Dws9oanNbqWBwgj1b0KLO5D8Ly3DFH9qB0npNPHX9WjYcJQ6AS
|
|
||||||
Y1t41W2DBXNZLk173aO1G98UzqjNvwG05x/UeJxJ8cMVPE9O8hcVcT0QBwd8RK6A
|
|
||||||
vtf3BrIeS21fOGKYTqCKi0mQatUWHaeyvj09RBt9H7lsPWDzHL2blhpBZQpOn2g1
|
|
||||||
VOrVsCem7IpZLBLv8ItR6FXfPGTBXEv9CP/7RIVXAQKBgQDoo+HCNEvp/nM2wBmW
|
|
||||||
b+FSs2t4ScBPHf+yQhSkzF5Cnd4LSd7cRhYGB24JFk8AtX9I84MCPhbvHudgxIfF
|
|
||||||
nqdfDh6MsDC1FavDNkuP6j9z3VXp4y0pbAux1xg0Nb9yKT20qMZM28QhKqh2wBNo
|
|
||||||
tqIOUV8rARaiYI1u2RmdMnAbAQKBgQDNbdi3IdM00DqFfPVfWLHFpHoV9tkJHezi
|
|
||||||
4OKvI7TU+ojosu2+4tn9Drpm2M2mbYY1kK/FAGTLqh3Du3qEPnu8xWbW6pu/WAAY
|
|
||||||
ZyRTvokP1CH0JIIEfH/uZ6WBmA2ReYsuELoRWW+7W1l1rf5jRWlnuzO+yhBEP+Ou
|
|
||||||
AbayJ9DQYwKBgEepk/Wa3neqJhuLeVZaCHLNSiG3tkGo4ActS+an/bFPqAKaMshv
|
|
||||||
3oDk8QRjltqFDjyOpqCeN7pZLrUkVR6PDMe/NbHo5Fgj4NE1fHlMk1dBqyFtFZBY
|
|
||||||
9BFITPBoTh0Ajz2Db/JlEDmXRmWuLUxoVetLLaG1qB9E1sx6m+VMkDQBAoGAB0QR
|
|
||||||
XDjYDZAn4bzPuPWcJA9zOf+nIYlrbYLiwasTpEzQNtrNSekgKLEyqpyUeYR6ML7T
|
|
||||||
WLZw2jtEHj4tUSwcmEqrHoLhy1zDdBmB0Wx10JeCM+5uotX8eGQ2GGVWZYTVBWYW
|
|
||||||
DrMJHqlWerESxFQaLE8Uv3TKKn/P/8GTwq1h110CgYB/u9aKYtsR85hITdqWRq2f
|
|
||||||
fCON+9WrOfAbt/H50qEBk2xVKKSPVDrTekqMPAuTagdA5+Y/pRA9zyy6wmfDfnC6
|
|
||||||
IyxVnhWRlLnByiHcs58N7vytTWmiKHQDrXAiWyxUy0ao/2Jyb/gLkj1avIfok0r/
|
|
||||||
5DMLZeOcLmweCkEEwXAG5w==
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
+1
-1
@@ -2,6 +2,6 @@ fn main() {
|
|||||||
ghostnet_rs::server::run().unwrap();
|
ghostnet_rs::server::run().unwrap();
|
||||||
// println!(
|
// println!(
|
||||||
// "Result: {}",
|
// "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::io::{Read, Write};
|
||||||
use std::net::TcpListener;
|
use std::net::TcpListener;
|
||||||
use std::sync::Arc;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use rustls::Stream;
|
use reqwest::Version;
|
||||||
use rustls::pki_types::pem::PemObject;
|
use reqwest::blocking::Client;
|
||||||
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
|
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
||||||
|
|
||||||
pub fn run() -> Result<(), Box<dyn StdError>> {
|
pub fn run() -> reqwest::Result<()> {
|
||||||
let cert_file = "cert.pem";
|
let listener = TcpListener::bind(format!(
|
||||||
let private_key_file = "key.pem";
|
"0.0.0.0:{}",
|
||||||
|
std::env::var("PORT").unwrap_or_else(|_| "3000".into())
|
||||||
let certs = CertificateDer::pem_file_iter(cert_file)
|
))
|
||||||
.unwrap()
|
.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();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (mut tcp_stream, _) = listener.accept()?;
|
let (mut stream, _) = listener.accept().unwrap();
|
||||||
let mut conn = rustls::ServerConnection::new(config.clone())?;
|
|
||||||
let mut tls_stream = rustls::Stream::new(&mut conn, &mut tcp_stream);
|
|
||||||
|
|
||||||
let mut buf = [0; 1024];
|
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();
|
let buf_str = String::from_utf8_lossy(&buf[..len]).to_string();
|
||||||
if buf_str.starts_with("ROUTE") {
|
if buf_str.starts_with("ROUTE") {
|
||||||
let addr = buf_str
|
let addr = buf_str
|
||||||
@@ -43,25 +28,80 @@ pub fn run() -> Result<(), Box<dyn StdError>> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.1;
|
.1;
|
||||||
let http = buf_str.split_once("\n").unwrap().1;
|
let http = buf_str.split_once("\n").unwrap().1;
|
||||||
tls_stream
|
stream
|
||||||
.write_all(&send_request(addr, http.as_bytes()))
|
.write_all(send_request(addr, http)?.as_bytes())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tls_stream.flush()?;
|
stream.flush().unwrap();
|
||||||
} else {
|
} else {
|
||||||
tls_stream
|
stream
|
||||||
.write_all(&send_request("github.com", buf_str.as_bytes()))
|
.write_all(send_request("https://wikipedia.org", "GET / HTTP/1.1")?.as_bytes())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tls_stream.flush()?;
|
stream.flush().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_request(addr: &str, buf: &[u8]) -> Vec<u8> {
|
fn send_request(url: &str, request: &str) -> reqwest::Result<String> {
|
||||||
let (mut conn, mut tcp) = crate::tls::mask_tls(addr).unwrap();
|
let client = Client::new();
|
||||||
let mut tls = Stream::new(&mut conn, &mut tcp);
|
let mut lines = request.lines();
|
||||||
tls.write_all(buf).unwrap();
|
|
||||||
let mut resp = Vec::new();
|
let request_line = lines.next().unwrap();
|
||||||
tls.read_to_end(&mut resp).unwrap();
|
let mut parts = request_line.split_whitespace();
|
||||||
resp
|
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::ClientConfig;
|
||||||
use rustls::client::ClientConnection;
|
use rustls::client::ClientConnection;
|
||||||
use rustls_native_certs;
|
|
||||||
use std::{net::TcpStream, sync::Arc};
|
use std::{net::TcpStream, sync::Arc};
|
||||||
|
|
||||||
pub fn mask_tls<'a>(
|
pub fn mask_tls<'a>(
|
||||||
|
|||||||
Reference in New Issue
Block a user