Skip to content

Instantly share code, notes, and snippets.

@lewisxy
Last active October 28, 2021 23:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lewisxy/ce698e31233c65fdc791c7b882cd5f41 to your computer and use it in GitHub Desktop.
Save lewisxy/ce698e31233c65fdc791c7b882cd5f41 to your computer and use it in GitHub Desktop.
TCP proxy PoC
// testing
// 1. open server on 127.0.0.1:7979
// $ nc -l -k 127.0.0.1 7979
// 2. connects to 127.0.0.1:7878
// $ nc 127.0.0.1 7878
// proxy is close when either side closed the connection
use std::io::prelude::*;
use std::net::{TcpListener, TcpStream, Shutdown, SocketAddr};
use std::io::{copy, ErrorKind, Error};
use anyhow::{Result};
fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
let remote: SocketAddr = "127.0.0.1:7979".parse().unwrap();
for stream in listener.incoming() {
let stream = stream.unwrap();
println!("connected");
handle_connection(stream, remote);
println!("proxy completed");
break;
}
}
fn handle_connection(mut source: TcpStream, destination: SocketAddr) -> Result<()> {
// `source` and `destination` are both `TcpStream`
let mut destination = TcpStream::connect(destination)?;
let mut source_copy = source.try_clone()?;
let mut destination_copy = destination.try_clone()?;
let src2dst = std::thread::spawn(move || {
std::io::copy(&mut source_copy, &mut destination_copy).unwrap();
println!("src -> dst completed");
// client has closed connection, we need to make server aware of it
//destination_copy.shutdown(Shutdown::Both).unwrap();
// shutdown twice might result in error on macOS
match destination_copy.shutdown(Shutdown::Both) {
Err(err) => match err.kind() {
ErrorKind::NotConnected => (),
e => println!("should not happen: {:?}", e),
},
Ok(_) => ()
};
});
let dst2src = std::thread::spawn(move || {
std::io::copy(&mut destination, &mut source).unwrap();
println!("dst -> src completed");
// server has closed connection, we need to make client aware of it
//source.shutdown(Shutdown::Both).unwrap();
match source.shutdown(Shutdown::Both) {
Err(err) => match err.kind() {
ErrorKind::NotConnected => (),
e => println!("should not happen: {:?}", e),
},
Ok(_) => ()
};
});
src2dst.join().unwrap();
dst2src.join().unwrap();
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment