@@ -4,6 +4,8 @@ use std::net::IpAddr;
4
4
use std:: net:: SocketAddr ;
5
5
use fast_socks5:: util:: target_addr:: TargetAddr ;
6
6
use fast_socks5:: client:: { Config , Socks5Stream } ;
7
+ use tokio:: net:: TcpStream ;
8
+ use tokio:: net:: TcpListener ;
7
9
8
10
#[ derive( err_derive:: Error , Debug ) ]
9
11
#[ error( no_from) ]
@@ -14,6 +16,12 @@ pub enum Error {
14
16
BindTempSocket ( #[ error( source) ] io:: Error ) ,
15
17
#[ error( display = "Failed to find free port" ) ]
16
18
GetTempAddress ( #[ error( source) ] io:: Error ) ,
19
+ #[ error( display = "Failed to bind TCP listener" ) ]
20
+ BindTcpListener ( #[ error( source) ] io:: Error ) ,
21
+ #[ error( display = "Failed to get TCP listener local addr" ) ]
22
+ GetTcpListenerAddress ( #[ error( source) ] io:: Error ) ,
23
+ #[ error( display = "Failed to connect client to remote" ) ]
24
+ ConnectToRemote ( #[ error( source) ] io:: Error ) ,
17
25
}
18
26
19
27
pub struct Handle {
@@ -57,54 +65,35 @@ pub async fn spawn(bind_addr: SocketAddr) -> Result<Handle, Error> {
57
65
Ok ( Handle { handle, bind_addr } )
58
66
}
59
67
60
- /// Spawn a SOCKS server that forwards everything via another SOCKS server at `via_socks_server`
61
- pub async fn spawn_via ( bind_addr : SocketAddr , via_socks_server : SocketAddr ) -> Result < Handle , Error > {
62
- let bind_addr = match bind_addr. port ( ) {
63
- 0 => SocketAddr :: new ( bind_addr. ip ( ) , find_free_port ( bind_addr. ip ( ) ) ?) ,
64
- _ => bind_addr,
65
- } ;
66
- let socks_server: fast_socks5:: server:: Socks5Server =
67
- fast_socks5:: server:: Socks5Server :: bind ( bind_addr)
68
- . await
69
- . map_err ( Error :: StartSocksServer ) ?;
68
+ /// Forward TCP traffic via `proxy_addr`
69
+ pub async fn forward ( bind_addr : SocketAddr , proxy_addr : SocketAddr ) -> Result < Handle , Error > {
70
+ let listener = TcpListener :: bind ( & bind_addr) . await . map_err ( Error :: BindTcpListener ) ?;
71
+ let bind_addr = listener. local_addr ( ) . map_err ( Error :: GetTcpListenerAddress ) ?;
70
72
71
73
let handle = tokio:: spawn ( async move {
72
- let mut incoming = socks_server. incoming ( ) ;
73
-
74
- while let Some ( new_client) = incoming. next ( ) . await {
75
- match new_client {
76
- Ok ( mut socket) => {
77
- let ( target_host, target_port) = match socket. target_addr ( ) . cloned ( ) {
78
- Some ( TargetAddr :: Domain ( host, port) ) => ( host, port) ,
79
- Some ( TargetAddr :: Ip ( addr) ) => ( addr. ip ( ) . to_string ( ) , addr. port ( ) ) ,
80
- None => {
81
- log:: error!( "missing target address" ) ;
82
- continue ;
83
- }
84
- } ;
85
-
86
- let mut client = match Socks5Stream :: connect (
87
- via_socks_server,
88
- target_host,
89
- target_port,
90
- Config :: default ( ) ,
91
- ) . await {
92
- Ok ( client) => client,
93
- Err ( error) => {
94
- log:: error!( "failed to connect client to proxy: {error}" ) ;
95
- continue ;
96
- }
97
- } ;
98
-
74
+ loop {
75
+ match listener. accept ( ) . await {
76
+ Ok ( ( mut client, _addr) ) => {
77
+ // FIXME: close these tasks
99
78
tokio:: spawn ( async move {
100
- match tokio:: io:: copy_bidirectional ( & mut client, & mut socket) . await {
101
- Ok ( _socket) => log:: info!( "socks client disconnected" ) ,
102
- Err ( error) => log:: error!( "socks client failed: {error}" ) ,
79
+ let mut proxy = match TcpStream :: connect ( proxy_addr) . await {
80
+ Ok ( proxy) => proxy,
81
+ Err ( error) => {
82
+ log:: error!( "failed to connect to TCP proxy: {error}" ) ;
83
+ return ;
84
+ }
85
+ } ;
86
+
87
+ match tokio:: io:: copy_bidirectional ( & mut client, & mut proxy) . await {
88
+ Ok ( ( a_bytes, b_bytes) ) => {
89
+ log:: info!( "wrote {a_bytes} <-> {b_bytes} bytes, client <-> proxy" ) ;
90
+ }
91
+ Err ( error) => log:: error!( "copy_directional failed: {error}" ) ,
103
92
}
104
93
} ) ;
105
94
}
106
95
Err ( error) => {
107
- log:: error!( "failed to accept socks client: {error}" ) ;
96
+ log:: error!( "failed to accept TCP client: {error}" ) ;
108
97
}
109
98
}
110
99
}
0 commit comments