1+ use super :: proxy:: { socks5, socks5_config:: random_auth} ;
2+ use multiaddr:: { MultiAddr , Protocol } ;
13pub use tokio:: {
24 net:: { TcpListener , TcpStream } ,
35 spawn,
46 task:: { JoinHandle , block_in_place, spawn_blocking, yield_now} ,
57} ;
68
7- use crate :: service:: config:: { TcpSocket , TcpSocketConfig } ;
9+ use crate :: service:: config:: {
10+ TcpSocket , TcpSocketConfig , TcpSocketTransformer , TransformerContext ,
11+ } ;
812use socket2:: { Domain , Protocol as SocketProtocol , Socket , Type } ;
913#[ cfg( unix) ]
1014use std:: os:: unix:: io:: { FromRawFd , IntoRawFd } ;
@@ -88,7 +92,8 @@ pub(crate) fn listen(addr: SocketAddr, tcp_config: TcpSocketConfig) -> io::Resul
8892 // user can disable it on tcp_config
8993 #[ cfg( not( windows) ) ]
9094 socket. set_reuse_address ( true ) ?;
91- let t = tcp_config ( TcpSocket { inner : socket } ) ?;
95+ let transformer_context = TransformerContext :: new_listen ( addr) ;
96+ let t = ( tcp_config. socket_transformer ) ( TcpSocket { inner : socket } , transformer_context) ?;
9297 t. inner . set_nonblocking ( true ) ?;
9398 // safety: fd convert by socket2
9499 unsafe {
@@ -113,15 +118,16 @@ pub(crate) fn listen(addr: SocketAddr, tcp_config: TcpSocketConfig) -> io::Resul
113118 socket. listen ( 1024 )
114119}
115120
116- pub ( crate ) async fn connect (
121+ async fn connect_direct (
117122 addr : SocketAddr ,
118- tcp_config : TcpSocketConfig ,
123+ socket_transformer : TcpSocketTransformer ,
119124) -> io:: Result < TcpStream > {
120125 let domain = Domain :: for_address ( addr) ;
121126 let socket = Socket :: new ( domain, Type :: STREAM , Some ( SocketProtocol :: TCP ) ) ?;
122127
123128 let socket = {
124- let t = tcp_config ( TcpSocket { inner : socket } ) ?;
129+ let transformer_context = TransformerContext :: new_dial ( addr) ;
130+ let t = socket_transformer ( TcpSocket { inner : socket } , transformer_context) ?;
125131 t. inner . set_nonblocking ( true ) ?;
126132 // safety: fd convert by socket2
127133 unsafe {
@@ -135,3 +141,106 @@ pub(crate) async fn connect(
135141
136142 socket. connect ( addr) . await
137143}
144+
145+ async fn connect_by_proxy (
146+ target_addr : String ,
147+ target_port : u16 ,
148+ mut proxy_server_url : url:: Url ,
149+ proxy_random_socks_auth : bool ,
150+ ) -> io:: Result < TcpStream > {
151+ if proxy_random_socks_auth {
152+ // Generate random username and password for authentication
153+ if proxy_server_url. username ( ) . is_empty ( ) {
154+ let ( random_username, random_passwd) = random_auth ( ) ;
155+ proxy_server_url
156+ . set_username ( & random_username)
157+ . map_err ( |_| io:: Error :: other ( "failed to set username" ) ) ?;
158+ proxy_server_url
159+ . set_password ( Some ( & random_passwd) )
160+ . map_err ( |_| io:: Error :: other ( "failed to set password" ) ) ?;
161+ } else {
162+ // if username is not empty, then use the original username and password
163+ }
164+ }
165+
166+ socks5:: connect ( proxy_server_url. clone ( ) , target_addr. clone ( ) , target_port)
167+ . await
168+ . map_err ( |err| {
169+ io:: Error :: new (
170+ io:: ErrorKind :: Other ,
171+ format ! (
172+ "socks5_connect to target_addr: {}, target_port: {} by proxy_server: {} failed, err: {}" ,
173+ target_addr, target_port, proxy_server_url, err
174+ ) ,
175+ )
176+ } )
177+ }
178+
179+ pub ( crate ) async fn connect (
180+ target_addr : SocketAddr ,
181+ tcp_config : TcpSocketConfig ,
182+ ) -> io:: Result < TcpStream > {
183+ let TcpSocketConfig {
184+ socket_transformer,
185+ proxy_url,
186+ onion_url : _,
187+ proxy_random_socks_auth,
188+ } = tcp_config;
189+
190+ match proxy_url {
191+ Some ( proxy_url) => connect_by_proxy (
192+ target_addr. ip ( ) . to_string ( ) ,
193+ target_addr. port ( ) ,
194+ proxy_url. clone ( ) ,
195+ proxy_random_socks_auth,
196+ )
197+ . await
198+ . map_err ( |err| {
199+ io:: Error :: new (
200+ io:: ErrorKind :: Other ,
201+ format ! ( "connect_by_proxy: {}, error: {}" , proxy_url, err) ,
202+ )
203+ } ) ,
204+ None => connect_direct ( target_addr, socket_transformer) . await ,
205+ }
206+ }
207+
208+ pub ( crate ) async fn connect_onion (
209+ onion_addr : MultiAddr ,
210+ tcp_config : TcpSocketConfig ,
211+ ) -> io:: Result < TcpStream > {
212+ let TcpSocketConfig {
213+ socket_transformer : _,
214+ proxy_url,
215+ onion_url,
216+ proxy_random_socks_auth,
217+ } = tcp_config;
218+ let tor_server_url = onion_url. or ( proxy_url) . ok_or ( io:: Error :: other (
219+ "need tor proxy server to connect to onion address" ,
220+ ) ) ?;
221+
222+ let onion_protocol = onion_addr
223+ . iter ( )
224+ . find_map ( |protocol| {
225+ if let Protocol :: Onion3 ( onion_address) = protocol {
226+ Some ( onion_address)
227+ } else {
228+ None
229+ }
230+ } )
231+ . ok_or ( io:: Error :: other ( format ! (
232+ "No Onion3 address found. in {}" ,
233+ onion_addr
234+ ) ) ) ?;
235+
236+ let onion_str = onion_protocol. hash_string ( ) + ".onion" ;
237+ let onion_port = onion_protocol. port ( ) ;
238+
239+ connect_by_proxy (
240+ onion_str,
241+ onion_port,
242+ tor_server_url,
243+ proxy_random_socks_auth,
244+ )
245+ . await
246+ }
0 commit comments