extern crate env_logger; extern crate futures; #[macro_use] extern crate log; extern crate tokio_core; extern crate tokio_io; extern crate tokio_socks5; extern crate trust_dns_resolver; use std::net::{IpAddr, SocketAddr}; use std::str::FromStr; use std::io; use futures::{future, Future, Stream}; use tokio_core::net::{TcpListener, TcpStream}; use tokio_core::reactor::Core; use tokio_io::io::copy; use tokio_io::AsyncRead; use trust_dns_resolver::ResolverFuture; fn main() { drop(env_logger::init()); let addr = "127.0.0.1:8080".parse().unwrap(); let mut lp = Core::new().unwrap(); let handle = lp.handle(); let listener = TcpListener::bind(&addr, &handle).unwrap(); let resolver = ResolverFuture::from_system_conf(&handle).unwrap(); println!("Listening for socks5 proxy connections on {}", addr); let streams = listener.incoming().and_then(|(socket, addr)| { debug!("{}", addr); tokio_socks5::serve(socket) }); let server = streams.for_each(move |(c1, host, port)| { println!("{}", addr); println!("remote address: {}:{}", host, port); let handle1 = handle.clone(); let look_up = resolve(&host, &resolver); let pair = look_up .and_then(move |addr| { TcpStream::connect(&SocketAddr::new(addr, port), &handle1).map(|c2| (c1, c2)) }); let pipe = pair.and_then(|(c1, c2)| { let (reader1, writer1) = c1.split(); let (reader2, writer2) = c2.split(); let half1 = copy(reader1, writer2); let half2 = copy(reader2, writer1); half1.join(half2).map(|(h1, h2)| (h1.0, h2.0)) }); let finish = pipe.map(|data| { println!("received {} bytes, responsed {} bytes", data.0, data.1) }).map_err(|e| info!("{}", e)); handle.spawn(finish); Ok(()) }); lp.run(server).unwrap(); } fn resolve(host: &str, resolver: &ResolverFuture) -> Box> { if let Ok(addr) = IpAddr::from_str(&host) { return Box::new(future::ok(addr)); } let look_up = resolver.lookup_ip(&host); let res = look_up .and_then(move |res| if let Some(addr) = res.iter().next() { future::ok(addr) } else { future::err(io::Error::new( io::ErrorKind::Other, "resolve fail".to_string(), )) }); Box::new(res) }