aboutsummaryrefslogtreecommitdiff
path: root/src/proxy.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/proxy.rs')
-rw-r--r--src/proxy.rs86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/proxy.rs b/src/proxy.rs
new file mode 100644
index 0000000..ce40e6e
--- /dev/null
+++ b/src/proxy.rs
@@ -0,0 +1,86 @@
+use native_tls::TlsConnector;
+use std::io::{Read, Write};
+use std::net::{TcpListener, TcpStream};
+use std::sync::Arc;
+use std::thread::{spawn, JoinHandle};
+
+use crate::configuration::ProxyConfiguration;
+
+pub fn create_proxy(configuration: Arc<ProxyConfiguration>) -> JoinHandle<()> {
+ let cloned_configuration = Arc::clone(&configuration);
+ spawn(move || {
+ run_proxy(cloned_configuration);
+ })
+}
+
+fn run_proxy(configuration: Arc<ProxyConfiguration>) {
+ let listener = TcpListener::bind(format!("0.0.0.0:{}", configuration.local_port)).unwrap();
+
+ println!("Proxy listening on port {}", configuration.local_port);
+
+ for stream in listener.incoming() {
+ match stream {
+ Ok(stream) => {
+ let cloned_configuration = Arc::clone(&configuration);
+ spawn(move || {
+ handle_client(stream, cloned_configuration);
+ });
+ }
+ Err(e) => {
+ eprintln!("Failed to accept connection: {}", e);
+ }
+ }
+ }
+}
+
+fn handle_client(mut client_stream: TcpStream, configuration: Arc<ProxyConfiguration>) {
+ let connector = TlsConnector::new().unwrap();
+ let remote_stream = TcpStream::connect(format!(
+ "{}:{}",
+ configuration.remote_domain, configuration.remote_port
+ ))
+ .unwrap();
+ let mut remote_stream = connector
+ .connect(&configuration.remote_domain, remote_stream)
+ .unwrap();
+
+ let mut client_stream_clone = client_stream.try_clone().unwrap();
+ let mut remote_stream_clone = remote_stream.get_ref().try_clone().unwrap();
+
+ let cloned_configuration = Arc::clone(&configuration);
+ spawn(move || {
+ forward_stream(&mut client_stream, &mut remote_stream, cloned_configuration);
+ });
+ forward_stream(
+ &mut remote_stream_clone,
+ &mut client_stream_clone,
+ configuration,
+ );
+}
+
+fn forward_stream<R: Read, W: Write>(
+ from: &mut R,
+ to: &mut W,
+ configuration: Arc<ProxyConfiguration>,
+) {
+ let mut buffer = [0; 4096];
+ loop {
+ match from.read(&mut buffer) {
+ Ok(0) => break, // EOF
+ Ok(n) => {
+ if let Err(e) = to.write_all(&buffer[..n]) {
+ eprintln!("{} proxy write error: {}", configuration.protocol, e);
+ break;
+ }
+ if let Err(e) = to.flush() {
+ eprintln!("{} proxy flush error: {}", configuration.protocol, e);
+ break;
+ }
+ }
+ Err(e) => {
+ eprintln!("{} proxy read error: {}", configuration.protocol, e);
+ break;
+ }
+ }
+ }
+}