💾 Archived View for 80h.dev › projects › gemserv › files › src › revproxy.rs.gemini captured on 2022-04-29 at 12:33:47. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2022-03-01)
-=-=-=-=-=-=-
01 #![cfg(feature = "proxy")]
02 use openssl::ssl::{SslConnector, SslMethod};
03 use std::io;
04 use std::net::ToSocketAddrs;
05 use tokio::io::{AsyncReadExt, AsyncWriteExt};
06 use tokio::net::TcpStream;
07
08 use crate::conn;
09 use crate::logger;
10 use crate::status::Status;
11
12 pub async fn proxy(addr: String, u: url::Url, mut con: conn::Connection) -> Result<(), io::Error> {
13 let p: Vec<&str> = u.path().trim_start_matches("/").splitn(2, "/").collect();
14 if p.len() == 1 {
15 logger::logger(con.peer_addr, Status::NotFound, u.as_str());
16 con.send_status(Status::NotFound, None).await?;
17 return Ok(());
18 }
19 if p[1] == "" || p[1] == "/" {
20 logger::logger(con.peer_addr, Status::NotFound, u.as_str());
21 con.send_status(Status::NotFound, None).await?;
22 return Ok(());
23 }
24 let addr = addr
25 .to_socket_addrs()?
26 .next()
27 .ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?;
28
29 let mut connector = SslConnector::builder(SslMethod::tls()).unwrap();
30 connector.set_verify(openssl::ssl::SslVerifyMode::NONE);
31 let config = connector.build().configure().unwrap();
32
33 let stream = match TcpStream::connect(&addr).await {
34 Ok(s) => s,
35 Err(_) => {
36 logger::logger(con.peer_addr, Status::ProxyError, u.as_str());
37 con.send_status(Status::ProxyError, None).await?;
38 return Ok(());
39 }
40 };
41 let mut stream = match tokio_openssl::connect(config, "localhost", stream).await {
42 Ok(s) => s,
43 Err(_) => {
44 logger::logger(con.peer_addr, Status::ProxyError, u.as_str());
45 con.send_status(Status::ProxyError, None).await?;
46 return Ok(());
47 }
48 };
49 stream.write_all(p[1].as_bytes()).await?;
50 stream.flush().await?;
51
52 let mut buf = vec![];
53 stream.read_to_end(&mut buf).await?;
54 // let req = String::from_utf8(buf[..].to_vec()).unwrap();
55 con.send_raw(&buf).await?;
56 Ok(())
57 }
58
59 pub async fn proxy_all(addr: &str, u: url::Url, mut con: conn::Connection) -> Result<(), io::Error> {
60 let mut connector = SslConnector::builder(SslMethod::tls()).unwrap();
61 connector.set_verify(openssl::ssl::SslVerifyMode::NONE);
62 let config = connector.build().configure().unwrap();
63
64 // TCP handshake
65 let stream = match TcpStream::connect(&addr).await {
66 Ok(s) => s,
67 Err(_) => {
68 logger::logger(con.peer_addr, Status::ProxyError, u.as_str());
69 con.send_status(Status::ProxyError, None).await?;
70 return Ok(());
71 }
72 };
73 let domain = addr.splitn(2, ':').next().unwrap();
74
75 // TLS handshake with SNI
76 let mut stream = match tokio_openssl::connect(config, domain, stream).await {
77 Ok(s) => s,
78 Err(_) => {
79 logger::logger(con.peer_addr, Status::ProxyError, u.as_str());
80 con.send_status(Status::ProxyError, None).await?;
81 return Ok(());
82 }
83 };
84
85 // send request: URL + CRLF
86 stream.write_all(u.as_ref().as_bytes()).await?;
87 stream.write_all(b"\r\n").await?;
88 stream.flush().await?;
89
90 // stream to client
91 con.send_stream(&mut stream).await?;
92 Ok(())
93 }