1#[cfg(unix)]
4use std::sync::Arc;
5use std::{
6 future::Future,
7 net::IpAddr,
8 path::PathBuf,
9 process::ExitCode,
10 time::{Duration, Instant},
11};
12
13use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint, builder::PossibleValuesParser};
14use futures::future::{self, FutureExt};
15use log::{error, info, trace};
16use tokio::{
17 self,
18 runtime::{Builder, Runtime},
19};
20
21#[cfg(feature = "local-redir")]
22use shadowsocks_service::config::RedirType;
23#[cfg(feature = "local-tunnel")]
24use shadowsocks_service::shadowsocks::relay::socks5::Address;
25use shadowsocks_service::{
26 acl::AccessControl,
27 config::{
28 Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig,
29 read_variable_field_value,
30 },
31 local::{Server, loadbalancing::PingBalancer},
32 shadowsocks::{
33 config::{Mode, ServerAddr, ServerConfig, ServerSource},
34 crypto::{CipherKind, available_ciphers},
35 plugin::PluginConfig,
36 },
37};
38
39#[cfg(feature = "logging")]
40use crate::logging;
41use crate::{
42 config::{Config as ServiceConfig, RuntimeMode},
43 error::{ShadowsocksError, ShadowsocksResult},
44 monitor, vparser,
45};
46
47#[cfg(feature = "local-dns")]
48mod local_value_parser {
49 use std::{
50 net::{IpAddr, SocketAddr},
51 str::FromStr,
52 };
53
54 use shadowsocks_service::shadowsocks::relay::socks5::{Address, AddressError};
55
56 #[derive(Debug, Clone)]
57 pub struct RemoteDnsAddress(pub Address);
58
59 impl FromStr for RemoteDnsAddress {
60 type Err = AddressError;
61
62 fn from_str(a: &str) -> Result<Self, Self::Err> {
63 if let Ok(ip) = a.parse::<IpAddr>() {
64 return Ok(Self(Address::SocketAddress(SocketAddr::new(ip, 53))));
65 }
66
67 if let Ok(saddr) = a.parse::<SocketAddr>() {
68 return Ok(Self(Address::SocketAddress(saddr)));
69 }
70
71 if a.find(':').is_some() {
72 a.parse::<Address>().map(RemoteDnsAddress)
73 } else {
74 Ok(Self(Address::DomainNameAddress(a.to_owned(), 53)))
75 }
76 }
77 }
78
79 #[inline]
80 pub fn parse_remote_dns_address(s: &str) -> Result<RemoteDnsAddress, AddressError> {
81 s.parse::<RemoteDnsAddress>()
82 }
83}
84
85pub fn define_command_line_options(mut app: Command) -> Command {
87 app = app.arg(
88 Arg::new("CONFIG")
89 .short('c')
90 .long("config")
91 .num_args(1)
92 .action(ArgAction::Set)
93 .value_parser(clap::value_parser!(PathBuf))
94 .value_hint(ValueHint::FilePath)
95 .help("Shadowsocks configuration file (https://shadowsocks.org/doc/configs.html)"),
96 )
97 .arg(
98 Arg::new("LOCAL_ADDR")
99 .short('b')
100 .long("local-addr")
101 .num_args(1)
102 .action(ArgAction::Set)
103 .value_parser(vparser::parse_server_addr)
104 .help("Local address, listen only to this address if specified"),
105 )
106 .arg(
107 Arg::new("UDP_ONLY")
108 .short('u')
109 .action(ArgAction::SetTrue)
110 .conflicts_with("TCP_AND_UDP")
111 .requires("LOCAL_ADDR")
112 .help("Server mode UDP_ONLY"),
113 )
114 .arg(
115 Arg::new("TCP_AND_UDP")
116 .short('U')
117 .action(ArgAction::SetTrue)
118 .help("Server mode TCP_AND_UDP"),
119 )
120 .arg(
121 Arg::new("PROTOCOL")
122 .long("protocol")
123 .num_args(1)
124 .action(ArgAction::Set)
125 .value_parser(PossibleValuesParser::new(ProtocolType::available_protocols()))
126 .help("Protocol for communicating with clients (SOCKS5 by default)"),
127 )
128 .arg(
129 Arg::new("UDP_BIND_ADDR")
130 .long("udp-bind-addr")
131 .num_args(1)
132 .action(ArgAction::Set)
133 .value_parser(vparser::parse_server_addr)
134 .help("UDP relay's bind address, default is the same as local-addr"),
135 )
136 .arg(
137 Arg::new("UDP_ASSOCIATE_ADDR")
138 .long("udp-associate-addr")
139 .num_args(1)
140 .action(ArgAction::Set)
141 .value_parser(vparser::parse_server_addr)
142 .help("UDP relay's externally visible address return in UDP Associate responses"),
143 )
144 .arg(
145 Arg::new("SERVER_ADDR")
146 .short('s')
147 .long("server-addr")
148 .num_args(1)
149 .action(ArgAction::Set)
150 .requires("ENCRYPT_METHOD")
151 .help("Server address"),
152 )
153 .arg(
154 Arg::new("PASSWORD")
155 .short('k')
156 .long("password")
157 .num_args(1)
158 .action(ArgAction::Set)
159 .requires("SERVER_ADDR")
160 .help("Server's password"),
161 )
162 .arg(
163 Arg::new("ENCRYPT_METHOD")
164 .short('m')
165 .long("encrypt-method")
166 .num_args(1)
167 .action(ArgAction::Set)
168 .requires("SERVER_ADDR")
169 .value_parser(PossibleValuesParser::new(available_ciphers()))
170 .help("Server's encryption method"),
171 )
172 .arg(
173 Arg::new("TIMEOUT")
174 .long("timeout")
175 .num_args(1)
176 .action(ArgAction::Set)
177 .value_parser(clap::value_parser!(u64))
178 .requires("SERVER_ADDR")
179 .help("Server's timeout seconds for TCP relay"),
180 )
181 .arg(
182 Arg::new("PLUGIN")
183 .long("plugin")
184 .num_args(1)
185 .action(ArgAction::Set)
186 .value_hint(ValueHint::CommandName)
187 .requires("SERVER_ADDR")
188 .help("SIP003 (https://shadowsocks.org/doc/sip003.html) plugin"),
189 )
190 .arg(
191 Arg::new("PLUGIN_MODE")
192 .long("plugin-mode")
193 .num_args(1)
194 .action(ArgAction::Set)
195 .requires("PLUGIN")
196 .help("SIP003/SIP003u plugin mode, must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`"),
197 )
198 .arg(
199 Arg::new("PLUGIN_OPT")
200 .long("plugin-opts")
201 .num_args(1)
202 .action(ArgAction::Set)
203 .requires("PLUGIN")
204 .help("Set SIP003 plugin options"),
205 )
206 .arg(
207 Arg::new("SERVER_URL")
208 .long("server-url")
209 .num_args(1)
210 .action(ArgAction::Set)
211 .value_hint(ValueHint::Url)
212 .value_parser(vparser::parse_server_url)
213 .help("Server address in SIP002 (https://shadowsocks.org/doc/sip002.html) URL"),
214 )
215 .group(ArgGroup::new("SERVER_CONFIG")
216 .arg("SERVER_ADDR").arg("SERVER_URL").multiple(true))
217 .arg(
218 Arg::new("ACL")
219 .long("acl")
220 .num_args(1)
221 .action(ArgAction::Set)
222 .value_hint(ValueHint::FilePath)
223 .help("Path to ACL (Access Control List)"),
224 )
225 .arg(Arg::new("DNS").long("dns").num_args(1).action(ArgAction::Set).help("DNS nameservers, formatted like [(tcp|udp)://]host[:port][,host[:port]]..., or unix:///path/to/dns, or predefined keys like \"google\", \"cloudflare\""))
226 .arg(Arg::new("DNS_CACHE_SIZE").long("dns-cache-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(usize)).help("DNS cache size in number of records. Works when trust-dns DNS backend is enabled."))
227 .arg(Arg::new("TCP_NO_DELAY").long("tcp-no-delay").alias("no-delay").action(ArgAction::SetTrue).help("Set TCP_NODELAY option for sockets"))
228 .arg(Arg::new("TCP_FAST_OPEN").long("tcp-fast-open").alias("fast-open").action(ArgAction::SetTrue).help("Enable TCP Fast Open (TFO)"))
229 .arg(Arg::new("TCP_KEEP_ALIVE").long("tcp-keep-alive").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Set TCP keep alive timeout seconds"))
230 .arg(Arg::new("TCP_MULTIPATH").long("tcp-multipath").alias("mptcp").action(ArgAction::SetTrue).help("Enable Multipath-TCP (MPTCP)"))
231 .arg(Arg::new("UDP_TIMEOUT").long("udp-timeout").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Timeout seconds for UDP relay"))
232 .arg(Arg::new("UDP_MAX_ASSOCIATIONS").long("udp-max-associations").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(usize)).help("Maximum associations to be kept simultaneously for UDP relay"))
233 .arg(Arg::new("INBOUND_SEND_BUFFER_SIZE").long("inbound-send-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set inbound sockets' SO_SNDBUF option"))
234 .arg(Arg::new("INBOUND_RECV_BUFFER_SIZE").long("inbound-recv-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set inbound sockets' SO_RCVBUF option"))
235 .arg(Arg::new("OUTBOUND_SEND_BUFFER_SIZE").long("outbound-send-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set outbound sockets' SO_SNDBUF option"))
236 .arg(Arg::new("OUTBOUND_RECV_BUFFER_SIZE").long("outbound-recv-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set outbound sockets' SO_RCVBUF option"))
237 .arg(Arg::new("OUTBOUND_BIND_ADDR").long("outbound-bind-addr").num_args(1).alias("bind-addr").action(ArgAction::Set).value_parser(vparser::parse_ip_addr).help("Bind address, outbound socket will bind this address"))
238 .arg(Arg::new("OUTBOUND_BIND_INTERFACE").long("outbound-bind-interface").num_args(1).action(ArgAction::Set).help("Set SO_BINDTODEVICE / IP_BOUND_IF / IP_UNICAST_IF option for outbound socket"))
239 .arg(
240 Arg::new("IPV6_FIRST")
241 .short('6')
242 .action(ArgAction::SetTrue)
243 .help("Resolve hostname to IPv6 address first"),
244 );
245
246 #[cfg(feature = "logging")]
247 {
248 app = app
249 .arg(
250 Arg::new("VERBOSE")
251 .short('v')
252 .action(ArgAction::Count)
253 .help("Set log level"),
254 )
255 .arg(
256 Arg::new("LOG_WITHOUT_TIME")
257 .long("log-without-time")
258 .action(ArgAction::SetTrue)
259 .help("Log without datetime prefix"),
260 )
261 .arg(
262 Arg::new("LOG_CONFIG")
263 .long("log-config")
264 .num_args(1)
265 .action(ArgAction::Set)
266 .value_parser(clap::value_parser!(PathBuf))
267 .value_hint(ValueHint::FilePath)
268 .help("log4rs configuration file"),
269 );
270 }
271
272 #[cfg(feature = "local-tunnel")]
273 {
274 app = app.arg(
275 Arg::new("FORWARD_ADDR")
276 .short('f')
277 .long("forward-addr")
278 .num_args(1)
279 .action(ArgAction::Set)
280 .requires("LOCAL_ADDR")
281 .value_parser(vparser::parse_address)
282 .required_if_eq("PROTOCOL", "tunnel")
283 .help("Forwarding data directly to this address (for tunnel)"),
284 );
285 }
286
287 #[cfg(all(unix, not(target_os = "android")))]
288 {
289 app = app.arg(
290 Arg::new("NOFILE")
291 .short('n')
292 .long("nofile")
293 .num_args(1)
294 .action(ArgAction::Set)
295 .value_parser(clap::value_parser!(u64))
296 .help("Set RLIMIT_NOFILE with both soft and hard limit"),
297 );
298 }
299
300 #[cfg(any(target_os = "linux", target_os = "android"))]
301 {
302 app = app.arg(
303 Arg::new("OUTBOUND_FWMARK")
304 .long("outbound-fwmark")
305 .num_args(1)
306 .action(ArgAction::Set)
307 .value_parser(clap::value_parser!(u32))
308 .help("Set SO_MARK option for outbound sockets"),
309 );
310 }
311
312 #[cfg(target_os = "freebsd")]
313 {
314 app = app.arg(
315 Arg::new("OUTBOUND_USER_COOKIE")
316 .long("outbound-user-cookie")
317 .num_args(1)
318 .action(ArgAction::Set)
319 .value_parser(clap::value_parser!(u32))
320 .help("Set SO_USER_COOKIE option for outbound sockets"),
321 );
322 }
323
324 #[cfg(feature = "local-redir")]
325 {
326 if RedirType::tcp_default() != RedirType::NotSupported {
327 app = app.arg(
328 Arg::new("TCP_REDIR")
329 .long("tcp-redir")
330 .num_args(1)
331 .action(ArgAction::Set)
332 .requires("LOCAL_ADDR")
333 .value_parser(PossibleValuesParser::new(RedirType::tcp_available_types()))
334 .help("TCP redir (transparent proxy) type"),
335 );
336 }
337
338 if RedirType::udp_default() != RedirType::NotSupported {
339 app = app.arg(
340 Arg::new("UDP_REDIR")
341 .long("udp-redir")
342 .num_args(1)
343 .action(ArgAction::Set)
344 .requires("LOCAL_ADDR")
345 .value_parser(PossibleValuesParser::new(RedirType::udp_available_types()))
346 .help("UDP redir (transparent proxy) type"),
347 );
348 }
349 }
350
351 #[cfg(target_os = "android")]
352 {
353 app = app.arg(
354 Arg::new("VPN_MODE")
355 .long("vpn")
356 .action(ArgAction::SetTrue)
357 .help("Enable VPN mode (only for Android)"),
358 );
359 }
360
361 #[cfg(feature = "local-flow-stat")]
362 {
363 #[cfg(unix)]
364 {
365 app = app.arg(
366 Arg::new("STAT_PATH")
367 .long("stat-path")
368 .num_args(1)
369 .action(ArgAction::Set)
370 .value_hint(ValueHint::FilePath)
371 .conflicts_with("STAT_ADDR")
372 .help("Specify socket path (unix domain socket) for sending traffic statistic"),
373 );
374 }
375
376 app = app.arg(
377 Arg::new("STAT_ADDR")
378 .long("stat-addr")
379 .num_args(1)
380 .action(ArgAction::Set)
381 .value_parser(vparser::parse_socket_addr)
382 .help("Specify socket address IP:PORT (TCP) for sending traffic statistic"),
383 );
384 }
385
386 #[cfg(feature = "local-dns")]
387 {
388 app = app
389 .arg(
390 Arg::new("LOCAL_DNS_ADDR")
391 .long("local-dns-addr")
392 .num_args(1)
393 .action(ArgAction::Set)
394 .required_if_eq("PROTOCOL", "dns")
395 .requires("LOCAL_ADDR")
396 .value_parser(vparser::parse_name_server_addr)
397 .help("Specify the address of local DNS server, send queries directly"),
398 )
399 .arg(
400 Arg::new("REMOTE_DNS_ADDR")
401 .long("remote-dns-addr")
402 .num_args(1)
403 .action(ArgAction::Set)
404 .required_if_eq("PROTOCOL", "dns")
405 .requires("LOCAL_ADDR")
406 .value_parser(self::local_value_parser::parse_remote_dns_address)
407 .help("Specify the address of remote DNS server, send queries through shadowsocks' tunnel"),
408 );
409
410 #[cfg(target_os = "android")]
411 {
412 app = app.arg(
413 Arg::new("DNS_LOCAL_ADDR")
414 .long("dns-addr")
415 .num_args(1)
416 .action(ArgAction::Set)
417 .requires_all(&["LOCAL_ADDR", "REMOTE_DNS_ADDR"])
418 .value_parser(vparser::parse_server_addr)
419 .help("DNS address, listen to this address if specified"),
420 );
421 }
422 }
423
424 #[cfg(feature = "local-tun")]
425 {
426 app = app
427 .arg(
428 Arg::new("TUN_INTERFACE_NAME")
429 .long("tun-interface-name")
430 .num_args(1)
431 .action(ArgAction::Set)
432 .help("Tun interface name, allocate one if not specify"),
433 )
434 .arg(
435 Arg::new("TUN_INTERFACE_ADDRESS")
436 .long("tun-interface-address")
437 .num_args(1)
438 .action(ArgAction::Set)
439 .value_parser(vparser::parse_ipnet)
440 .help("Tun interface address (network)"),
441 )
442 .arg(
443 Arg::new("TUN_INTERFACE_DESTINATION")
444 .long("tun-interface-destination")
445 .num_args(1)
446 .action(ArgAction::Set)
447 .value_parser(vparser::parse_ipnet)
448 .help("Tun interface destination address (network)"),
449 );
450
451 #[cfg(unix)]
452 {
453 app = app.arg(
454 Arg::new("TUN_DEVICE_FD_FROM_PATH")
455 .long("tun-device-fd-from-path")
456 .num_args(1)
457 .action(ArgAction::Set)
458 .value_parser(clap::value_parser!(PathBuf))
459 .value_hint(ValueHint::AnyPath)
460 .help("Tun device file descriptor will be transferred from this unix domain socket path"),
461 );
462 }
463 }
464
465 #[cfg(feature = "local-fake-dns")]
466 {
467 app = app
468 .arg(
469 Arg::new("FAKE_DNS_RECORD_EXPIRE_DURATION")
470 .long("fake-dns-record-expire-duration")
471 .num_args(1)
472 .action(ArgAction::Set)
473 .value_parser(clap::value_parser!(u64))
474 .help("Fake DNS record expire duration in seconds"),
475 )
476 .arg(
477 Arg::new("FAKE_DNS_IPV4_NETWORK")
478 .long("fake-dns-ipv4-network")
479 .num_args(1)
480 .action(ArgAction::Set)
481 .value_parser(vparser::parse_ipnet)
482 .help("Fake DNS IPv4 address network"),
483 )
484 .arg(
485 Arg::new("FAKE_DNS_IPV6_NETWORK")
486 .long("fake-dns-ipv6-network")
487 .num_args(1)
488 .action(ArgAction::Set)
489 .value_parser(vparser::parse_ipnet)
490 .help("Fake DNS IPv6 address network"),
491 )
492 .arg(
493 Arg::new("FAKE_DNS_DATABASE_PATH")
494 .long("fake-dns-database-path")
495 .num_args(1)
496 .action(ArgAction::Set)
497 .value_hint(ValueHint::AnyPath)
498 .help("Fake DNS database storage path"),
499 );
500 }
501
502 #[cfg(unix)]
503 {
504 app = app
505 .arg(
506 Arg::new("DAEMONIZE")
507 .short('d')
508 .long("daemonize")
509 .action(ArgAction::SetTrue)
510 .help("Daemonize"),
511 )
512 .arg(
513 Arg::new("DAEMONIZE_PID_PATH")
514 .long("daemonize-pid")
515 .num_args(1)
516 .action(ArgAction::Set)
517 .value_parser(clap::value_parser!(PathBuf))
518 .value_hint(ValueHint::FilePath)
519 .help("File path to store daemonized process's PID"),
520 );
521 }
522
523 #[cfg(feature = "multi-threaded")]
524 {
525 app = app
526 .arg(
527 Arg::new("SINGLE_THREADED")
528 .long("single-threaded")
529 .action(ArgAction::SetTrue)
530 .help("Run the program all in one thread"),
531 )
532 .arg(
533 Arg::new("WORKER_THREADS")
534 .long("worker-threads")
535 .num_args(1)
536 .action(ArgAction::Set)
537 .value_parser(clap::value_parser!(usize))
538 .help("Sets the number of worker threads the `Runtime` will use"),
539 );
540 }
541
542 #[cfg(unix)]
543 {
544 app = app.arg(
545 Arg::new("USER")
546 .long("user")
547 .short('a')
548 .num_args(1)
549 .action(ArgAction::Set)
550 .value_hint(ValueHint::Username)
551 .help("Run as another user"),
552 );
553 }
554
555 #[cfg(feature = "local-online-config")]
556 {
557 app = app
558 .arg(
559 Arg::new("ONLINE_CONFIG_URL")
560 .long("online-config-url")
561 .num_args(1)
562 .action(ArgAction::Set)
563 .value_hint(ValueHint::Url)
564 .help("SIP008 Online Configuration Delivery URL (https://shadowsocks.org/doc/sip008.html)"),
565 )
566 .arg(
567 Arg::new("ONLINE_CONFIG_UPDATE_INTERVAL")
568 .long("online-config-update-interval")
569 .num_args(1)
570 .action(ArgAction::Set)
571 .value_parser(clap::value_parser!(u64))
572 .help("SIP008 Online Configuration Delivery update interval in seconds, 3600 by default"),
573 )
574 .arg(
575 Arg::new("ONLINE_CONFIG_ALLOWED_PLUGIN")
576 .long("online-config-allowed-plugin")
577 .action(ArgAction::Append)
578 .help("SIP008 Online Configuration Delivery allowed plugin list"),
579 );
580 }
581
582 app
583}
584
585pub fn create(matches: &ArgMatches) -> ShadowsocksResult<(Runtime, impl Future<Output = ShadowsocksResult> + use<>)> {
587 #[cfg_attr(not(feature = "local-online-config"), allow(unused_mut))]
588 let (config, _, runtime) = {
589 let config_path_opt = matches.get_one::<PathBuf>("CONFIG").cloned().or_else(|| {
590 if !matches.contains_id("SERVER_CONFIG") {
591 match crate::config::get_default_config_path("local.json") {
592 None => None,
593 Some(p) => {
594 println!("loading default config {p:?}");
595 Some(p)
596 }
597 }
598 } else {
599 None
600 }
601 });
602
603 let mut service_config = match config_path_opt {
604 Some(ref config_path) => ServiceConfig::load_from_file(config_path)
605 .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("loading config {config_path:?}, {err}")))?,
606 None => ServiceConfig::default(),
607 };
608 service_config.set_options(matches);
609
610 #[cfg(feature = "logging")]
611 match service_config.log.config_path {
612 Some(ref path) => {
613 logging::init_with_file(path);
614 }
615 None => {
616 logging::init_with_config("sslocal", &service_config.log);
617 }
618 }
619
620 trace!("{:?}", service_config);
621
622 let mut config = match config_path_opt {
623 Some(cpath) => Config::load_from_file(&cpath, ConfigType::Local)
624 .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("loading config {cpath:?}, {err}")))?,
625 None => Config::new(ConfigType::Local),
626 };
627
628 if let Some(svr_addr) = matches.get_one::<String>("SERVER_ADDR") {
629 let method = matches
630 .get_one::<String>("ENCRYPT_METHOD")
631 .map(|x| x.parse::<CipherKind>().expect("method"))
632 .expect("`method` is required");
633
634 let password = match matches.get_one::<String>("PASSWORD") {
635 Some(pwd) => read_variable_field_value(pwd).into(),
636 None => {
637 if method.is_none() {
639 String::new()
641 } else {
642 match crate::password::read_server_password(svr_addr) {
643 Ok(pwd) => pwd,
644 Err(..) => panic!("`password` is required for server {svr_addr}"),
645 }
646 }
647 }
648 };
649
650 let svr_addr = svr_addr.parse::<ServerAddr>().expect("server-addr");
651 let timeout = matches.get_one::<u64>("TIMEOUT").map(|x| Duration::from_secs(*x));
652
653 let mut sc = match ServerConfig::new(svr_addr, password, method) {
654 Ok(sc) => sc,
655 Err(err) => {
656 panic!("failed to create ServerConfig, error: {}", err);
657 }
658 };
659 sc.set_source(ServerSource::CommandLine);
660 if let Some(timeout) = timeout {
661 sc.set_timeout(timeout);
662 }
663
664 if let Some(p) = matches.get_one::<String>("PLUGIN").cloned() {
665 let plugin = PluginConfig {
666 plugin: p,
667 plugin_opts: matches.get_one::<String>("PLUGIN_OPT").cloned(),
668 plugin_args: Vec::new(),
669 plugin_mode: matches
670 .get_one::<String>("PLUGIN_MODE")
671 .map(|x| {
672 x.parse::<Mode>()
673 .expect("plugin-mode must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`")
674 })
675 .unwrap_or(Mode::TcpOnly),
676 };
677
678 sc.set_plugin(plugin);
679 }
680
681 config.server.push(ServerInstanceConfig::with_server_config(sc));
682 }
683
684 if let Some(mut svr_addr) = matches.get_one::<ServerConfig>("SERVER_URL").cloned() {
685 svr_addr.set_source(ServerSource::CommandLine);
686 config.server.push(ServerInstanceConfig::with_server_config(svr_addr));
687 }
688
689 #[cfg(feature = "local-flow-stat")]
690 {
691 use shadowsocks_service::config::LocalFlowStatAddress;
692 use std::net::SocketAddr;
693
694 #[cfg(unix)]
695 if let Some(stat_path) = matches.get_one::<String>("STAT_PATH") {
696 config.local_stat_addr = Some(LocalFlowStatAddress::UnixStreamPath(From::from(stat_path)));
697 }
698
699 if let Some(stat_addr) = matches.get_one::<SocketAddr>("STAT_ADDR").cloned() {
700 config.local_stat_addr = Some(LocalFlowStatAddress::TcpStreamAddr(stat_addr));
701 }
702 }
703
704 #[cfg(target_os = "android")]
705 if matches.get_flag("VPN_MODE") {
706 config.outbound_vpn_protect_path = Some(From::from("protect_path"));
709 }
710
711 if matches.get_raw("LOCAL_ADDR").is_some() || matches.get_raw("PROTOCOL").is_some() {
712 let protocol = match matches.get_one::<String>("PROTOCOL").map(|s| s.as_str()) {
713 Some("socks") => ProtocolType::Socks,
714 #[cfg(feature = "local-http")]
715 Some("http") => ProtocolType::Http,
716 #[cfg(feature = "local-tunnel")]
717 Some("tunnel") => ProtocolType::Tunnel,
718 #[cfg(feature = "local-redir")]
719 Some("redir") => ProtocolType::Redir,
720 #[cfg(feature = "local-dns")]
721 Some("dns") => ProtocolType::Dns,
722 #[cfg(feature = "local-tun")]
723 Some("tun") => ProtocolType::Tun,
724 Some(p) => panic!("not supported `protocol` \"{p}\""),
725 None => ProtocolType::Socks,
726 };
727
728 let mut local_config = LocalConfig::new(protocol);
729 match matches.get_one::<ServerAddr>("LOCAL_ADDR").cloned() {
730 Some(local_addr) => local_config.addr = Some(local_addr),
731 None => {
732 #[cfg(feature = "local-tun")]
733 if protocol == ProtocolType::Tun {
734 } else {
736 panic!("`local-addr` is required for protocol {}", protocol.as_str());
737 }
738 }
739 }
740
741 if let Some(udp_bind_addr) = matches.get_one::<ServerAddr>("UDP_BIND_ADDR").cloned() {
742 local_config.udp_addr = Some(udp_bind_addr);
743 }
744
745 if let Some(udp_associate_addr) = matches.get_one::<ServerAddr>("UDP_ASSOCIATE_ADDR").cloned() {
746 local_config.udp_associate_addr = Some(udp_associate_addr);
747 }
748
749 #[cfg(feature = "local-tunnel")]
750 if let Some(addr) = matches.get_one::<Address>("FORWARD_ADDR").cloned() {
751 local_config.forward_addr = Some(addr);
752 }
753
754 #[cfg(feature = "local-redir")]
755 {
756 if RedirType::tcp_default() != RedirType::NotSupported {
757 if let Some(tcp_redir) = matches.get_one::<String>("TCP_REDIR") {
758 local_config.tcp_redir = tcp_redir.parse::<RedirType>().expect("tcp-redir");
759 }
760 }
761
762 if RedirType::udp_default() != RedirType::NotSupported {
763 if let Some(udp_redir) = matches.get_one::<String>("UDP_REDIR") {
764 local_config.udp_redir = udp_redir.parse::<RedirType>().expect("udp-redir");
765 }
766 }
767 }
768
769 #[cfg(feature = "local-dns")]
770 {
771 use shadowsocks_service::local::dns::NameServerAddr;
772
773 use self::local_value_parser::RemoteDnsAddress;
774
775 if let Some(addr) = matches.get_one::<NameServerAddr>("LOCAL_DNS_ADDR").cloned() {
776 local_config.local_dns_addr = Some(addr);
777 }
778
779 if let Some(addr) = matches.get_one::<RemoteDnsAddress>("REMOTE_DNS_ADDR").cloned() {
780 local_config.remote_dns_addr = Some(addr.0);
781 }
782 }
783
784 #[cfg(all(feature = "local-dns", target_os = "android"))]
785 if protocol != ProtocolType::Dns {
786 if let Some(addr) = matches.get_one::<ServerAddr>("DNS_LOCAL_ADDR").cloned() {
790 let mut local_dns_config = LocalConfig::new_with_addr(addr, ProtocolType::Dns);
791
792 local_dns_config.local_dns_addr = local_config.local_dns_addr.take();
794 local_dns_config.remote_dns_addr = local_config.remote_dns_addr.take();
795
796 config
797 .local
798 .push(LocalInstanceConfig::with_local_config(local_dns_config));
799 }
800 }
801
802 #[cfg(feature = "local-tun")]
803 {
804 use ipnet::IpNet;
805
806 if let Some(tun_address) = matches.get_one::<IpNet>("TUN_INTERFACE_ADDRESS").cloned() {
807 local_config.tun_interface_address = Some(tun_address);
808 }
809 if let Some(tun_address) = matches.get_one::<IpNet>("TUN_INTERFACE_DESTINATION").cloned() {
810 local_config.tun_interface_destination = Some(tun_address);
811 }
812 if let Some(tun_name) = matches.get_one::<String>("TUN_INTERFACE_NAME").cloned() {
813 local_config.tun_interface_name = Some(tun_name);
814 }
815
816 #[cfg(unix)]
817 if let Some(fd_path) = matches.get_one::<PathBuf>("TUN_DEVICE_FD_FROM_PATH").cloned() {
818 local_config.tun_device_fd_from_path = Some(fd_path);
819 }
820 }
821
822 #[cfg(feature = "local-fake-dns")]
823 {
824 use ipnet::{Ipv4Net, Ipv6Net};
825
826 if let Some(d) = matches.get_one::<u64>("FAKE_DNS_RECORD_EXPIRE_DURATION") {
827 local_config.fake_dns_record_expire_duration = Some(Duration::from_secs(*d));
828 }
829 if let Some(n) = matches.get_one::<Ipv4Net>("FAKE_DNS_IPV4_NETWORK") {
830 local_config.fake_dns_ipv4_network = Some(*n);
831 }
832 if let Some(n) = matches.get_one::<Ipv6Net>("FAKE_DNS_IPV6_NETWORK") {
833 local_config.fake_dns_ipv6_network = Some(*n);
834 }
835 if let Some(p) = matches.get_one::<PathBuf>("FAKE_DNS_DATABASE_PATH").cloned() {
836 local_config.fake_dns_database_path = Some(p);
837 }
838 }
839
840 if matches.get_flag("UDP_ONLY") {
841 local_config.mode = Mode::UdpOnly;
842 }
843
844 if matches.get_flag("TCP_AND_UDP") {
845 local_config.mode = Mode::TcpAndUdp;
846 }
847
848 config.local.push(LocalInstanceConfig::with_local_config(local_config));
849 }
850
851 if matches.get_flag("TCP_NO_DELAY") {
852 config.no_delay = true;
853 }
854
855 if matches.get_flag("TCP_FAST_OPEN") {
856 config.fast_open = true;
857 }
858
859 if let Some(keep_alive) = matches.get_one::<u64>("TCP_KEEP_ALIVE") {
860 config.keep_alive = Some(Duration::from_secs(*keep_alive));
861 }
862
863 if matches.get_flag("TCP_MULTIPATH") {
864 config.mptcp = true;
865 }
866
867 #[cfg(any(target_os = "linux", target_os = "android"))]
868 if let Some(mark) = matches.get_one::<u32>("OUTBOUND_FWMARK") {
869 config.outbound_fwmark = Some(*mark);
870 }
871
872 #[cfg(target_os = "freebsd")]
873 if let Some(user_cookie) = matches.get_one::<u32>("OUTBOUND_USER_COOKIE") {
874 config.outbound_user_cookie = Some(*user_cookie);
875 }
876
877 if let Some(iface) = matches.get_one::<String>("OUTBOUND_BIND_INTERFACE").cloned() {
878 config.outbound_bind_interface = Some(iface);
879 }
880
881 #[cfg(all(unix, not(target_os = "android")))]
882 match matches.get_one::<u64>("NOFILE") {
883 Some(nofile) => config.nofile = Some(*nofile),
884 None => {
885 if config.nofile.is_none() {
886 crate::sys::adjust_nofile();
887 }
888 }
889 }
890
891 if let Some(acl_file) = matches.get_one::<String>("ACL") {
892 let acl = AccessControl::load_from_file(acl_file)
893 .map_err(|err| ShadowsocksError::LoadAclFailure(format!("loading ACL \"{acl_file}\", {err}")))?;
894 config.acl = Some(acl);
895 }
896
897 if let Some(dns) = matches.get_one::<String>("DNS") {
898 config.set_dns_formatted(dns).expect("dns");
899 }
900
901 if let Some(dns_cache_size) = matches.get_one::<usize>("DNS_CACHE_SIZE") {
902 config.dns_cache_size = Some(*dns_cache_size);
903 }
904
905 if matches.get_flag("IPV6_FIRST") {
906 config.ipv6_first = true;
907 }
908
909 if let Some(udp_timeout) = matches.get_one::<u64>("UDP_TIMEOUT") {
910 config.udp_timeout = Some(Duration::from_secs(*udp_timeout));
911 }
912
913 if let Some(udp_max_assoc) = matches.get_one::<usize>("UDP_MAX_ASSOCIATIONS") {
914 config.udp_max_associations = Some(*udp_max_assoc);
915 }
916
917 if let Some(bs) = matches.get_one::<u32>("INBOUND_SEND_BUFFER_SIZE") {
918 config.inbound_send_buffer_size = Some(*bs);
919 }
920 if let Some(bs) = matches.get_one::<u32>("INBOUND_RECV_BUFFER_SIZE") {
921 config.inbound_recv_buffer_size = Some(*bs);
922 }
923 if let Some(bs) = matches.get_one::<u32>("OUTBOUND_SEND_BUFFER_SIZE") {
924 config.outbound_send_buffer_size = Some(*bs);
925 }
926 if let Some(bs) = matches.get_one::<u32>("OUTBOUND_RECV_BUFFER_SIZE") {
927 config.outbound_recv_buffer_size = Some(*bs);
928 }
929
930 if let Some(bind_addr) = matches.get_one::<IpAddr>("OUTBOUND_BIND_ADDR") {
931 config.outbound_bind_addr = Some(*bind_addr);
932 }
933
934 #[cfg(feature = "local-online-config")]
935 if let Some(online_config_url) = matches.get_one::<String>("ONLINE_CONFIG_URL") {
936 use shadowsocks_service::config::OnlineConfig;
937
938 let online_config_update_interval = matches.get_one::<u64>("ONLINE_CONFIG_UPDATE_INTERVAL").cloned();
939
940 let mut allowed_plugins = None;
941 if let Some(plugins) = matches.get_many::<String>("ONLINE_CONFIG_ALLOWED_PLUGIN") {
942 allowed_plugins = Some(plugins.cloned().collect());
943 }
944
945 config.online_config = Some(OnlineConfig {
946 config_url: online_config_url.clone(),
947 update_interval: online_config_update_interval.map(Duration::from_secs),
948 allowed_plugins,
949 });
950 }
951
952 if config.local.is_empty() {
955 return Err(ShadowsocksError::InsufficientParams(
956 "missing `local_address`, consider specifying it by --local-addr command line option, \
957 or \"local_address\" and \"local_port\" in configuration file"
958 .to_string(),
959 ));
960 }
961
962 config
963 .check_integrity()
964 .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("config integrity check failed, {err}")))?;
965
966 #[cfg(unix)]
967 if matches.get_flag("DAEMONIZE") || matches.get_raw("DAEMONIZE_PID_PATH").is_some() {
968 use crate::daemonize;
969 daemonize::daemonize(matches.get_one::<PathBuf>("DAEMONIZE_PID_PATH"));
970 }
971
972 #[cfg(unix)]
973 if let Some(uname) = matches.get_one::<String>("USER") {
974 crate::sys::run_as_user(uname).map_err(|err| {
975 ShadowsocksError::InsufficientParams(format!("failed to change as user, error: {err}"))
976 })?;
977 }
978
979 info!("shadowsocks local {} build {}", crate::VERSION, crate::BUILD_TIME);
980
981 let mut builder = match service_config.runtime.mode {
982 RuntimeMode::SingleThread => Builder::new_current_thread(),
983 #[cfg(feature = "multi-threaded")]
984 RuntimeMode::MultiThread => {
985 let mut builder = Builder::new_multi_thread();
986 if let Some(worker_threads) = service_config.runtime.worker_count {
987 builder.worker_threads(worker_threads);
988 }
989
990 builder
991 }
992 };
993
994 let runtime = builder.enable_all().build().expect("create tokio Runtime");
995
996 (config, service_config, runtime)
997 };
998
999 let main_fut = async move {
1000 let config_path = config.config_path.clone();
1001
1002 let instance = Server::new(config).await.expect("create local");
1003
1004 let reload_task = match config_path {
1005 Some(config_path) => ServerReloader {
1006 config_path: config_path.clone(),
1007 balancer: instance.server_balancer().clone(),
1008 }
1009 .launch_reload_server_task()
1010 .boxed(),
1011 None => future::pending().boxed(),
1012 };
1013
1014 let abort_signal = monitor::create_signal_monitor();
1015 let server = instance.run();
1016
1017 let reload_task = reload_task.fuse();
1018 let abort_signal = abort_signal.fuse();
1019 let server = server.fuse();
1020
1021 tokio::pin!(reload_task);
1022 tokio::pin!(abort_signal);
1023 tokio::pin!(server);
1024
1025 loop {
1026 futures::select! {
1027 server_res = server => {
1028 match server_res {
1029 Ok(..) => {
1031 return Err(ShadowsocksError::ServerExitUnexpectedly("server exited unexpectedly".to_owned()));
1032 }
1033 Err(err) => {
1035 return Err(ShadowsocksError::ServerAborted(format!("server aborted with {err}")));
1036 }
1037 }
1038 }
1039 _ = abort_signal => {
1041 return Ok(());
1042 }
1043 _ = reload_task => {
1044 trace!("server-loader task task exited");
1046 }
1047 }
1048 }
1049 };
1050
1051 Ok((runtime, main_fut))
1052}
1053
1054#[inline]
1056pub fn main(matches: &ArgMatches) -> ExitCode {
1057 match create(matches).and_then(|(runtime, main_fut)| runtime.block_on(main_fut)) {
1058 Ok(()) => ExitCode::SUCCESS,
1059 Err(err) => {
1060 eprintln!("{err}");
1061 err.exit_code().into()
1062 }
1063 }
1064}
1065
1066struct ServerReloader {
1067 config_path: PathBuf,
1068 balancer: PingBalancer,
1069}
1070
1071impl ServerReloader {
1072 #[cfg_attr(not(unix), allow(dead_code))]
1073 async fn run_once(&self) -> Result<(), Box<dyn std::error::Error>> {
1074 let start_time = Instant::now();
1075
1076 let source_config = match Config::load_from_file(&self.config_path, ConfigType::Local) {
1078 Ok(c) => c,
1079 Err(err) => {
1080 error!(
1081 "server-loader task failed to load from file: {}, error: {}",
1082 self.config_path.display(),
1083 err
1084 );
1085 return Err(Box::new(err));
1086 }
1087 };
1088
1089 let server_len = source_config.server.len();
1090
1091 let fetch_end_time = Instant::now();
1092
1093 if let Err(err) = self
1094 .balancer
1095 .reset_servers(source_config.server, &[ServerSource::Configuration])
1096 .await
1097 {
1098 error!("server-loader task {} servers but found error: {}", server_len, err);
1099 return Err(Box::new(err));
1100 }
1101
1102 let total_end_time = Instant::now();
1103
1104 info!(
1105 "server-loader task load from {} with {} servers, fetch costs: {:?}, total costs: {:?}",
1106 self.config_path.display(),
1107 server_len,
1108 fetch_end_time - start_time,
1109 total_end_time - start_time,
1110 );
1111
1112 Ok(())
1113 }
1114
1115 #[cfg(unix)]
1116 async fn launch_signal_reload_server_task(self: Arc<Self>) {
1117 use log::debug;
1118 use tokio::signal::unix::{SignalKind, signal};
1119
1120 let mut sigusr1 = signal(SignalKind::user_defined1()).expect("signal");
1121
1122 debug!("server-loader task is now listening USR1");
1123
1124 while sigusr1.recv().await.is_some() {
1125 let _ = self.run_once().await;
1126 }
1127 }
1128
1129 #[cfg(unix)]
1130 async fn launch_reload_server_task(self) {
1131 let arc_self = Arc::new(self);
1132 arc_self.launch_signal_reload_server_task().await
1133 }
1134
1135 #[cfg(windows)]
1136 async fn launch_reload_server_task(self) {
1137 let _ = self.config_path;
1138 let _ = self.balancer;
1139 }
1140}
1141
1142#[cfg(test)]
1143mod test {
1144 use clap::Command;
1145
1146 #[test]
1147 fn verify_local_command() {
1148 let mut app = Command::new("shadowsocks")
1149 .version(crate::VERSION)
1150 .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)");
1151 app = super::define_command_line_options(app);
1152 app.debug_assert();
1153 }
1154}