shadowsocks_service/local/
context.rs1use std::sync::Arc;
4#[cfg(feature = "local-dns")]
5use std::{net::IpAddr, time::Duration};
6
7#[cfg(feature = "local-dns")]
8use lru_time_cache::LruCache;
9use shadowsocks::{
10 config::ServerType,
11 context::{Context, SharedContext},
12 dns_resolver::DnsResolver,
13 net::{AcceptOpts, ConnectOpts},
14 relay::Address,
15};
16#[cfg(feature = "local-dns")]
17use tokio::sync::Mutex;
18#[cfg(feature = "local-fake-dns")]
19use tokio::sync::RwLock;
20
21use crate::{acl::AccessControl, config::SecurityConfig, net::FlowStat};
22
23#[cfg(feature = "local-fake-dns")]
24use super::fake_dns::manager::FakeDnsManager;
25
26#[derive(Clone)]
28pub struct ServiceContext {
29 context: SharedContext,
30 connect_opts: ConnectOpts,
31 accept_opts: AcceptOpts,
32
33 acl: Option<Arc<AccessControl>>,
35
36 flow_stat: Arc<FlowStat>,
38
39 #[cfg(feature = "local-dns")]
41 reverse_lookup_cache: Arc<Mutex<LruCache<IpAddr, bool>>>,
42
43 #[cfg(feature = "local-fake-dns")]
44 fake_dns_manager: Arc<RwLock<Vec<Arc<FakeDnsManager>>>>,
45}
46
47impl Default for ServiceContext {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53impl ServiceContext {
54 pub fn new() -> Self {
56 Self {
57 context: Context::new_shared(ServerType::Local),
58 connect_opts: ConnectOpts::default(),
59 accept_opts: AcceptOpts::default(),
60 acl: None,
61 flow_stat: Arc::new(FlowStat::new()),
62 #[cfg(feature = "local-dns")]
63 reverse_lookup_cache: Arc::new(Mutex::new(LruCache::with_expiry_duration_and_capacity(
64 Duration::from_secs(3 * 24 * 60 * 60),
65 10240, ))),
67 #[cfg(feature = "local-fake-dns")]
68 fake_dns_manager: Arc::new(RwLock::new(Vec::new())),
69 }
70 }
71
72 pub fn context(&self) -> SharedContext {
74 self.context.clone()
75 }
76
77 pub fn context_ref(&self) -> &Context {
79 self.context.as_ref()
80 }
81
82 pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) {
84 self.connect_opts = connect_opts;
85 }
86
87 pub fn connect_opts_ref(&self) -> &ConnectOpts {
89 &self.connect_opts
90 }
91
92 pub fn set_accept_opts(&mut self, accept_opts: AcceptOpts) {
94 self.accept_opts = accept_opts;
95 }
96
97 pub fn accept_opts(&self) -> AcceptOpts {
99 self.accept_opts.clone()
100 }
101
102 pub fn set_acl(&mut self, acl: Arc<AccessControl>) {
104 self.acl = Some(acl);
105 }
106
107 pub fn acl(&self) -> Option<&AccessControl> {
109 self.acl.as_deref()
110 }
111
112 pub fn flow_stat(&self) -> Arc<FlowStat> {
114 self.flow_stat.clone()
115 }
116
117 pub fn flow_stat_ref(&self) -> &FlowStat {
119 self.flow_stat.as_ref()
120 }
121
122 pub fn set_dns_resolver(&mut self, resolver: Arc<DnsResolver>) {
124 let context = Arc::get_mut(&mut self.context).expect("cannot set DNS resolver on a shared context");
125 context.set_dns_resolver(resolver)
126 }
127
128 pub fn dns_resolver(&self) -> &DnsResolver {
130 self.context.dns_resolver()
131 }
132
133 pub async fn check_target_bypassed(&self, addr: &Address) -> bool {
135 match self.acl {
136 None => false,
137 Some(ref acl) => {
138 #[cfg(feature = "local-dns")]
139 {
140 if let Address::SocketAddress(saddr) = addr {
141 let mut reverse_lookup_cache = self.reverse_lookup_cache.lock().await;
143 if let Some(forward) = reverse_lookup_cache.get(&saddr.ip()) {
145 return !*forward;
146 }
147 }
148 }
149
150 acl.check_target_bypassed(&self.context, addr).await
151 }
152 }
153 }
154
155 #[cfg(feature = "local-dns")]
157 pub async fn add_to_reverse_lookup_cache(&self, addr: IpAddr, forward: bool) {
158 let is_exception = forward
159 != match self.acl {
160 None => true,
162 Some(ref a) => a.check_ip_in_proxy_list(&addr),
163 };
164 let mut reverse_lookup_cache = self.reverse_lookup_cache.lock().await;
165 match reverse_lookup_cache.get_mut(&addr) {
166 Some(value) => {
167 if is_exception {
168 *value = forward;
169 } else {
170 reverse_lookup_cache.remove(&addr);
172 }
173 }
174 None => {
175 if is_exception {
176 reverse_lookup_cache.insert(addr, forward);
177 }
178 }
179 }
180 }
181
182 pub fn set_ipv6_first(&mut self, ipv6_first: bool) {
184 let context = Arc::get_mut(&mut self.context).expect("cannot set ipv6_first on a shared context");
185 context.set_ipv6_first(ipv6_first);
186 }
187
188 pub fn set_security_config(&mut self, security: &SecurityConfig) {
190 let context = Arc::get_mut(&mut self.context).expect("cannot set security on a shared context");
191 context.set_replay_attack_policy(security.replay_attack.policy);
192 }
193
194 #[cfg(feature = "local-fake-dns")]
196 pub async fn add_fake_dns_manager(&self, manager: Arc<FakeDnsManager>) {
197 let mut managers = self.fake_dns_manager.write().await;
198 managers.push(manager);
199 }
200
201 #[cfg(feature = "local-fake-dns")]
203 pub async fn try_map_fake_address(&self, addr: &Address) -> Option<Address> {
204 let socket_addr = match addr {
205 Address::DomainNameAddress(..) => return None,
206 Address::SocketAddress(socket_addr) => socket_addr,
207 };
208 let ip_addr = socket_addr.ip();
209
210 for mgr in self.fake_dns_manager.read().await.iter() {
211 if let Ok(Some(name)) = mgr.map_ip_domain(ip_addr).await {
212 let new_addr = Address::DomainNameAddress(name.to_string(), socket_addr.port());
213 log::trace!("fakedns mapped {} -> {}", addr, new_addr);
214 return Some(new_addr);
215 }
216 }
217
218 None
219 }
220}