Skip to content

Commit 101a6f2

Browse files
committed
Cache recently ACL checking results
ACL checking may requires lots of calculation and network I/O (DNS resolution)
1 parent d3e2922 commit 101a6f2

File tree

4 files changed

+49
-19
lines changed

4 files changed

+49
-19
lines changed

src/context.rs

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1516
use bloomfilter::Bloom;
16-
use log::{log_enabled, warn};
17-
#[cfg(feature = "local-dns-relay")]
17+
use log::{log_enabled, trace, warn};
1818
use 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")]
2122
use 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

src/relay/dnsrelay/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,16 @@ impl<Remote: upstream::Upstream> DnsRelay<Remote> {
274274
for rec in result.answers() {
275275
debug!("dns answer: {:?}", rec);
276276
match rec.rdata() {
277-
RData::A(ref ip) => self.context.add_to_reverse_lookup_cache(&IpAddr::V4(*ip), forward),
278-
RData::AAAA(ref ip) => self.context.add_to_reverse_lookup_cache(&IpAddr::V6(*ip), forward),
277+
RData::A(ref ip) => {
278+
self.context
279+
.add_to_reverse_lookup_cache(&IpAddr::V4(*ip), forward)
280+
.await
281+
}
282+
RData::AAAA(ref ip) => {
283+
self.context
284+
.add_to_reverse_lookup_cache(&IpAddr::V6(*ip), forward)
285+
.await
286+
}
279287
_ => (),
280288
}
281289
}

src/relay/socks4.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl fmt::Display for ResultCode {
111111
}
112112

113113
/// SOCKS4 Address type
114-
#[derive(Clone, PartialEq, Eq, Hash)]
114+
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
115115
pub enum Address {
116116
/// Socket address (IP Address)
117117
SocketAddress(SocketAddrV4),

src/relay/socks5.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ impl From<Error> for io::Error {
205205
}
206206

207207
/// SOCKS5 address type
208-
#[derive(Clone, PartialEq, Eq, Hash)]
208+
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
209209
pub enum Address {
210210
/// Socket address (IP Address)
211211
SocketAddress(SocketAddr),

0 commit comments

Comments
 (0)