mod socks5;
mod trojan;
mod tls;
mod common;
use tokio::{sync::mpsc::Receiver, io::{AsyncReadExt, AsyncWriteExt}};
#[derive(Debug)]
pub struct Proxy {
client_addr: String,
client_port: u16,
server_addr: String,
server_port: u16,
passwd: String,
sni: String,
}
impl Proxy {
pub fn new(client_addr: &str,client_port: u16,server_addr:&str,server_port:u16,passwd: &str,sni: &str) ->Self {
Self {
client_addr: client_addr.to_string(),
client_port,
server_addr: server_addr.to_string(),
server_port,
passwd: passwd.to_string(),
sni: sni.to_string(),
}
}
pub async fn start(&self,recv: &mut Receiver<bool>) -> tokio::io::Result<()> {
log::info!("Trojan start...");
let addr = format!("{}:{}",self.client_addr,self.client_port);
let acceptor = socks5::Socks5Acceptor::new(&addr).await?;
loop {
log::info!("do accept");
tokio::select! {
accept = acceptor.accept() => {
match accept {
Ok((mut stream,addr)) => {
log::info!("Received new connection from {}", addr);
let tls_connector = tls::TrojanTlsConnector::new(&self.sni, &self.server_addr,self.server_port)?;
let mut connector = trojan::TrojanConnector::new(self.passwd.as_bytes(), tls_connector)?;
match connector.connect(&addr).await {
Ok(trojan_stream) => {
socks5::Socks5Acceptor::request_ack(&mut stream).await?;
log::info!("{}: socks5 connect success", addr);
tokio::spawn(async move {
trojan::relay_tcp(trojan_stream,stream).await;
log::info!("{} connection end", addr)
});
}
Err(e) => {
log::warn!("{}: has error {}", addr, e);
}
}
},
Err(e) => log::debug!("accept has error {}",e),
};
},
_ = recv.recv() => {
log::info!("receive stop signal.");
return Ok(());
}
}
}
}
}
pub async fn client_start(addr:&str,port:u16,proxy_ip:&str, proxy_port: u16) -> tokio::io::Result<()> {
let connector = socks5::Socks5Connector::new(proxy_ip,proxy_port);
let mut stream = connector.connect(addr,port).await.unwrap();
stream.set_nodelay(true)?;
println!("get stream");
let content = vec![
"GET / HTTP/1.1",
"Host: www.google.com",
"User-Agent: curl/7.64.0",
"Accept: */*",
];
for i in content {
stream.write_all(i.to_string().as_bytes()).await?;
stream.write_u16(0x0D0A).await?;
}
stream.write_u16(0x0D0A).await?;
println!("send end");
let mut frame = String::new();
loop {
let mut buf = Vec::new();
let len = stream.read_buf(&mut buf).await?;
if len == 0 {
println!("[client] read end...");
break;
}
println!("len={}",len);
frame = frame + &String::from_utf8(buf).unwrap();
println!("frame:{}",frame);
let lines:Vec<&str> = frame.split("\r\n").collect();
if !lines.is_empty() && lines[0].contains("OK") {
println!("response ok");
break;
}
}
Ok(())
}