@@ -7,16 +7,17 @@ use std::{
77 atomic:: { AtomicBool , Ordering } ,
88 Arc ,
99 } ,
10+ time:: Duration ,
1011} ;
1112
1213#[ cfg( feature = "local-dns-relay" ) ]
13- use std:: { net:: IpAddr , time :: Duration } ;
14+ use std:: net:: IpAddr ;
1415
1516use bloomfilter:: Bloom ;
16- use log:: { log_enabled, warn} ;
17- #[ cfg( feature = "local-dns-relay" ) ]
17+ use log:: { log_enabled, trace, warn} ;
1818use lru_time_cache:: LruCache ;
19- use spin:: Mutex ;
19+ use spin:: Mutex as SpinMutex ;
20+ use tokio:: sync:: Mutex as AsyncMutex ;
2021#[ cfg( feature = "trust-dns" ) ]
2122use trust_dns_resolver:: TokioAsyncResolver ;
2223
@@ -171,19 +172,22 @@ pub struct Context {
171172
172173 // Check for duplicated IV/Nonce, for prevent replay attack
173174 // https://github.com/shadowsocks/shadowsocks-org/issues/44
174- nonce_ppbloom : Mutex < PingPongBloom > ,
175+ nonce_ppbloom : SpinMutex < PingPongBloom > ,
175176
176177 // For Android's flow stat report
177178 #[ cfg( feature = "local-flow-stat" ) ]
178179 local_flow_statistic : ServerFlowStatistic ,
179180
180181 // For DNS relay's ACL domain name reverse lookup -- whether the IP shall be forwarded
181182 #[ cfg( feature = "local-dns-relay" ) ]
182- reverse_lookup_cache : Mutex < LruCache < IpAddr , bool > > ,
183+ reverse_lookup_cache : AsyncMutex < LruCache < IpAddr , bool > > ,
183184
184185 // For local DNS upstream
185186 #[ cfg( feature = "local-dns-relay" ) ]
186187 local_dns : LocalUpstream ,
188+
189+ // ACL check result cache
190+ acl_check_cache : AsyncMutex < LruCache < Address , bool > > ,
187191}
188192
189193/// Unique context thw whole server
@@ -224,11 +228,7 @@ impl Context {
224228 }
225229 }
226230
227- let nonce_ppbloom = Mutex :: new ( PingPongBloom :: new ( config. config_type ) ) ;
228- #[ cfg( feature = "local-dns-relay" ) ]
229- let reverse_lookup_cache = Mutex :: new ( LruCache :: < IpAddr , bool > :: with_expiry_duration ( Duration :: from_secs (
230- 3 * 24 * 60 * 60 ,
231- ) ) ) ;
231+ let nonce_ppbloom = SpinMutex :: new ( PingPongBloom :: new ( config. config_type ) ) ;
232232 #[ cfg( feature = "local-dns-relay" ) ]
233233 let local_dns = LocalUpstream :: new ( & config) ;
234234
@@ -240,9 +240,15 @@ impl Context {
240240 #[ cfg( feature = "local-flow-stat" ) ]
241241 local_flow_statistic : ServerFlowStatistic :: new ( ) ,
242242 #[ cfg( feature = "local-dns-relay" ) ]
243- reverse_lookup_cache,
243+ reverse_lookup_cache : AsyncMutex :: new ( LruCache :: with_expiry_duration ( Duration :: from_secs (
244+ 3 * 24 * 60 * 60 ,
245+ ) ) ) ,
244246 #[ cfg( feature = "local-dns-relay" ) ]
245247 local_dns,
248+ acl_check_cache : AsyncMutex :: new ( LruCache :: with_expiry_duration_and_capacity (
249+ Duration :: from_secs ( 24 * 60 * 60 ) ,
250+ 512 ,
251+ ) ) ,
246252 }
247253 }
248254
@@ -376,14 +382,14 @@ impl Context {
376382
377383 /// Add a record to the reverse lookup cache
378384 #[ cfg( feature = "local-dns-relay" ) ]
379- pub fn add_to_reverse_lookup_cache ( & self , addr : & IpAddr , forward : bool ) {
385+ pub async fn add_to_reverse_lookup_cache ( & self , addr : & IpAddr , forward : bool ) {
380386 let is_exception = forward
381387 != match self . acl ( ) {
382388 // Proxy everything by default
383389 None => true ,
384390 Some ( a) => a. check_ip_in_proxy_list ( addr) ,
385391 } ;
386- let mut reverse_lookup_cache = self . reverse_lookup_cache . lock ( ) ;
392+ let mut reverse_lookup_cache = self . reverse_lookup_cache . lock ( ) . await ;
387393 match reverse_lookup_cache. get_mut ( addr) {
388394 Some ( value) => {
389395 if is_exception {
@@ -453,7 +459,23 @@ impl Context {
453459 }
454460 }
455461 }
456- a. check_target_bypassed ( self , target) . await
462+
463+ // ACL checking may need over 500ms (DNS resolving)
464+ if let Some ( bypassed) = self . acl_check_cache . lock ( ) . await . get ( target) {
465+ trace ! (
466+ "check bypassing {} cached result: {}" ,
467+ target,
468+ if * bypassed { "bypassed" } else { "proxied" }
469+ ) ;
470+
471+ return * bypassed;
472+ }
473+
474+ let r = a. check_target_bypassed ( self , target) . await ;
475+
476+ self . acl_check_cache . lock ( ) . await . insert ( target. clone ( ) , r) ;
477+
478+ r
457479 }
458480
459481 /// Get client flow statistics
0 commit comments