use ppp::v1::Addresses;
use ppp::v2::{Builder, Command, Protocol, Type, Version};
use std::env::args;
use std::io::{self, prelude::*};
use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream};
use std::thread::spawn;
use std::time::Duration;
fn handle_connection(mut client_input: TcpStream, server_address: &SocketAddr) -> io::Result<()> {
let mut server_input = TcpStream::connect_timeout(server_address, Duration::from_secs(1))?;
client_input.set_nodelay(true)?;
server_input.set_nodelay(true)?;
let mut client_output = client_input.try_clone()?;
let mut server_output = server_input.try_clone()?;
let client_to_server = spawn(move || {
let client_address = client_input.peer_addr()?;
let server_address = server_output.peer_addr()?;
match args().nth(1).as_ref().map(String::as_str) {
Some("v1") => {
println!("Writing v1 header.");
let header = Addresses::from((client_address, server_address)).to_string();
for byte in header.as_bytes() {
server_output.write_all(&[*byte])?;
server_output.flush()?;
}
}
_ => {
println!("Writing v2 header.");
let mut header = Builder::with_addresses(
Version::Two | Command::Proxy,
Protocol::Stream,
(client_address, server_address),
)
.write_tlv(Type::NoOp, b"Hello, World!")?
.build()?;
for byte in header.drain(..) {
server_output.write_all(&[byte])?;
server_output.flush()?;
}
}
}
let mut buffer = [0; 512];
client_input.read(&mut buffer)?;
server_output.write_all(&mut buffer)?;
server_output.flush()
});
let server_to_client = spawn(move || std::io::copy(&mut server_input, &mut client_output));
client_to_server.join().unwrap()?;
server_to_client.join().unwrap()?;
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let listen_address = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 8888);
let proxy_address = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 7777);
let listener = TcpListener::bind(&listen_address).unwrap();
println!("Listening on: {}", listen_address);
println!("Proxying to: {}", proxy_address);
for stream in listener.incoming() {
if let Err(error) = handle_connection(stream?, &proxy_address) {
eprintln!("[ERROR] {}", error);
}
}
Ok(())
}