@@ -2,6 +2,8 @@ use futures::StreamExt;
2
2
use std:: io;
3
3
use std:: net:: IpAddr ;
4
4
use std:: net:: SocketAddr ;
5
+ use fast_socks5:: util:: target_addr:: TargetAddr ;
6
+ use fast_socks5:: client:: { Config , Socks5Stream } ;
5
7
6
8
#[ derive( err_derive:: Error , Debug ) ]
7
9
#[ error( no_from) ]
@@ -19,6 +21,7 @@ pub struct Handle {
19
21
bind_addr : SocketAddr ,
20
22
}
21
23
24
+ /// Spawn a SOCKS server bound to `bind_addr`
22
25
pub async fn spawn ( bind_addr : SocketAddr ) -> Result < Handle , Error > {
23
26
let bind_addr = match bind_addr. port ( ) {
24
27
0 => SocketAddr :: new ( bind_addr. ip ( ) , find_free_port ( bind_addr. ip ( ) ) ?) ,
@@ -36,6 +39,8 @@ pub async fn spawn(bind_addr: SocketAddr) -> Result<Handle, Error> {
36
39
match new_client {
37
40
Ok ( socket) => {
38
41
let fut = socket. upgrade_to_socks5 ( ) ;
42
+
43
+ // Act as normal SOCKS server
39
44
tokio:: spawn ( async move {
40
45
match fut. await {
41
46
Ok ( _socket) => log:: info!( "socks client disconnected" ) ,
@@ -52,6 +57,61 @@ pub async fn spawn(bind_addr: SocketAddr) -> Result<Handle, Error> {
52
57
Ok ( Handle { handle, bind_addr } )
53
58
}
54
59
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 ) ?;
70
+
71
+ 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
+
99
+ 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}" ) ,
103
+ }
104
+ } ) ;
105
+ }
106
+ Err ( error) => {
107
+ log:: error!( "failed to accept socks client: {error}" ) ;
108
+ }
109
+ }
110
+ }
111
+ } ) ;
112
+ Ok ( Handle { handle, bind_addr } )
113
+ }
114
+
55
115
impl Handle {
56
116
pub fn bind_addr ( & self ) -> SocketAddr {
57
117
self . bind_addr
0 commit comments