1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use std::net::SocketAddr;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream};
use tracing::{info, warn};
use crate::modules::hex_encode;
pub struct ProxyListener {
pub local_addr: SocketAddr,
pub target_addr: SocketAddr,
}
impl ProxyListener {
pub async fn spawn(target_ip: &str, target_port: u16) -> anyhow::Result<Self> {
let listener = TcpListener::bind("127.0.0.1:0").await?;
let local_addr = listener.local_addr()?;
let target_str = format!("{}:{}", target_ip, target_port);
let target_addr: SocketAddr = tokio::net::lookup_host(&target_str)
.await?
.next()
.ok_or_else(|| anyhow::anyhow!("could not resolve hostname: {}", target_ip))?;
tokio::spawn(async move {
if let Ok((mut client_stream, _client_addr)) = listener.accept().await {
info!("Proxy accepted connection for {}", target_addr);
match tokio::time::timeout(
std::time::Duration::from_secs(5),
TcpStream::connect(target_addr),
)
.await
{
Ok(Ok(mut target_stream)) => {
let (mut cr, mut cw) = client_stream.split();
let (mut tr, mut tw) = target_stream.split();
let client_to_target = async {
let mut buf = vec![0u8; 8192];
loop {
match cr.read(&mut buf).await {
Ok(0) => break,
Ok(n) => {
info!(
"Proxy C->S {} bytes: {}",
n,
hex_encode(&buf[..n.min(32)])
);
if tw.write_all(&buf[..n]).await.is_err() {
break;
}
}
Err(_) => break,
}
}
};
let target_to_client = async {
let mut buf = vec![0u8; 8192];
loop {
match tr.read(&mut buf).await {
Ok(0) => break,
Ok(n) => {
info!(
"Proxy S->C {} bytes: {}",
n,
hex_encode(&buf[..n.min(32)])
);
if cw.write_all(&buf[..n]).await.is_err() {
break;
}
}
Err(_) => break,
}
}
};
tokio::select! {
_ = client_to_target => {}
_ = target_to_client => {}
}
}
Ok(Err(e)) => warn!("Proxy failed to connect to target {}: {}", target_addr, e),
Err(_) => warn!("Proxy connect timeout to target {}", target_addr),
}
}
});
Ok(Self {
local_addr,
target_addr,
})
}
}