use anyhow::Result;
use clap::{App, Arg};
use socksx::{Socks5Client, Socks6Client};
use tokio::io::AsyncWriteExt;
#[tokio::main]
async fn main() -> Result<()> {
let args = App::new("Client")
.arg(
Arg::new("VERSION")
.short('s')
.long("socks")
.about("The SOCKS version to use")
.possible_values(&["5", "6"])
.default_value("6"),
)
.arg(
Arg::new("PROXY_HOST")
.about("The IP/hostname of the proxy")
.default_value("127.0.0.1"),
)
.arg(
Arg::new("PROXY_PORT")
.about("The port of the proxy server")
.default_value("1080"),
)
.arg(
Arg::new("DEST_HOST")
.about("The IP/hostname of the destination")
.default_value("127.0.0.1"),
)
.arg(
Arg::new("DEST_PORT")
.about("The port of the destination server")
.default_value("12345"),
)
.get_matches();
let proxy_host = args.value_of("PROXY_HOST").unwrap();
let proxy_port = args.value_of("PROXY_PORT").unwrap();
let proxy_addr = format!("{}:{}", proxy_host, proxy_port);
let dest_host = args.value_of("DEST_HOST").unwrap();
let dest_port = args.value_of("DEST_PORT").unwrap();
let dest_addr = format!("{}:{}", dest_host, dest_port);
match args.value_of("VERSION") {
Some("5") => connect_v5(proxy_addr, dest_addr).await,
Some("6") => connect_v6(proxy_addr, dest_addr).await,
Some(version) => panic!("Unsupported version: {}", version),
None => unreachable!(),
}
}
async fn connect_v5(
proxy_addr: String,
dest_addr: String,
) -> Result<()> {
let client = Socks5Client::new(proxy_addr, None).await?;
let (mut outgoing, _) = client.connect(dest_addr).await?;
outgoing.write(String::from("Hello, world!\n").as_bytes()).await?;
Ok(())
}
async fn connect_v6(
proxy_addr: String,
dest_addr: String,
) -> Result<()> {
let client = Socks6Client::new(proxy_addr, None).await?;
let (mut outgoing, _) = client.connect(dest_addr, None, None).await?;
outgoing.write(String::from("Hello, world!\n").as_bytes()).await?;
Ok(())
}