shadowsocks_rust/service/
local.rs

1//! Local server launchers
2
3#[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
85/// Defines command line options
86pub 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
585/// Create `Runtime` and `main` entry
586pub 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                    // NOTE: svr_addr should have been checked by crate::vparser
638                    if method.is_none() {
639                        // If method doesn't need a key (none, plain), then we can leave it empty
640                        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            // A socket `protect_path` in CWD
707            // Same as shadowsocks-libev's android.c
708            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                        // `tun` protocol doesn't need --local-addr
735                    } 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                // Start a DNS local server binding to DNS_LOCAL_ADDR
787                //
788                // This is a special route only for shadowsocks-android
789                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                    // The `local_dns_addr` and `remote_dns_addr` are for this DNS server (for compatibility)
793                    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        // DONE READING options
953
954        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                        // Server future resolved without an error. This should never happen.
1030                        Ok(..) => {
1031                            return Err(ShadowsocksError::ServerExitUnexpectedly("server exited unexpectedly".to_owned()));
1032                        }
1033                        // Server future resolved with error, which are listener errors in most cases
1034                        Err(err) => {
1035                            return Err(ShadowsocksError::ServerAborted(format!("server aborted with {err}")));
1036                        }
1037                    }
1038                }
1039                // The abort signal future resolved. Means we should just exit.
1040                _ = abort_signal => {
1041                    return Ok(());
1042                }
1043                _ = reload_task => {
1044                    // continue.
1045                    trace!("server-loader task task exited");
1046                }
1047            }
1048        }
1049    };
1050
1051    Ok((runtime, main_fut))
1052}
1053
1054/// Program entrance `main`
1055#[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        // Load servers from source
1077        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}