shadowsocks_service/
config.rs

1//! This is a mod for storing and parsing configuration
2//!
3//! According to shadowsocks' official documentation, the standard configuration
4//! file should be in JSON format:
5//!
6//! ```ignore
7//! {
8//!     "server": "127.0.0.1",
9//!     "server_port": 1080,
10//!     "local_port": 8388,
11//!     "password": "the-password",
12//!     "timeout": 300,
13//!     "method": "aes-256-cfb",
14//!     "local_address": "127.0.0.1"
15//! }
16//! ```
17//!
18//! But this configuration is not for using multiple shadowsocks server, so we
19//! introduce an extended configuration file format:
20//!
21//! ```ignore
22//! {
23//!     "servers": [
24//!         {
25//!             "server": "127.0.0.1",
26//!             "server_port": 1080,
27//!             "password": "hellofuck",
28//!             "method": "bf-cfb"
29//!         },
30//!         {
31//!             "server": "127.0.0.1",
32//!             "server_port": 1081,
33//!             "password": "hellofuck",
34//!             "method": "aes-128-cfb"
35//!         }
36//!     ],
37//!     "local_port": 8388,
38//!     "local_address": "127.0.0.1"
39//! }
40//! ```
41//!
42//! These defined server will be used with a load balancing algorithm.
43
44use std::{
45    borrow::Cow,
46    convert::{From, Infallible},
47    default::Default,
48    env,
49    fmt::{self, Debug, Display, Formatter},
50    fs::OpenOptions,
51    io::Read,
52    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
53    option::Option,
54    path::{Path, PathBuf},
55    str::FromStr,
56    string::ToString,
57    time::Duration,
58};
59
60use cfg_if::cfg_if;
61#[cfg(feature = "hickory-dns")]
62use hickory_resolver::config::{NameServerConfig, ResolverConfig};
63#[cfg(feature = "local-tun")]
64use ipnet::IpNet;
65#[cfg(feature = "local-fake-dns")]
66use ipnet::{Ipv4Net, Ipv6Net};
67use log::warn;
68use serde::{Deserialize, Serialize};
69#[cfg(any(feature = "local-tunnel", feature = "local-dns"))]
70use shadowsocks::relay::socks5::Address;
71use shadowsocks::{
72    config::{
73        ManagerAddr, Mode, ReplayAttackPolicy, ServerAddr, ServerConfig, ServerSource, ServerUser, ServerUserManager,
74        ServerWeight,
75    },
76    crypto::CipherKind,
77    plugin::PluginConfig,
78};
79
80use crate::acl::AccessControl;
81#[cfg(feature = "local-dns")]
82use crate::local::dns::NameServerAddr;
83#[cfg(feature = "local")]
84use crate::local::socks::config::Socks5AuthConfig;
85
86#[derive(Serialize, Deserialize, Debug)]
87#[serde(untagged)]
88enum SSDnsConfig {
89    Simple(String),
90    #[cfg(feature = "hickory-dns")]
91    HickoryDns(ResolverConfig),
92}
93
94#[derive(Serialize, Deserialize, Debug, Default)]
95struct SSSecurityConfig {
96    #[serde(skip_serializing_if = "Option::is_none")]
97    replay_attack: Option<SSSecurityReplayAttackConfig>,
98}
99
100#[derive(Serialize, Deserialize, Debug, Default)]
101struct SSSecurityReplayAttackConfig {
102    #[serde(skip_serializing_if = "Option::is_none")]
103    policy: Option<String>,
104}
105
106#[derive(Serialize, Deserialize, Debug, Default)]
107struct SSBalancerConfig {
108    #[serde(skip_serializing_if = "Option::is_none")]
109    max_server_rtt: Option<u64>,
110    #[serde(skip_serializing_if = "Option::is_none")]
111    check_interval: Option<u64>,
112    #[serde(skip_serializing_if = "Option::is_none")]
113    check_best_interval: Option<u64>,
114}
115
116#[derive(Serialize, Deserialize, Debug, Default)]
117struct SSConfig {
118    #[serde(skip_serializing_if = "Option::is_none")]
119    server: Option<String>,
120    #[serde(skip_serializing_if = "Option::is_none")]
121    server_port: Option<u16>,
122
123    #[serde(skip_serializing_if = "Option::is_none")]
124    local_address: Option<String>,
125    #[serde(skip_serializing_if = "Option::is_none")]
126    local_port: Option<u16>,
127
128    /// macOS launch activate socket for local_port
129    #[cfg(target_os = "macos")]
130    #[serde(skip_serializing_if = "Option::is_none")]
131    launchd_udp_socket_name: Option<String>,
132    #[cfg(target_os = "macos")]
133    #[serde(skip_serializing_if = "Option::is_none")]
134    launchd_tcp_socket_name: Option<String>,
135
136    #[serde(skip_serializing_if = "Option::is_none")]
137    protocol: Option<String>,
138
139    #[serde(skip_serializing_if = "Option::is_none")]
140    manager_address: Option<String>,
141    #[serde(skip_serializing_if = "Option::is_none")]
142    manager_port: Option<u16>,
143
144    #[serde(skip_serializing_if = "Option::is_none")]
145    password: Option<String>,
146    #[serde(skip_serializing_if = "Option::is_none")]
147    method: Option<String>,
148
149    #[serde(skip_serializing_if = "Option::is_none")]
150    plugin: Option<String>,
151    #[serde(skip_serializing_if = "Option::is_none")]
152    plugin_opts: Option<String>,
153    #[serde(skip_serializing_if = "Option::is_none")]
154    plugin_args: Option<Vec<String>>,
155    #[serde(skip_serializing_if = "Option::is_none")]
156    plugin_mode: Option<String>,
157
158    #[serde(skip_serializing_if = "Option::is_none")]
159    timeout: Option<u64>,
160
161    #[serde(skip_serializing_if = "Option::is_none")]
162    udp_timeout: Option<u64>,
163    #[serde(skip_serializing_if = "Option::is_none")]
164    udp_max_associations: Option<usize>,
165    #[serde(skip_serializing_if = "Option::is_none")]
166    udp_mtu: Option<usize>,
167
168    #[serde(skip_serializing_if = "Option::is_none", alias = "shadowsocks")]
169    servers: Option<Vec<SSServerExtConfig>>,
170
171    #[serde(skip_serializing_if = "Option::is_none")]
172    locals: Option<Vec<SSLocalExtConfig>>,
173
174    #[serde(skip_serializing_if = "Option::is_none")]
175    dns: Option<SSDnsConfig>,
176
177    #[serde(skip_serializing_if = "Option::is_none")]
178    dns_cache_size: Option<usize>,
179
180    #[serde(skip_serializing_if = "Option::is_none")]
181    mode: Option<String>,
182
183    #[serde(skip_serializing_if = "Option::is_none")]
184    no_delay: Option<bool>,
185
186    #[serde(skip_serializing_if = "Option::is_none")]
187    keep_alive: Option<u64>,
188
189    #[cfg(all(unix, not(target_os = "android")))]
190    #[serde(skip_serializing_if = "Option::is_none")]
191    nofile: Option<u64>,
192
193    #[serde(skip_serializing_if = "Option::is_none")]
194    ipv6_first: Option<bool>,
195    #[serde(skip_serializing_if = "Option::is_none")]
196    ipv6_only: Option<bool>,
197
198    #[serde(skip_serializing_if = "Option::is_none")]
199    fast_open: Option<bool>,
200
201    #[serde(skip_serializing_if = "Option::is_none")]
202    mptcp: Option<bool>,
203
204    #[serde(skip_serializing_if = "Option::is_none")]
205    #[cfg(any(target_os = "linux", target_os = "android"))]
206    outbound_fwmark: Option<u32>,
207
208    #[serde(skip_serializing_if = "Option::is_none")]
209    #[cfg(target_os = "freebsd")]
210    outbound_user_cookie: Option<u32>,
211
212    #[serde(skip_serializing_if = "Option::is_none")]
213    outbound_bind_addr: Option<String>,
214
215    #[serde(skip_serializing_if = "Option::is_none")]
216    outbound_bind_interface: Option<String>,
217
218    #[serde(skip_serializing_if = "Option::is_none")]
219    outbound_udp_allow_fragmentation: Option<bool>,
220
221    #[serde(skip_serializing_if = "Option::is_none")]
222    security: Option<SSSecurityConfig>,
223
224    #[serde(skip_serializing_if = "Option::is_none")]
225    balancer: Option<SSBalancerConfig>,
226
227    #[serde(skip_serializing_if = "Option::is_none")]
228    acl: Option<String>,
229
230    #[cfg(feature = "local-online-config")]
231    #[serde(skip_serializing_if = "Option::is_none")]
232    version: Option<u32>,
233
234    #[cfg(feature = "local-online-config")]
235    #[serde(skip_serializing_if = "Option::is_none")]
236    online_config: Option<SSOnlineConfig>,
237}
238
239#[derive(Serialize, Deserialize, Debug, Default)]
240struct SSLocalExtConfig {
241    #[serde(skip_serializing_if = "Option::is_none")]
242    local_address: Option<String>,
243    #[serde(skip_serializing_if = "Option::is_none")]
244    local_port: Option<u16>,
245
246    #[serde(skip_serializing_if = "Option::is_none")]
247    disabled: Option<bool>,
248
249    #[serde(skip_serializing_if = "Option::is_none")]
250    mode: Option<String>,
251
252    #[serde(skip_serializing_if = "Option::is_none")]
253    local_udp_address: Option<String>,
254    #[serde(skip_serializing_if = "Option::is_none")]
255    local_udp_port: Option<u16>,
256
257    #[serde(skip_serializing_if = "Option::is_none")]
258    protocol: Option<String>,
259
260    /// macOS launch activate socket
261    #[cfg(target_os = "macos")]
262    #[serde(skip_serializing_if = "Option::is_none")]
263    launchd_udp_socket_name: Option<String>,
264    #[cfg(target_os = "macos")]
265    #[serde(skip_serializing_if = "Option::is_none")]
266    launchd_tcp_socket_name: Option<String>,
267
268    /// TCP Transparent Proxy type
269    #[cfg(feature = "local-redir")]
270    #[serde(skip_serializing_if = "Option::is_none")]
271    tcp_redir: Option<String>,
272    /// UDP Transparent Proxy type
273    #[cfg(feature = "local-redir")]
274    #[serde(skip_serializing_if = "Option::is_none")]
275    udp_redir: Option<String>,
276
277    /// Local DNS's address
278    ///
279    /// Sending DNS query directly to this address
280    #[cfg(feature = "local-dns")]
281    #[serde(skip_serializing_if = "Option::is_none")]
282    local_dns_address: Option<String>,
283    #[cfg(feature = "local-dns")]
284    #[serde(skip_serializing_if = "Option::is_none")]
285    local_dns_port: Option<u16>,
286    /// Remote DNS's address
287    ///
288    /// Sending DNS query through proxy to this address
289    #[cfg(feature = "local-dns")]
290    #[serde(skip_serializing_if = "Option::is_none")]
291    remote_dns_address: Option<String>,
292    #[cfg(feature = "local-dns")]
293    #[serde(skip_serializing_if = "Option::is_none")]
294    remote_dns_port: Option<u16>,
295    #[cfg(feature = "local-dns")]
296    #[serde(skip_serializing_if = "Option::is_none")]
297    client_cache_size: Option<usize>,
298
299    /// Tunnel
300    #[cfg(feature = "local-tunnel")]
301    #[serde(skip_serializing_if = "Option::is_none")]
302    forward_address: Option<String>,
303    #[cfg(feature = "local-tunnel")]
304    #[serde(skip_serializing_if = "Option::is_none")]
305    forward_port: Option<u16>,
306
307    /// Tun
308    #[cfg(feature = "local-tun")]
309    #[serde(skip_serializing_if = "Option::is_none")]
310    tun_interface_name: Option<String>,
311    #[cfg(feature = "local-tun")]
312    #[serde(skip_serializing_if = "Option::is_none")]
313    tun_interface_address: Option<String>,
314    #[cfg(feature = "local-tun")]
315    #[serde(skip_serializing_if = "Option::is_none")]
316    tun_interface_destination: Option<String>,
317    #[cfg(all(feature = "local-tun", unix))]
318    #[serde(skip_serializing_if = "Option::is_none")]
319    tun_device_fd_from_path: Option<String>,
320
321    /// SOCKS5
322    #[cfg(feature = "local")]
323    #[serde(skip_serializing_if = "Option::is_none")]
324    socks5_auth_config_path: Option<String>,
325
326    /// Fake DNS
327    #[cfg(feature = "local-fake-dns")]
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub fake_dns_record_expire_duration: Option<u64>,
330    #[cfg(feature = "local-fake-dns")]
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub fake_dns_ipv4_network: Option<String>,
333    #[cfg(feature = "local-fake-dns")]
334    #[serde(skip_serializing_if = "Option::is_none")]
335    pub fake_dns_ipv6_network: Option<String>,
336    #[cfg(feature = "local-fake-dns")]
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub fake_dns_database_path: Option<String>,
339
340    #[serde(skip_serializing_if = "Option::is_none")]
341    acl: Option<String>,
342}
343
344#[derive(Serialize, Deserialize, Debug)]
345struct SSServerUserConfig {
346    name: String,
347    password: String,
348}
349
350#[derive(Serialize, Deserialize, Debug)]
351struct SSServerExtConfig {
352    // SIP008 https://github.com/shadowsocks/shadowsocks-org/issues/89
353    //
354    // `address` and `port` are non-standard field name only for shadowsocks-rust
355    #[serde(alias = "address")]
356    server: String,
357    #[serde(alias = "port")]
358    server_port: u16,
359
360    #[serde(skip_serializing_if = "Option::is_none")]
361    password: Option<String>,
362    method: String,
363
364    #[serde(skip_serializing_if = "Option::is_none")]
365    users: Option<Vec<SSServerUserConfig>>,
366
367    #[serde(skip_serializing_if = "Option::is_none")]
368    disabled: Option<bool>,
369
370    #[serde(skip_serializing_if = "Option::is_none")]
371    plugin: Option<String>,
372    #[serde(skip_serializing_if = "Option::is_none")]
373    plugin_opts: Option<String>,
374    #[serde(skip_serializing_if = "Option::is_none")]
375    plugin_args: Option<Vec<String>>,
376    #[serde(skip_serializing_if = "Option::is_none")]
377    plugin_mode: Option<String>,
378
379    #[serde(skip_serializing_if = "Option::is_none")]
380    timeout: Option<u64>,
381
382    #[serde(skip_serializing_if = "Option::is_none", alias = "name")]
383    remarks: Option<String>,
384    #[serde(skip_serializing_if = "Option::is_none")]
385    id: Option<String>,
386
387    #[serde(skip_serializing_if = "Option::is_none")]
388    mode: Option<String>,
389
390    #[serde(skip_serializing_if = "Option::is_none")]
391    tcp_weight: Option<f32>,
392    #[serde(skip_serializing_if = "Option::is_none")]
393    udp_weight: Option<f32>,
394
395    #[serde(skip_serializing_if = "Option::is_none")]
396    acl: Option<String>,
397
398    #[serde(skip_serializing_if = "Option::is_none")]
399    #[cfg(any(target_os = "linux", target_os = "android"))]
400    outbound_fwmark: Option<u32>,
401
402    #[serde(skip_serializing_if = "Option::is_none")]
403    #[cfg(target_os = "freebsd")]
404    outbound_user_cookie: Option<u32>,
405
406    #[serde(skip_serializing_if = "Option::is_none")]
407    outbound_bind_addr: Option<IpAddr>,
408
409    #[serde(skip_serializing_if = "Option::is_none")]
410    outbound_bind_interface: Option<String>,
411
412    #[serde(skip_serializing_if = "Option::is_none")]
413    outbound_udp_allow_fragmentation: Option<bool>,
414}
415
416#[cfg(feature = "local-online-config")]
417#[derive(Serialize, Deserialize, Debug, Default)]
418struct SSOnlineConfig {
419    config_url: String,
420    #[serde(skip_serializing_if = "Option::is_none")]
421    update_interval: Option<u64>,
422    #[serde(skip_serializing_if = "Option::is_none")]
423    allowed_plugins: Option<Vec<String>>,
424}
425
426/// Server config type
427#[derive(Clone, Copy, Debug, Eq, PartialEq)]
428pub enum ConfigType {
429    /// Config for local
430    Local,
431
432    /// Config for server
433    Server,
434
435    /// Config for Manager server
436    Manager,
437
438    /// Config for online config (SIP008)
439    /// https://shadowsocks.org/doc/sip008.html
440    #[cfg(feature = "local-online-config")]
441    OnlineConfig,
442}
443
444impl ConfigType {
445    /// Check if it is local server type
446    pub fn is_local(self) -> bool {
447        self == Self::Local
448    }
449
450    /// Check if it is remote server type
451    pub fn is_server(self) -> bool {
452        self == Self::Server
453    }
454
455    /// Check if it is manager server type
456    pub fn is_manager(self) -> bool {
457        self == Self::Manager
458    }
459
460    /// Check if it is online config type (SIP008)
461    #[cfg(feature = "local-online-config")]
462    pub fn is_online_config(self) -> bool {
463        self == Self::OnlineConfig
464    }
465}
466
467cfg_if! {
468    if #[cfg(feature = "local-redir")] {
469        /// Transparent Proxy type
470        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
471        pub enum RedirType {
472            /// For not supported platforms
473            NotSupported,
474
475            /// For Linux-like systems' Netfilter `REDIRECT`. Only for TCP connections.
476            ///
477            /// This is supported from Linux 2.4 Kernel. Document: <https://www.netfilter.org/documentation/index.html#documentation-howto>
478            ///
479            /// NOTE: Filter rule `REDIRECT` can only be applied to TCP connections.
480            #[cfg(any(target_os = "linux", target_os = "android"))]
481            Redirect,
482
483            /// For Linux-like systems' Netfilter TPROXY rule.
484            ///
485            /// NOTE: Filter rule `TPROXY` can be applied to TCP and UDP connections.
486            #[cfg(any(target_os = "linux", target_os = "android"))]
487            TProxy,
488
489            /// Packet Filter (pf)
490            ///
491            /// Supported by OpenBSD 3.0+, FreeBSD 5.3+, NetBSD 3.0+, Solaris 11.3+, macOS 10.7+, iOS, QNX
492            ///
493            /// Document: <https://www.freebsd.org/doc/handbook/firewalls-pf.html>
494            #[cfg(any(
495                target_os = "freebsd",
496                target_os = "openbsd",
497                target_os = "macos",
498                target_os = "ios"
499            ))]
500            PacketFilter,
501
502            /// IPFW
503            ///
504            /// Supported by FreeBSD, macOS 10.6- (Have been removed completely on macOS 10.10)
505            ///
506            /// Document: https://www.freebsd.org/doc/handbook/firewalls-ipfw.html
507            #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))]
508            IpFirewall,
509        }
510
511        impl RedirType {
512            cfg_if! {
513                if #[cfg(any(target_os = "linux", target_os = "android"))] {
514                    /// Default TCP transparent proxy solution on this platform
515                    pub const fn tcp_default() -> Self {
516                        Self::Redirect
517                    }
518
519                    /// Available TCP transparent proxy types
520                    #[doc(hidden)]
521                    pub fn tcp_available_types() -> &'static [&'static str] {
522                        const AVAILABLE_TYPES: &[&str] = &[RedirType::Redirect.name(), RedirType::TProxy.name()];
523                        AVAILABLE_TYPES
524                    }
525
526                    /// Default UDP transparent proxy solution on this platform
527                    pub const fn udp_default() -> Self {
528                        Self::TProxy
529                    }
530
531                    /// Available UDP transparent proxy types
532                    #[doc(hidden)]
533                    pub fn udp_available_types() -> &'static [&'static str] {
534                        const AVAILABLE_TYPES: &[&str] = &[RedirType::TProxy.name()];
535                        AVAILABLE_TYPES
536                    }
537                } else if #[cfg(any(target_os = "freebsd"))] {
538                    /// Default TCP transparent proxy solution on this platform
539                    pub fn tcp_default() -> RedirType {
540                        RedirType::PacketFilter
541                    }
542
543                    /// Available TCP transparent proxy types
544                    #[doc(hidden)]
545                    pub fn tcp_available_types() -> &'static [&'static str] {
546                        const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name(), RedirType::IpFirewall.name()];
547                        AVAILABLE_TYPES
548                    }
549
550                    /// Default UDP transparent proxy solution on this platform
551                    pub fn udp_default() -> RedirType {
552                        RedirType::PacketFilter
553                    }
554
555                    /// Available UDP transparent proxy types
556                    #[doc(hidden)]
557                    pub const fn udp_available_types() -> &'static [&'static str] {
558                        const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name(), RedirType::IpFirewall.name()];
559                        AVAILABLE_TYPES
560                    }
561                } else if #[cfg(target_os = "openbsd")] {
562                    /// Default TCP transparent proxy solution on this platform
563                    pub fn tcp_default() -> RedirType {
564                        RedirType::PacketFilter
565                    }
566
567                    /// Available TCP transparent proxy types
568                    #[doc(hidden)]
569                    pub fn tcp_available_types() -> &'static [&'static str] {
570                        const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name()];
571                        AVAILABLE_TYPES
572                    }
573
574                    /// Default UDP transparent proxy solution on this platform
575                    pub fn udp_default() -> RedirType {
576                        RedirType::PacketFilter
577                    }
578
579                    /// Available UDP transparent proxy types
580                    #[doc(hidden)]
581                    pub const fn udp_available_types() -> &'static [&'static str] {
582                        const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name()];
583                        AVAILABLE_TYPES
584                    }
585                } else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
586                    /// Default TCP transparent proxy solution on this platform
587                    pub fn tcp_default() -> RedirType {
588                        RedirType::PacketFilter
589                    }
590
591                    /// Available TCP transparent proxy types
592                    #[doc(hidden)]
593                    pub const fn tcp_available_types() -> &'static [&'static str] {
594                        const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name(), RedirType::IpFirewall.name()];
595                        AVAILABLE_TYPES
596                    }
597
598                    /// Default UDP transparent proxy solution on this platform
599                    pub fn udp_default() -> RedirType {
600                        RedirType::PacketFilter
601                    }
602
603                    /// Available UDP transparent proxy types
604                    #[doc(hidden)]
605                    pub const fn udp_available_types() -> &'static [&'static str] {
606                        const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name()];
607                        AVAILABLE_TYPES
608                    }
609                } else {
610                    /// Default TCP transparent proxy solution on this platform
611                    pub fn tcp_default() -> RedirType {
612                        RedirType::NotSupported
613                    }
614
615                    /// Available TCP transparent proxy types
616                    #[doc(hidden)]
617                    pub const fn tcp_available_types() -> &'static [&'static str] {
618                        const AVAILABLE_TYPES: &[&str] = &[];
619                        AVAILABLE_TYPES
620                    }
621
622                    /// Default UDP transparent proxy solution on this platform
623                    pub fn udp_default() -> RedirType {
624                        RedirType::NotSupported
625                    }
626
627                    /// Available UDP transparent proxy types
628                    #[doc(hidden)]
629                    pub const fn udp_available_types() -> &'static [&'static str] {
630                        const AVAILABLE_TYPES: &[&str] = &[];
631                        AVAILABLE_TYPES
632                    }
633                }
634            }
635
636            /// Check if transparent proxy is supported on this platform
637            pub fn is_supported(self) -> bool {
638                self != Self::NotSupported
639            }
640
641            /// Name of redirect type (transparent proxy type)
642            pub const fn name(self) -> &'static str {
643                match self {
644                    // Dummy, shouldn't be used in any useful situations
645                    Self::NotSupported => "not_supported",
646
647                    #[cfg(any(target_os = "linux", target_os = "android"))]
648                    Self::Redirect => "redirect",
649
650                    #[cfg(any(target_os = "linux", target_os = "android"))]
651                    Self::TProxy => "tproxy",
652
653                    #[cfg(any(
654                        target_os = "freebsd",
655                        target_os = "openbsd",
656                        target_os = "macos",
657                        target_os = "ios"
658                    ))]
659                    RedirType::PacketFilter => "pf",
660
661                    #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))]
662                    RedirType::IpFirewall => "ipfw",
663                }
664            }
665        }
666
667        impl Display for RedirType {
668            fn fmt(&self, f: &mut Formatter) -> fmt::Result {
669                f.write_str(self.name())
670            }
671        }
672
673        /// Error type for `RedirType`'s `FromStr::Err`
674        #[derive(Debug)]
675        pub struct InvalidRedirType;
676
677        impl Display for InvalidRedirType {
678            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
679                f.write_str("invalid RedirType")
680            }
681        }
682
683        impl FromStr for RedirType {
684            type Err = InvalidRedirType;
685
686            fn from_str(s: &str) -> Result<Self, InvalidRedirType> {
687                match s {
688                    #[cfg(any(target_os = "linux", target_os = "android"))]
689                    "redirect" => Ok(Self::Redirect),
690
691                    #[cfg(any(target_os = "linux", target_os = "android"))]
692                    "tproxy" => Ok(Self::TProxy),
693
694                    #[cfg(any(
695                        target_os = "freebsd",
696                        target_os = "openbsd",
697                        target_os = "macos",
698                        target_os = "ios",
699                    ))]
700                    "pf" => Ok(RedirType::PacketFilter),
701
702                    #[cfg(any(
703                        target_os = "freebsd",
704                        target_os = "macos",
705                        target_os = "ios",
706                    ))]
707                    "ipfw" => Ok(RedirType::IpFirewall),
708
709                    _ => Err(InvalidRedirType),
710                }
711            }
712        }
713    }
714}
715
716/// Host for servers to bind
717///
718/// Servers will bind to a port of this host
719#[derive(Clone, Debug)]
720pub enum ManagerServerHost {
721    /// Domain name
722    Domain(String),
723    /// IP address
724    Ip(IpAddr),
725}
726
727impl Default for ManagerServerHost {
728    fn default() -> Self {
729        Self::Ip(Ipv4Addr::UNSPECIFIED.into())
730    }
731}
732
733impl FromStr for ManagerServerHost {
734    type Err = Infallible;
735
736    fn from_str(s: &str) -> Result<Self, Self::Err> {
737        match s.parse::<IpAddr>() {
738            Ok(s) => Ok(Self::Ip(s)),
739            Err(..) => Ok(Self::Domain(s.to_owned())),
740        }
741    }
742}
743
744/// Mode of Manager's server
745#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
746pub enum ManagerServerMode {
747    /// Run shadowsocks server in the same process of manager
748    #[default]
749    Builtin,
750
751    /// Run shadowsocks server in standalone (process) mode
752    #[cfg(unix)]
753    Standalone,
754}
755
756/// Parsing ManagerServerMode error
757#[derive(Debug, Clone, Copy)]
758pub struct ManagerServerModeError;
759
760impl Display for ManagerServerModeError {
761    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
762        f.write_str("invalid ManagerServerMode")
763    }
764}
765
766impl FromStr for ManagerServerMode {
767    type Err = ManagerServerModeError;
768
769    fn from_str(s: &str) -> Result<Self, Self::Err> {
770        match s {
771            "builtin" => Ok(Self::Builtin),
772            #[cfg(unix)]
773            "standalone" => Ok(Self::Standalone),
774            _ => Err(ManagerServerModeError),
775        }
776    }
777}
778
779impl Display for ManagerServerMode {
780    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
781        match *self {
782            Self::Builtin => f.write_str("builtin"),
783            #[cfg(unix)]
784            Self::Standalone => f.write_str("standalone"),
785        }
786    }
787}
788
789/// Configuration for Manager
790#[derive(Clone, Debug)]
791pub struct ManagerConfig {
792    /// Address of `ss-manager`. Send servers' statistic data to the manager server
793    pub addr: ManagerAddr,
794    /// Manager's default method
795    pub method: Option<CipherKind>,
796    /// Manager's default plugin
797    pub plugin: Option<PluginConfig>,
798    /// Timeout for TCP connections, setting to manager's created servers
799    pub timeout: Option<Duration>,
800    /// IP/Host for servers to bind (inbound)
801    ///
802    /// Note: Outbound address is defined in Config.local_addr
803    pub server_host: ManagerServerHost,
804    /// Server's mode
805    pub mode: Mode,
806    /// Server's running mode
807    pub server_mode: ManagerServerMode,
808    /// Server's command if running in Standalone mode
809    #[cfg(unix)]
810    pub server_program: String,
811    /// Server's working directory if running in Standalone mode
812    #[cfg(unix)]
813    pub server_working_directory: PathBuf,
814}
815
816impl ManagerConfig {
817    /// Create a ManagerConfig with default options
818    pub fn new(addr: ManagerAddr) -> Self {
819        Self {
820            addr,
821            method: None,
822            plugin: None,
823            timeout: None,
824            server_host: ManagerServerHost::default(),
825            mode: Mode::TcpOnly,
826            server_mode: ManagerServerMode::Builtin,
827            #[cfg(unix)]
828            server_program: "ssserver".to_owned(),
829            #[cfg(unix)]
830            server_working_directory: match std::env::current_dir() {
831                Ok(d) => d,
832                Err(..) => "/tmp/shadowsocks-manager".into(),
833            },
834        }
835    }
836}
837
838/// Protocol of local server
839#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
840pub enum ProtocolType {
841    #[default]
842    Socks,
843    #[cfg(feature = "local-http")]
844    Http,
845    #[cfg(feature = "local-tunnel")]
846    Tunnel,
847    #[cfg(feature = "local-redir")]
848    Redir,
849    #[cfg(feature = "local-dns")]
850    Dns,
851    #[cfg(feature = "local-tun")]
852    Tun,
853    #[cfg(feature = "local-fake-dns")]
854    FakeDns,
855}
856
857impl ProtocolType {
858    /// As string representation
859    pub fn as_str(&self) -> &'static str {
860        match *self {
861            Self::Socks => "socks",
862            #[cfg(feature = "local-http")]
863            Self::Http => "http",
864            #[cfg(feature = "local-tunnel")]
865            Self::Tunnel => "tunnel",
866            #[cfg(feature = "local-redir")]
867            Self::Redir => "redir",
868            #[cfg(feature = "local-dns")]
869            Self::Dns => "dns",
870            #[cfg(feature = "local-tun")]
871            Self::Tun => "tun",
872            #[cfg(feature = "local-fake-dns")]
873            Self::FakeDns => "fake-dns",
874        }
875    }
876
877    /// Get all available protocols
878    pub fn available_protocols() -> &'static [&'static str] {
879        &[
880            "socks",
881            #[cfg(feature = "local-http")]
882            "http",
883            #[cfg(feature = "local-tunnel")]
884            "tunnel",
885            #[cfg(feature = "local-redir")]
886            "redir",
887            #[cfg(feature = "local-dns")]
888            "dns",
889            #[cfg(feature = "local-tun")]
890            "tun",
891            #[cfg(feature = "local-fake-dns")]
892            "fake-dns",
893        ]
894    }
895}
896
897/// Error while parsing `ProtocolType` from string
898#[derive(Debug)]
899pub struct ProtocolTypeError;
900
901impl Display for ProtocolTypeError {
902    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
903        f.write_str("invalid ProtocolType")
904    }
905}
906
907impl FromStr for ProtocolType {
908    type Err = ProtocolTypeError;
909
910    fn from_str(s: &str) -> Result<Self, Self::Err> {
911        match s {
912            "socks" => Ok(Self::Socks),
913            #[cfg(feature = "local-http")]
914            "http" => Ok(Self::Http),
915            #[cfg(feature = "local-tunnel")]
916            "tunnel" => Ok(Self::Tunnel),
917            #[cfg(feature = "local-redir")]
918            "redir" => Ok(Self::Redir),
919            #[cfg(feature = "local-dns")]
920            "dns" => Ok(Self::Dns),
921            #[cfg(feature = "local-tun")]
922            "tun" => Ok(Self::Tun),
923            #[cfg(feature = "local-fake-dns")]
924            "fake-dns" => Ok(Self::FakeDns),
925            _ => Err(ProtocolTypeError),
926        }
927    }
928}
929
930/// Local server configuration
931#[derive(Clone, Debug)]
932pub struct LocalConfig {
933    /// Listen address for local servers
934    pub addr: Option<ServerAddr>,
935
936    /// Local Protocol
937    pub protocol: ProtocolType,
938
939    /// Mode
940    /// Uses global `mode` if not specified
941    pub mode: Mode,
942
943    /// UDP server bind address. Uses `addr` if not specified
944    ///
945    /// Resolving Android's issue: [shadowsocks/shadowsocks-android#2571](https://github.com/shadowsocks/shadowsocks-android/issues/2571)
946    pub udp_addr: Option<ServerAddr>,
947
948    /// UDP Associate address. Uses `udp_addr` if not specified
949    pub udp_associate_addr: Option<ServerAddr>,
950
951    /// Destination address for tunnel
952    #[cfg(feature = "local-tunnel")]
953    pub forward_addr: Option<Address>,
954
955    /// TCP Transparent Proxy type
956    #[cfg(feature = "local-redir")]
957    pub tcp_redir: RedirType,
958    /// UDP Transparent Proxy type
959    #[cfg(feature = "local-redir")]
960    pub udp_redir: RedirType,
961
962    /// Local DNS's address
963    ///
964    /// Sending DNS query directly to this address
965    #[cfg(feature = "local-dns")]
966    pub local_dns_addr: Option<NameServerAddr>,
967    /// Remote DNS's address
968    ///
969    /// Sending DNS query through proxy to this address
970    #[cfg(feature = "local-dns")]
971    pub remote_dns_addr: Option<Address>,
972    // client cache size
973    // if a lot of `create connection` observed in log,
974    // increase the size
975    #[cfg(feature = "local-dns")]
976    pub client_cache_size: Option<usize>,
977
978    /// Tun interface's name
979    ///
980    /// Linux: eth0, eth1, ...
981    /// macOS: utun0, utun1, ...
982    #[cfg(feature = "local-tun")]
983    pub tun_interface_name: Option<String>,
984    /// Tun interface's address and netmask
985    #[cfg(feature = "local-tun")]
986    pub tun_interface_address: Option<IpNet>,
987    /// Tun interface's destination address and netmask
988    #[cfg(feature = "local-tun")]
989    pub tun_interface_destination: Option<IpNet>,
990    /// Tun interface's file descriptor
991    #[cfg(all(feature = "local-tun", unix))]
992    pub tun_device_fd: Option<std::os::unix::io::RawFd>,
993    /// Tun interface's file descriptor read from this Unix Domain Socket
994    #[cfg(all(feature = "local-tun", unix))]
995    pub tun_device_fd_from_path: Option<PathBuf>,
996
997    /// macOS launchd socket for TCP listener
998    ///
999    /// <https://developer.apple.com/documentation/xpc/1505523-launch_activate_socket>
1000    /// <https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html>
1001    ///
1002    /// ```plist
1003    /// <key>Sockets</key>
1004    /// <dict>
1005    ///     <key>{launchd_tcp_socket_name}</key>
1006    ///     <dict>
1007    ///         <key>SockType</key>
1008    ///         <string>stream</string>
1009    ///         ... other keys ...
1010    ///     </dict>
1011    /// </dict>
1012    /// ```
1013    #[cfg(target_os = "macos")]
1014    pub launchd_tcp_socket_name: Option<String>,
1015    /// macOS launchd socket for UDP listener
1016    ///
1017    /// <https://developer.apple.com/documentation/xpc/1505523-launch_activate_socket>
1018    /// <https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html>
1019    ///
1020    /// ```plist
1021    /// <key>Sockets</key>
1022    /// <dict>
1023    ///     <key>{launchd_udp_socket_name}</key>
1024    ///     <dict>
1025    ///         <key>SockType</key>
1026    ///         <string>dgram</string>
1027    ///         ... other keys ...
1028    ///     </dict>
1029    /// </dict>
1030    /// ```
1031    #[cfg(target_os = "macos")]
1032    pub launchd_udp_socket_name: Option<String>,
1033
1034    /// Set `IPV6_V6ONLY` for listener socket
1035    pub ipv6_only: bool,
1036
1037    /// SOCKS5 Authentication configuration
1038    #[cfg(feature = "local")]
1039    pub socks5_auth: Socks5AuthConfig,
1040
1041    /// Fake DNS record expire seconds
1042    #[cfg(feature = "local-fake-dns")]
1043    pub fake_dns_record_expire_duration: Option<Duration>,
1044    /// Fake DNS IPv4 allocation space
1045    #[cfg(feature = "local-fake-dns")]
1046    pub fake_dns_ipv4_network: Option<Ipv4Net>,
1047    /// Fake DNS IPv6 allocation space
1048    #[cfg(feature = "local-fake-dns")]
1049    pub fake_dns_ipv6_network: Option<Ipv6Net>,
1050    /// Fake DNS storage database path
1051    #[cfg(feature = "local-fake-dns")]
1052    pub fake_dns_database_path: Option<PathBuf>,
1053}
1054
1055impl LocalConfig {
1056    /// Create a new `LocalConfig`
1057    pub fn new(protocol: ProtocolType) -> Self {
1058        // DNS server runs in `TcpAndUdp` mode by default to maintain backwards compatibility
1059        // see https://github.com/shadowsocks/shadowsocks-rust/issues/1281
1060        let mode = match protocol {
1061            #[cfg(feature = "local-dns")]
1062            ProtocolType::Dns => Mode::TcpAndUdp,
1063            _ => Mode::TcpOnly,
1064        };
1065
1066        Self {
1067            addr: None,
1068
1069            protocol,
1070
1071            mode,
1072            udp_addr: None,
1073            udp_associate_addr: None,
1074
1075            #[cfg(feature = "local-tunnel")]
1076            forward_addr: None,
1077
1078            #[cfg(feature = "local-redir")]
1079            tcp_redir: RedirType::tcp_default(),
1080            #[cfg(feature = "local-redir")]
1081            udp_redir: RedirType::udp_default(),
1082
1083            #[cfg(feature = "local-dns")]
1084            local_dns_addr: None,
1085            #[cfg(feature = "local-dns")]
1086            remote_dns_addr: None,
1087            #[cfg(feature = "local-dns")]
1088            client_cache_size: None,
1089
1090            #[cfg(feature = "local-tun")]
1091            tun_interface_name: None,
1092            #[cfg(feature = "local-tun")]
1093            tun_interface_address: None,
1094            #[cfg(feature = "local-tun")]
1095            tun_interface_destination: None,
1096            #[cfg(all(feature = "local-tun", unix))]
1097            tun_device_fd: None,
1098            #[cfg(all(feature = "local-tun", unix))]
1099            tun_device_fd_from_path: None,
1100
1101            #[cfg(target_os = "macos")]
1102            launchd_tcp_socket_name: None,
1103            #[cfg(target_os = "macos")]
1104            launchd_udp_socket_name: None,
1105
1106            ipv6_only: false,
1107
1108            #[cfg(feature = "local")]
1109            socks5_auth: Socks5AuthConfig::default(),
1110
1111            #[cfg(feature = "local-fake-dns")]
1112            fake_dns_record_expire_duration: None,
1113            #[cfg(feature = "local-fake-dns")]
1114            fake_dns_ipv4_network: None,
1115            #[cfg(feature = "local-fake-dns")]
1116            fake_dns_ipv6_network: None,
1117            #[cfg(feature = "local-fake-dns")]
1118            fake_dns_database_path: None,
1119        }
1120    }
1121
1122    /// Create a new `LocalConfig` with listen address
1123    pub fn new_with_addr(addr: ServerAddr, protocol: ProtocolType) -> Self {
1124        let mut config = Self::new(protocol);
1125        config.addr = Some(addr);
1126        config
1127    }
1128
1129    fn check_integrity(&self) -> Result<(), Error> {
1130        match self.protocol {
1131            #[cfg(feature = "local-tun")]
1132            ProtocolType::Tun => {}
1133
1134            _ => {
1135                if self.addr.is_none() {
1136                    let err = Error::new(ErrorKind::MissingField, "missing `addr` in configuration", None);
1137                    return Err(err);
1138                }
1139            }
1140        }
1141
1142        match self.protocol {
1143            #[cfg(feature = "local-dns")]
1144            ProtocolType::Dns => {
1145                if self.local_dns_addr.is_none() || self.remote_dns_addr.is_none() {
1146                    let err = Error::new(
1147                        ErrorKind::MissingField,
1148                        "missing `local_dns_addr` or `remote_dns_addr` in configuration",
1149                        None,
1150                    );
1151                    return Err(err);
1152                }
1153            }
1154            #[cfg(feature = "local-tunnel")]
1155            ProtocolType::Tunnel => {
1156                if self.forward_addr.is_none() {
1157                    let err = Error::new(ErrorKind::MissingField, "missing `forward_addr` in configuration", None);
1158                    return Err(err);
1159                }
1160            }
1161
1162            #[cfg(feature = "local-http")]
1163            ProtocolType::Http => {
1164                if !self.mode.enable_tcp() {
1165                    let err = Error::new(ErrorKind::Invalid, "TCP mode have to be enabled for http", None);
1166                    return Err(err);
1167                }
1168            }
1169
1170            _ => {}
1171        }
1172
1173        Ok(())
1174    }
1175
1176    // Check if it is a basic format of local
1177    pub fn is_basic(&self) -> bool {
1178        if self.protocol != ProtocolType::Socks || self.udp_addr.is_some() {
1179            return false;
1180        }
1181
1182        #[cfg(feature = "local-tunnel")]
1183        if self.forward_addr.is_some() {
1184            return false;
1185        }
1186
1187        #[cfg(feature = "local-redir")]
1188        if self.tcp_redir != RedirType::tcp_default() || self.udp_redir != RedirType::udp_default() {
1189            return false;
1190        }
1191
1192        #[cfg(feature = "local-dns")]
1193        if self.local_dns_addr.is_some() || self.remote_dns_addr.is_some() {
1194            return false;
1195        }
1196
1197        true
1198    }
1199}
1200
1201#[derive(Clone, Debug, Default)]
1202pub enum DnsConfig {
1203    #[default]
1204    System,
1205    #[cfg(feature = "hickory-dns")]
1206    HickoryDns(ResolverConfig),
1207    #[cfg(feature = "local-dns")]
1208    LocalDns(NameServerAddr),
1209}
1210
1211/// Security Config
1212#[derive(Clone, Debug, Default)]
1213pub struct SecurityConfig {
1214    pub replay_attack: SecurityReplayAttackConfig,
1215}
1216
1217#[derive(Clone, Debug, Default)]
1218pub struct SecurityReplayAttackConfig {
1219    pub policy: ReplayAttackPolicy,
1220}
1221
1222/// Balancer Config
1223#[derive(Clone, Debug, Default)]
1224pub struct BalancerConfig {
1225    /// MAX rtt of servers, which is the timeout duration of each check requests
1226    pub max_server_rtt: Option<Duration>,
1227    /// Interval between each checking
1228    pub check_interval: Option<Duration>,
1229    /// Interval for checking the best server
1230    pub check_best_interval: Option<Duration>,
1231}
1232
1233/// Address for local to report flow statistic data
1234#[cfg(feature = "local-flow-stat")]
1235#[derive(Debug, Clone)]
1236pub enum LocalFlowStatAddress {
1237    /// UNIX Domain Socket address
1238    #[cfg(unix)]
1239    UnixStreamPath(PathBuf),
1240    /// TCP Stream Address
1241    TcpStreamAddr(SocketAddr),
1242}
1243
1244/// Server instance config
1245#[derive(Debug, Clone)]
1246pub struct ServerInstanceConfig {
1247    /// Server's config
1248    pub config: ServerConfig,
1249    /// Server's private ACL, set to `None` will use the global `AccessControl`
1250    pub acl: Option<AccessControl>,
1251    /// Server's outbound fwmark / address / interface to support split tunnel
1252    #[cfg(any(target_os = "linux", target_os = "android"))]
1253    pub outbound_fwmark: Option<u32>,
1254    #[cfg(target_os = "freebsd")]
1255    pub outbound_user_cookie: Option<u32>,
1256    pub outbound_bind_addr: Option<IpAddr>,
1257    pub outbound_bind_interface: Option<String>,
1258    pub outbound_udp_allow_fragmentation: Option<bool>,
1259}
1260
1261impl ServerInstanceConfig {
1262    /// Create with `ServerConfig`
1263    pub fn with_server_config(config: ServerConfig) -> Self {
1264        Self {
1265            config,
1266            acl: None,
1267            #[cfg(any(target_os = "linux", target_os = "android"))]
1268            outbound_fwmark: None,
1269            #[cfg(target_os = "freebsd")]
1270            outbound_user_cookie: None,
1271            outbound_bind_addr: None,
1272            outbound_bind_interface: None,
1273            outbound_udp_allow_fragmentation: None,
1274        }
1275    }
1276}
1277
1278/// Local instance config
1279#[derive(Debug, Clone)]
1280pub struct LocalInstanceConfig {
1281    /// Local server's config
1282    pub config: LocalConfig,
1283    /// Server's private ACL, set to `None` will use the global `AccessControl`
1284    pub acl: Option<AccessControl>,
1285}
1286
1287impl LocalInstanceConfig {
1288    /// Create with `LocalConfig`
1289    pub fn with_local_config(config: LocalConfig) -> Self {
1290        Self { config, acl: None }
1291    }
1292}
1293
1294/// OnlineConfiguration (SIP008)
1295/// https://shadowsocks.org/doc/sip008.html
1296#[cfg(feature = "local-online-config")]
1297#[derive(Debug, Clone)]
1298pub struct OnlineConfig {
1299    /// SIP008 URL
1300    pub config_url: String,
1301    /// Update interval, 3600s by default
1302    pub update_interval: Option<Duration>,
1303    /// Allowed plugins
1304    pub allowed_plugins: Option<Vec<String>>,
1305}
1306
1307/// Configuration
1308#[derive(Clone, Debug)]
1309pub struct Config {
1310    /// Remote ShadowSocks server configurations
1311    pub server: Vec<ServerInstanceConfig>,
1312    /// Local server configuration
1313    pub local: Vec<LocalInstanceConfig>,
1314
1315    /// DNS configuration, uses system-wide DNS configuration by default
1316    ///
1317    /// Value could be a `IpAddr`, uses UDP DNS protocol with port `53`. For example: `8.8.8.8`
1318    ///
1319    /// Also Value could be some pre-defined DNS server names:
1320    ///
1321    /// - `google`
1322    /// - `cloudflare`, `cloudflare_tls`, `cloudflare_https`
1323    /// - `quad9`, `quad9_tls`
1324    pub dns: DnsConfig,
1325    pub dns_cache_size: Option<usize>,
1326    /// Uses IPv6 addresses first
1327    ///
1328    /// Set to `true` if you want to query IPv6 addresses before IPv4
1329    pub ipv6_first: bool,
1330    /// Set `IPV6_V6ONLY` for listener sockets
1331    pub ipv6_only: bool,
1332
1333    /// Set `TCP_NODELAY` socket option
1334    pub no_delay: bool,
1335    /// Set `TCP_FASTOPEN` socket option
1336    pub fast_open: bool,
1337    /// Set TCP Keep-Alive duration, will set both `TCP_KEEPIDLE` and `TCP_KEEPINTVL`
1338    ///
1339    /// <https://github.com/shadowsocks/shadowsocks-rust/issues/546>
1340    ///
1341    /// If this is not set, sockets will be set with a default timeout
1342    pub keep_alive: Option<Duration>,
1343    /// Multipath-TCP
1344    pub mptcp: bool,
1345
1346    /// `RLIMIT_NOFILE` option for *nix systems
1347    #[cfg(all(unix, not(target_os = "android")))]
1348    pub nofile: Option<u64>,
1349
1350    /// Set `SO_MARK` socket option for outbound sockets
1351    #[cfg(any(target_os = "linux", target_os = "android"))]
1352    pub outbound_fwmark: Option<u32>,
1353    /// Set `SO_USER_COOKIE` socket option for outbound sockets
1354    #[cfg(target_os = "freebsd")]
1355    pub outbound_user_cookie: Option<u32>,
1356    /// Set `SO_BINDTODEVICE` (Linux), `IP_BOUND_IF` (BSD), `IP_UNICAST_IF` (Windows) socket option for outbound sockets
1357    pub outbound_bind_interface: Option<String>,
1358    /// Outbound sockets will `bind` to this address
1359    pub outbound_bind_addr: Option<IpAddr>,
1360    /// Outbound UDP sockets allow IP fragmentation
1361    pub outbound_udp_allow_fragmentation: bool,
1362    /// Path to protect callback unix address, only for Android
1363    #[cfg(target_os = "android")]
1364    pub outbound_vpn_protect_path: Option<PathBuf>,
1365
1366    /// Set `SO_SNDBUF` for inbound sockets
1367    pub inbound_send_buffer_size: Option<u32>,
1368    /// Set `SO_RCVBUF` for inbound sockets
1369    pub inbound_recv_buffer_size: Option<u32>,
1370    /// Set `SO_SNDBUF` for outbound sockets
1371    pub outbound_send_buffer_size: Option<u32>,
1372    /// Set `SO_RCVBUF` for outbound sockets
1373    pub outbound_recv_buffer_size: Option<u32>,
1374
1375    /// Manager's configuration
1376    pub manager: Option<ManagerConfig>,
1377
1378    /// Config is for Client or Server
1379    pub config_type: ConfigType,
1380
1381    /// Timeout for UDP Associations, default is 5 minutes
1382    pub udp_timeout: Option<Duration>,
1383    /// Maximum number of UDP Associations, default is unconfigured
1384    pub udp_max_associations: Option<usize>,
1385    /// Maximum Transmission Unit (MTU) size for UDP packets
1386    /// 65535 by default. Suggestion: 1500
1387    /// NOTE: mtu includes IP header, UDP header, UDP payload
1388    pub udp_mtu: Option<usize>,
1389
1390    /// ACL configuration (Global)
1391    ///
1392    /// Could be overwritten by servers/locals' private `acl`
1393    pub acl: Option<AccessControl>,
1394
1395    /// Flow statistic report Unix socket path (only for Android)
1396    #[cfg(feature = "local-flow-stat")]
1397    pub local_stat_addr: Option<LocalFlowStatAddress>,
1398
1399    /// Replay attack policy
1400    pub security: SecurityConfig,
1401
1402    /// Balancer config of local server
1403    pub balancer: BalancerConfig,
1404
1405    /// Configuration file path, the actual path of the configuration.
1406    /// This is normally for auto-reloading if implementation supports.
1407    pub config_path: Option<PathBuf>,
1408
1409    /// OnlineConfiguration (SIP008)
1410    /// https://shadowsocks.org/doc/sip008.html
1411    #[cfg(feature = "local-online-config")]
1412    pub online_config: Option<OnlineConfig>,
1413}
1414
1415/// Configuration parsing error kind
1416#[derive(Copy, Clone, Debug)]
1417pub enum ErrorKind {
1418    /// Missing required fields in JSON configuration
1419    MissingField,
1420    /// Missing some keys that must be provided together
1421    Malformed,
1422    /// Invalid value of some configuration keys
1423    Invalid,
1424    /// Invalid JSON
1425    JsonParsingError,
1426    /// `std::io::Error`
1427    IoError,
1428}
1429
1430/// Configuration parsing error
1431pub struct Error {
1432    pub kind: ErrorKind,
1433    pub desc: &'static str,
1434    pub detail: Option<String>,
1435}
1436
1437impl Error {
1438    pub fn new(kind: ErrorKind, desc: &'static str, detail: Option<String>) -> Self {
1439        Self { kind, desc, detail }
1440    }
1441}
1442
1443impl std::error::Error for Error {
1444    fn description(&self) -> &str {
1445        self.desc
1446    }
1447}
1448
1449macro_rules! impl_from {
1450    ($error:ty, $kind:expr, $desc:expr) => {
1451        impl From<$error> for Error {
1452            fn from(err: $error) -> Self {
1453                Error::new($kind, $desc, Some(format!("{:?}", err)))
1454            }
1455        }
1456    };
1457}
1458
1459impl_from!(::std::io::Error, ErrorKind::IoError, "error while reading file");
1460impl_from!(json5::Error, ErrorKind::JsonParsingError, "json parse error");
1461impl_from!(serde_json::Error, ErrorKind::JsonParsingError, "json parse error");
1462
1463impl Debug for Error {
1464    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1465        match self.detail {
1466            None => write!(f, "{}", self.desc),
1467            Some(ref det) => write!(f, "{} {}", self.desc, det),
1468        }
1469    }
1470}
1471
1472impl Display for Error {
1473    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1474        match self.detail {
1475            None => f.write_str(self.desc),
1476            Some(ref d) => write!(f, "{}, {}", self.desc, d),
1477        }
1478    }
1479}
1480
1481impl Config {
1482    /// Creates an empty configuration
1483    pub fn new(config_type: ConfigType) -> Self {
1484        Self {
1485            server: Vec::new(),
1486            local: Vec::new(),
1487
1488            dns: DnsConfig::default(),
1489            dns_cache_size: None,
1490            ipv6_first: false,
1491            ipv6_only: false,
1492
1493            no_delay: false,
1494            fast_open: false,
1495            keep_alive: None,
1496            mptcp: false,
1497
1498            #[cfg(all(unix, not(target_os = "android")))]
1499            nofile: None,
1500
1501            #[cfg(any(target_os = "linux", target_os = "android"))]
1502            outbound_fwmark: None,
1503            #[cfg(target_os = "freebsd")]
1504            outbound_user_cookie: None,
1505            outbound_bind_interface: None,
1506            outbound_bind_addr: None,
1507            outbound_udp_allow_fragmentation: false,
1508            #[cfg(target_os = "android")]
1509            outbound_vpn_protect_path: None,
1510
1511            inbound_send_buffer_size: None,
1512            inbound_recv_buffer_size: None,
1513            outbound_send_buffer_size: None,
1514            outbound_recv_buffer_size: None,
1515
1516            manager: None,
1517
1518            config_type,
1519
1520            udp_timeout: None,
1521            udp_max_associations: None,
1522            udp_mtu: None,
1523
1524            acl: None,
1525
1526            #[cfg(feature = "local-flow-stat")]
1527            local_stat_addr: None,
1528
1529            security: SecurityConfig::default(),
1530
1531            balancer: BalancerConfig::default(),
1532
1533            config_path: None,
1534
1535            #[cfg(feature = "local-online-config")]
1536            online_config: None,
1537        }
1538    }
1539
1540    fn load_from_ssconfig(config: SSConfig, config_type: ConfigType) -> Result<Self, Error> {
1541        let mut nconfig = Self::new(config_type);
1542
1543        // Client
1544        //
1545        // local_address is allowed to be NULL, which means to bind to ::1 or 127.0.0.1
1546        //
1547        // https://shadowsocks.org/en/config/quick-guide.html
1548        #[inline]
1549        fn get_local_address(local_address: Option<String>, local_port: u16, ipv6_first: bool) -> ServerAddr {
1550            match local_address {
1551                Some(addr) => {
1552                    match addr.parse::<IpAddr>() {
1553                        Ok(ip) => ServerAddr::from(SocketAddr::new(ip, local_port)),
1554                        Err(..) => {
1555                            // treated as domain
1556                            ServerAddr::from((addr, local_port))
1557                        }
1558                    }
1559                }
1560                None => {
1561                    // Implementation note: This is not implemented like libev which will choose IPv6 or IPv6 LoopBack address
1562                    // by checking all its remote servers if all of them supports IPv6.
1563                    let ip = if ipv6_first {
1564                        Ipv6Addr::LOCALHOST.into()
1565                    } else {
1566                        Ipv4Addr::LOCALHOST.into()
1567                    };
1568
1569                    ServerAddr::from(SocketAddr::new(ip, local_port))
1570                }
1571            }
1572        }
1573
1574        // Mode
1575        let mut global_mode = Mode::TcpOnly;
1576        if let Some(m) = config.mode {
1577            match m.parse::<Mode>() {
1578                Ok(xm) => global_mode = xm,
1579                Err(..) => {
1580                    let e = Error::new(
1581                        ErrorKind::Malformed,
1582                        "malformed `mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`",
1583                        None,
1584                    );
1585                    return Err(e);
1586                }
1587            }
1588        }
1589
1590        match config_type {
1591            ConfigType::Local => {
1592                // Standard config
1593                if config.local_address.is_some() && config.local_port.unwrap_or(0) == 0 {
1594                    let err = Error::new(ErrorKind::MissingField, "missing `local_port`", None);
1595                    return Err(err);
1596                }
1597
1598                if let Some(local_port) = config.local_port {
1599                    // local_port won't be 0, it was checked above
1600                    assert_ne!(local_port, 0);
1601
1602                    let local_addr =
1603                        get_local_address(config.local_address, local_port, config.ipv6_first.unwrap_or(false));
1604
1605                    // shadowsocks uses SOCKS5 by default
1606                    let mut local_config = LocalConfig::new(ProtocolType::Socks);
1607                    local_config.addr = Some(local_addr);
1608                    local_config.mode = global_mode;
1609                    local_config.protocol = match config.protocol {
1610                        None => ProtocolType::Socks,
1611                        Some(p) => match p.parse::<ProtocolType>() {
1612                            Ok(p) => p,
1613                            Err(..) => {
1614                                let err = Error::new(
1615                                    ErrorKind::Malformed,
1616                                    "`protocol` invalid",
1617                                    Some(format!("unrecognized protocol {p}")),
1618                                );
1619                                return Err(err);
1620                            }
1621                        },
1622                    };
1623                    #[cfg(target_os = "macos")]
1624                    {
1625                        local_config
1626                            .launchd_tcp_socket_name
1627                            .clone_from(&config.launchd_tcp_socket_name);
1628                        local_config
1629                            .launchd_udp_socket_name
1630                            .clone_from(&config.launchd_udp_socket_name);
1631                    }
1632
1633                    let local_instance = LocalInstanceConfig {
1634                        config: local_config,
1635                        acl: None,
1636                    };
1637
1638                    nconfig.local.push(local_instance);
1639                }
1640
1641                // Ext locals
1642                // `locals` are only effective in local server
1643                if let Some(locals) = config.locals {
1644                    for local in locals {
1645                        if local.disabled.unwrap_or(false) {
1646                            continue;
1647                        }
1648
1649                        let protocol = match local.protocol {
1650                            None => ProtocolType::Socks,
1651                            Some(p) => match p.parse::<ProtocolType>() {
1652                                Ok(p) => p,
1653                                Err(..) => {
1654                                    let err = Error::new(
1655                                        ErrorKind::Malformed,
1656                                        "`protocol` invalid",
1657                                        Some(format!("unrecognized protocol {p}")),
1658                                    );
1659                                    return Err(err);
1660                                }
1661                            },
1662                        };
1663
1664                        let mut local_config = LocalConfig::new(protocol);
1665
1666                        if let Some(local_port) = local.local_port {
1667                            if local_port == 0 {
1668                                let err = Error::new(ErrorKind::Malformed, "`local_port` cannot be 0", None);
1669                                return Err(err);
1670                            }
1671
1672                            let local_addr =
1673                                get_local_address(local.local_address, local_port, config.ipv6_first.unwrap_or(false));
1674                            local_config.addr = Some(local_addr);
1675                        } else if local.local_address.is_some() {
1676                            let err = Error::new(ErrorKind::Malformed, "missing `local_port`", None);
1677                            return Err(err);
1678                        }
1679
1680                        if let Some(local_udp_port) = local.local_udp_port {
1681                            if local_udp_port == 0 {
1682                                let err = Error::new(ErrorKind::Malformed, "`local_udp_port` cannot be 0", None);
1683                                return Err(err);
1684                            }
1685
1686                            let local_udp_addr = get_local_address(
1687                                local.local_udp_address,
1688                                local_udp_port,
1689                                config.ipv6_first.unwrap_or(false),
1690                            );
1691
1692                            local_config.udp_addr = Some(local_udp_addr);
1693                        }
1694
1695                        #[cfg(target_os = "macos")]
1696                        {
1697                            local_config.launchd_tcp_socket_name = local.launchd_tcp_socket_name;
1698                            local_config.launchd_udp_socket_name = local.launchd_udp_socket_name;
1699                        }
1700
1701                        match local.mode {
1702                            Some(mode) => match mode.parse::<Mode>() {
1703                                Ok(mode) => local_config.mode = mode,
1704                                Err(..) => {
1705                                    let err = Error::new(ErrorKind::Malformed, "invalid `mode`", None);
1706                                    return Err(err);
1707                                }
1708                            },
1709                            None => {
1710                                // DNS server runs in `TcpAndUdp` mode by default to maintain backwards compatibility
1711                                // see https://github.com/shadowsocks/shadowsocks-rust/issues/1281
1712                                let mode = match protocol {
1713                                    #[cfg(feature = "local-dns")]
1714                                    ProtocolType::Dns => Mode::TcpAndUdp,
1715                                    _ => global_mode,
1716                                };
1717
1718                                local_config.mode = mode;
1719                            }
1720                        }
1721
1722                        #[cfg(feature = "local-tunnel")]
1723                        if let Some(forward_address) = local.forward_address {
1724                            let forward_port = match local.forward_port {
1725                                None | Some(0) => {
1726                                    let err =
1727                                        Error::new(ErrorKind::Malformed, "`forward_port` cannot be missing or 0", None);
1728                                    return Err(err);
1729                                }
1730                                Some(p) => p,
1731                            };
1732
1733                            local_config.forward_addr = Some(match forward_address.parse::<IpAddr>() {
1734                                Ok(ip) => Address::from(SocketAddr::new(ip, forward_port)),
1735                                Err(..) => Address::from((forward_address, forward_port)),
1736                            });
1737                        }
1738
1739                        #[cfg(feature = "local-redir")]
1740                        if let Some(tcp_redir) = local.tcp_redir {
1741                            match tcp_redir.parse::<RedirType>() {
1742                                Ok(r) => local_config.tcp_redir = r,
1743                                Err(..) => {
1744                                    let err = Error::new(ErrorKind::Malformed, "`tcp_redir` invalid", None);
1745                                    return Err(err);
1746                                }
1747                            }
1748                        }
1749
1750                        #[cfg(feature = "local-redir")]
1751                        if let Some(udp_redir) = local.udp_redir {
1752                            match udp_redir.parse::<RedirType>() {
1753                                Ok(r) => local_config.udp_redir = r,
1754                                Err(..) => {
1755                                    let err = Error::new(ErrorKind::Malformed, "`udp_redir` invalid", None);
1756                                    return Err(err);
1757                                }
1758                            }
1759                        }
1760
1761                        #[cfg(feature = "local-dns")]
1762                        if let Some(local_dns_address) = local.local_dns_address {
1763                            match local_dns_address.parse::<IpAddr>() {
1764                                Ok(ip) => {
1765                                    local_config.local_dns_addr = Some(NameServerAddr::SocketAddr(SocketAddr::new(
1766                                        ip,
1767                                        local.local_dns_port.unwrap_or(53),
1768                                    )));
1769                                }
1770                                #[cfg(unix)]
1771                                Err(..) => {
1772                                    local_config.local_dns_addr =
1773                                        Some(NameServerAddr::UnixSocketAddr(PathBuf::from(local_dns_address)));
1774                                }
1775                                #[cfg(not(unix))]
1776                                Err(..) => {
1777                                    let err = Error::new(ErrorKind::Malformed, "`local_dns_address` invalid", None);
1778                                    return Err(err);
1779                                }
1780                            }
1781                        }
1782
1783                        #[cfg(feature = "local-dns")]
1784                        if let Some(client_cache_size) = local.client_cache_size {
1785                            local_config.client_cache_size = Some(client_cache_size);
1786                        }
1787
1788                        #[cfg(feature = "local-dns")]
1789                        if let Some(remote_dns_address) = local.remote_dns_address {
1790                            let remote_dns_port = local.remote_dns_port.unwrap_or(53);
1791                            local_config.remote_dns_addr = Some(match remote_dns_address.parse::<IpAddr>() {
1792                                Ok(ip) => Address::from(SocketAddr::new(ip, remote_dns_port)),
1793                                Err(..) => Address::from((remote_dns_address, remote_dns_port)),
1794                            });
1795                        }
1796
1797                        #[cfg(feature = "local-tun")]
1798                        if let Some(tun_interface_address) = local.tun_interface_address {
1799                            match tun_interface_address.parse::<IpNet>() {
1800                                Ok(addr) => local_config.tun_interface_address = Some(addr),
1801                                Err(..) => {
1802                                    let err = Error::new(ErrorKind::Malformed, "`tun_interface_address` invalid", None);
1803                                    return Err(err);
1804                                }
1805                            }
1806                        }
1807
1808                        #[cfg(feature = "local-tun")]
1809                        if let Some(tun_interface_destination) = local.tun_interface_destination {
1810                            match tun_interface_destination.parse::<IpNet>() {
1811                                Ok(addr) => local_config.tun_interface_destination = Some(addr),
1812                                Err(..) => {
1813                                    let err =
1814                                        Error::new(ErrorKind::Malformed, "`tun_interface_destination` invalid", None);
1815                                    return Err(err);
1816                                }
1817                            }
1818                        }
1819
1820                        #[cfg(feature = "local-tun")]
1821                        if let Some(tun_interface_name) = local.tun_interface_name {
1822                            local_config.tun_interface_name = Some(tun_interface_name);
1823                        }
1824
1825                        #[cfg(all(feature = "local-tun", unix))]
1826                        if let Some(tun_device_fd_from_path) = local.tun_device_fd_from_path {
1827                            local_config.tun_device_fd_from_path = Some(From::from(tun_device_fd_from_path));
1828                        }
1829
1830                        #[cfg(feature = "local")]
1831                        if let Some(socks5_auth_config_path) = local.socks5_auth_config_path {
1832                            local_config.socks5_auth = Socks5AuthConfig::load_from_file(&socks5_auth_config_path)?;
1833                        }
1834
1835                        #[cfg(feature = "local-fake-dns")]
1836                        {
1837                            if let Some(d) = local.fake_dns_record_expire_duration {
1838                                local_config.fake_dns_record_expire_duration = Some(Duration::from_secs(d));
1839                            }
1840                            if let Some(n) = local.fake_dns_ipv4_network {
1841                                match n.parse::<Ipv4Net>() {
1842                                    Ok(n) => local_config.fake_dns_ipv4_network = Some(n),
1843                                    Err(..) => {
1844                                        let err =
1845                                            Error::new(ErrorKind::Malformed, "invalid `fake_dns_ipv4_network`", None);
1846                                        return Err(err);
1847                                    }
1848                                }
1849                            }
1850                            if let Some(n) = local.fake_dns_ipv6_network {
1851                                match n.parse::<Ipv6Net>() {
1852                                    Ok(n) => local_config.fake_dns_ipv6_network = Some(n),
1853                                    Err(..) => {
1854                                        let err =
1855                                            Error::new(ErrorKind::Malformed, "invalid `fake_dns_ipv6_network`", None);
1856                                        return Err(err);
1857                                    }
1858                                }
1859                            }
1860                            if let Some(p) = local.fake_dns_database_path {
1861                                local_config.fake_dns_database_path = Some(p.into());
1862                            }
1863                        }
1864
1865                        let mut local_instance = LocalInstanceConfig {
1866                            config: local_config,
1867                            acl: None,
1868                        };
1869
1870                        if let Some(acl_path) = local.acl {
1871                            let acl = match AccessControl::load_from_file(&acl_path) {
1872                                Ok(acl) => acl,
1873                                Err(err) => {
1874                                    let err = Error::new(
1875                                        ErrorKind::Invalid,
1876                                        "acl loading failed",
1877                                        Some(format!("file {acl_path}, error: {err}")),
1878                                    );
1879                                    return Err(err);
1880                                }
1881                            };
1882                            local_instance.acl = Some(acl);
1883                        }
1884
1885                        nconfig.local.push(local_instance);
1886                    }
1887                }
1888            }
1889            ConfigType::Server | ConfigType::Manager => {
1890                // NOTE: IGNORED.
1891                // servers only uses `local_address` for binding outbound interfaces
1892                //
1893                // This behavior causes lots of confusion. use outbound_bind_addr instead
1894            }
1895            #[cfg(feature = "local-online-config")]
1896            ConfigType::OnlineConfig => {
1897                // SIP008. https://shadowsocks.org/doc/sip008.html
1898                // "version" should be set to "1"
1899                match config.version {
1900                    Some(1) => {}
1901                    Some(v) => {
1902                        let err = Error::new(
1903                            ErrorKind::Invalid,
1904                            "invalid online config version",
1905                            Some(format!("version: {v}")),
1906                        );
1907                        return Err(err);
1908                    }
1909                    None => {
1910                        warn!(
1911                            "OnlineConfig \"version\" is missing in the configuration, assuming it is a compatible version for this project"
1912                        );
1913                    }
1914                }
1915            }
1916        }
1917
1918        let server_source = match config_type {
1919            ConfigType::Local | ConfigType::Server | ConfigType::Manager => ServerSource::Configuration,
1920            #[cfg(feature = "local-online-config")]
1921            ConfigType::OnlineConfig => ServerSource::OnlineConfig,
1922        };
1923
1924        // Standard config
1925        // Server
1926        match (config.server, config.server_port, config.password, &config.method) {
1927            (Some(address), Some(port), pwd_opt, Some(m)) => {
1928                let addr = match address.parse::<Ipv4Addr>() {
1929                    Ok(v4) => ServerAddr::SocketAddr(SocketAddr::V4(SocketAddrV4::new(v4, port))),
1930                    Err(..) => match address.parse::<Ipv6Addr>() {
1931                        Ok(v6) => ServerAddr::SocketAddr(SocketAddr::V6(SocketAddrV6::new(v6, port, 0, 0))),
1932                        Err(..) => ServerAddr::DomainName(address, port),
1933                    },
1934                };
1935
1936                let method = match m.parse::<CipherKind>() {
1937                    Ok(m) => m,
1938                    Err(..) => {
1939                        let err = Error::new(
1940                            ErrorKind::Invalid,
1941                            "unsupported method",
1942                            Some(format!("`{m}` is not a supported method")),
1943                        );
1944                        return Err(err);
1945                    }
1946                };
1947
1948                // Only "password" support getting from environment variable.
1949                let password = match pwd_opt {
1950                    Some(ref pwd) => read_variable_field_value(pwd),
1951                    None => {
1952                        if method.is_none() {
1953                            String::new().into()
1954                        } else {
1955                            let err = Error::new(
1956                                ErrorKind::MissingField,
1957                                "`password` is required",
1958                                Some(format!("`password` is required for method {method}")),
1959                            );
1960                            return Err(err);
1961                        }
1962                    }
1963                };
1964
1965                let mut nsvr = match ServerConfig::new(addr, password, method) {
1966                    Ok(svr) => svr,
1967                    Err(serr) => {
1968                        let err = Error::new(
1969                            ErrorKind::Malformed,
1970                            "server config create failed",
1971                            Some(format!("{}", serr)),
1972                        );
1973                        return Err(err);
1974                    }
1975                };
1976                nsvr.set_source(server_source);
1977                nsvr.set_mode(global_mode);
1978
1979                if let Some(ref p) = config.plugin {
1980                    // SIP008 allows "plugin" to be an empty string
1981                    // Empty string implies "no plugin"
1982                    if !p.is_empty() {
1983                        let plugin = PluginConfig {
1984                            plugin: p.clone(),
1985                            plugin_opts: config.plugin_opts.clone(),
1986                            plugin_args: config.plugin_args.clone().unwrap_or_default(),
1987                            plugin_mode: match config.plugin_mode {
1988                                None => Mode::TcpOnly,
1989                                Some(ref mode) => match mode.parse::<Mode>() {
1990                                    Ok(m) => m,
1991                                    Err(..) => {
1992                                        let e = Error::new(
1993                                            ErrorKind::Malformed,
1994                                            "malformed `plugin_mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`",
1995                                            None,
1996                                        );
1997                                        return Err(e);
1998                                    }
1999                                },
2000                            },
2001                        };
2002                        nsvr.set_plugin(plugin);
2003                    }
2004                }
2005
2006                if let Some(timeout) = config.timeout.map(Duration::from_secs) {
2007                    nsvr.set_timeout(timeout);
2008                }
2009
2010                nconfig.server.push(ServerInstanceConfig::with_server_config(nsvr));
2011            }
2012            (None, None, None, Some(_)) if config_type.is_manager() => {
2013                // Set the default method for manager
2014            }
2015            (None, None, None, None) => (),
2016            _ => {
2017                let err = Error::new(
2018                    ErrorKind::Malformed,
2019                    "`server`, `server_port`, `method`, `password` must be provided together",
2020                    None,
2021                );
2022                return Err(err);
2023            }
2024        }
2025
2026        // Ext servers
2027        if let Some(servers) = config.servers {
2028            for svr in servers {
2029                // Skip if server is disabled
2030                if svr.disabled.unwrap_or(false) {
2031                    continue;
2032                }
2033
2034                let address = svr.server;
2035                let port = svr.server_port;
2036
2037                let addr = match address.parse::<Ipv4Addr>() {
2038                    Ok(v4) => ServerAddr::SocketAddr(SocketAddr::V4(SocketAddrV4::new(v4, port))),
2039                    Err(..) => match address.parse::<Ipv6Addr>() {
2040                        Ok(v6) => ServerAddr::SocketAddr(SocketAddr::V6(SocketAddrV6::new(v6, port, 0, 0))),
2041                        Err(..) => ServerAddr::DomainName(address, port),
2042                    },
2043                };
2044
2045                let method = match svr.method.parse::<CipherKind>() {
2046                    Ok(m) => m,
2047                    Err(..) => {
2048                        let err = Error::new(
2049                            ErrorKind::Invalid,
2050                            "unsupported method",
2051                            Some(format!("`{}` is not a supported method", svr.method)),
2052                        );
2053                        return Err(err);
2054                    }
2055                };
2056
2057                // Only "password" support getting from environment variable.
2058                let password = match svr.password {
2059                    Some(ref pwd) => read_variable_field_value(pwd),
2060                    None => {
2061                        if method.is_none() {
2062                            String::new().into()
2063                        } else {
2064                            let err = Error::new(
2065                                ErrorKind::MissingField,
2066                                "`password` is required",
2067                                Some(format!("`password` is required for method {method}")),
2068                            );
2069                            return Err(err);
2070                        }
2071                    }
2072                };
2073
2074                let mut nsvr = match ServerConfig::new(addr, password, method) {
2075                    Ok(svr) => svr,
2076                    Err(serr) => {
2077                        let err = Error::new(
2078                            ErrorKind::Malformed,
2079                            "server config create failed",
2080                            Some(format!("{}", serr)),
2081                        );
2082                        return Err(err);
2083                    }
2084                };
2085                nsvr.set_source(server_source);
2086
2087                // Extensible Identity Header, Users
2088                if let Some(users) = svr.users {
2089                    let mut user_manager = ServerUserManager::new();
2090
2091                    for user in users {
2092                        let user = match ServerUser::with_encoded_key(user.name, &user.password) {
2093                            Ok(u) => u,
2094                            Err(..) => {
2095                                let err = Error::new(
2096                                    ErrorKind::Malformed,
2097                                    "`users[].password` should be base64 encoded",
2098                                    None,
2099                                );
2100                                return Err(err);
2101                            }
2102                        };
2103
2104                        user_manager.add_user(user);
2105                    }
2106
2107                    nsvr.set_user_manager(user_manager);
2108                }
2109
2110                match svr.mode {
2111                    Some(mode) => match mode.parse::<Mode>() {
2112                        Ok(mode) => nsvr.set_mode(mode),
2113                        Err(..) => {
2114                            let err = Error::new(ErrorKind::Invalid, "invalid `mode`", None);
2115                            return Err(err);
2116                        }
2117                    },
2118                    None => {
2119                        // Server will derive mode from the global scope
2120                        if matches!(config_type, ConfigType::Server | ConfigType::Manager) {
2121                            nsvr.set_mode(global_mode);
2122                        }
2123                    }
2124                }
2125
2126                if let Some(p) = svr.plugin {
2127                    // SIP008 allows "plugin" to be an empty string
2128                    // Empty string implies "no plugin"
2129                    if !p.is_empty() {
2130                        let plugin = PluginConfig {
2131                            plugin: p,
2132                            plugin_opts: svr.plugin_opts,
2133                            plugin_args: svr.plugin_args.unwrap_or_default(),
2134                            plugin_mode: match svr.plugin_mode {
2135                                None => Mode::TcpOnly,
2136                                Some(ref mode) => match mode.parse::<Mode>() {
2137                                    Ok(m) => m,
2138                                    Err(..) => {
2139                                        let e = Error::new(
2140                                            ErrorKind::Malformed,
2141                                            "malformed `plugin_mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`",
2142                                            None,
2143                                        );
2144                                        return Err(e);
2145                                    }
2146                                },
2147                            },
2148                        };
2149                        nsvr.set_plugin(plugin);
2150                    }
2151                }
2152
2153                if let Some(timeout) = config.timeout.map(Duration::from_secs) {
2154                    nsvr.set_timeout(timeout);
2155                }
2156
2157                if let Some(remarks) = svr.remarks {
2158                    nsvr.set_remarks(remarks);
2159                }
2160
2161                if let Some(id) = svr.id {
2162                    nsvr.set_id(id);
2163                }
2164
2165                if svr.tcp_weight.is_some() || svr.udp_weight.is_some() {
2166                    let tcp_weight = svr.tcp_weight.unwrap_or(1.0);
2167                    if !(0.0..=1.0).contains(&tcp_weight) {
2168                        let err = Error::new(ErrorKind::Invalid, "invalid `tcp_weight`, must be in [0, 1]", None);
2169                        return Err(err);
2170                    }
2171                    let udp_weight = svr.udp_weight.unwrap_or(1.0);
2172                    if !(0.0..=1.0).contains(&udp_weight) {
2173                        let err = Error::new(ErrorKind::Invalid, "invalid `udp_weight`, must be in [0, 1]", None);
2174                        return Err(err);
2175                    }
2176                    let mut weight = ServerWeight::new();
2177                    weight.set_tcp_weight(tcp_weight);
2178                    weight.set_udp_weight(udp_weight);
2179                    nsvr.set_weight(weight);
2180                }
2181
2182                let mut server_instance = ServerInstanceConfig::with_server_config(nsvr);
2183
2184                if let Some(acl_path) = svr.acl {
2185                    let acl = match AccessControl::load_from_file(&acl_path) {
2186                        Ok(acl) => acl,
2187                        Err(err) => {
2188                            let err = Error::new(
2189                                ErrorKind::Invalid,
2190                                "acl loading failed",
2191                                Some(format!("file {acl_path}, error: {err}")),
2192                            );
2193                            return Err(err);
2194                        }
2195                    };
2196                    server_instance.acl = Some(acl);
2197                }
2198
2199                #[cfg(any(target_os = "linux", target_os = "android"))]
2200                if let Some(outbound_fwmark) = svr.outbound_fwmark {
2201                    server_instance.outbound_fwmark = Some(outbound_fwmark);
2202                }
2203
2204                #[cfg(target_os = "freebsd")]
2205                if let Some(outbound_user_cookie) = svr.outbound_user_cookie {
2206                    server_instance.outbound_user_cookie = Some(outbound_user_cookie);
2207                }
2208
2209                if let Some(outbound_bind_addr) = svr.outbound_bind_addr {
2210                    server_instance.outbound_bind_addr = Some(outbound_bind_addr);
2211                }
2212
2213                if let Some(ref outbound_bind_interface) = svr.outbound_bind_interface {
2214                    server_instance.outbound_bind_interface = Some(outbound_bind_interface.clone());
2215                }
2216
2217                if let Some(outbound_udp_allow_fragmentation) = svr.outbound_udp_allow_fragmentation {
2218                    server_instance.outbound_udp_allow_fragmentation = Some(outbound_udp_allow_fragmentation);
2219                }
2220
2221                nconfig.server.push(server_instance);
2222            }
2223        }
2224
2225        // Set timeout globally
2226        if let Some(timeout) = config.timeout {
2227            let timeout = Duration::from_secs(timeout);
2228            // Set as a default timeout
2229            for inst in &mut nconfig.server {
2230                let svr = &mut inst.config;
2231                if svr.timeout().is_none() {
2232                    svr.set_timeout(timeout);
2233                }
2234            }
2235        }
2236
2237        // Manager Address
2238        if let Some(ma) = config.manager_address {
2239            let manager = match config.manager_port {
2240                Some(port) => {
2241                    match ma.parse::<IpAddr>() {
2242                        Ok(ip) => ManagerAddr::from(SocketAddr::new(ip, port)),
2243                        Err(..) => {
2244                            // treated as domain
2245                            ManagerAddr::from((ma, port))
2246                        }
2247                    }
2248                }
2249                #[cfg(unix)]
2250                None => ManagerAddr::from(PathBuf::from(ma)),
2251                #[cfg(not(unix))]
2252                None => {
2253                    let e = Error::new(ErrorKind::MissingField, "missing `manager_port`", None);
2254                    return Err(e);
2255                }
2256            };
2257
2258            let mut manager_config = ManagerConfig::new(manager);
2259            manager_config.mode = global_mode;
2260
2261            if let Some(ref m) = config.method {
2262                match m.parse::<CipherKind>() {
2263                    Ok(method) => manager_config.method = Some(method),
2264                    Err(..) => {
2265                        let err = Error::new(
2266                            ErrorKind::Invalid,
2267                            "unsupported method",
2268                            Some(format!("`{m}` is not a supported method")),
2269                        );
2270                        return Err(err);
2271                    }
2272                }
2273            }
2274
2275            if let Some(p) = config.plugin {
2276                // SIP008 allows "plugin" to be an empty string
2277                // Empty string implies "no plugin"
2278                if !p.is_empty() {
2279                    manager_config.plugin = Some(PluginConfig {
2280                        plugin: p,
2281                        plugin_opts: config.plugin_opts,
2282                        plugin_args: config.plugin_args.unwrap_or_default(),
2283                        plugin_mode: match config.plugin_mode {
2284                            None => Mode::TcpOnly,
2285                            Some(ref mode) => match mode.parse::<Mode>() {
2286                                Ok(m) => m,
2287                                Err(..) => {
2288                                    let e = Error::new(
2289                                        ErrorKind::Malformed,
2290                                        "malformed `plugin_mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`",
2291                                        None,
2292                                    );
2293                                    return Err(e);
2294                                }
2295                            },
2296                        },
2297                    });
2298                }
2299            }
2300
2301            nconfig.manager = Some(manager_config);
2302        }
2303
2304        // DNS
2305        {
2306            match config.dns {
2307                Some(SSDnsConfig::Simple(ds)) => nconfig.set_dns_formatted(&ds)?,
2308                #[cfg(feature = "hickory-dns")]
2309                Some(SSDnsConfig::HickoryDns(c)) => nconfig.dns = DnsConfig::HickoryDns(c),
2310                None => nconfig.dns = DnsConfig::System,
2311            }
2312            nconfig.dns_cache_size = config.dns_cache_size;
2313        }
2314
2315        // TCP nodelay
2316        if let Some(b) = config.no_delay {
2317            nconfig.no_delay = b;
2318        }
2319
2320        // TCP fast open
2321        if let Some(b) = config.fast_open {
2322            nconfig.fast_open = b;
2323        }
2324
2325        // TCP Keep-Alive
2326        if let Some(d) = config.keep_alive {
2327            nconfig.keep_alive = Some(Duration::from_secs(d));
2328        }
2329
2330        // Multipath-TCP
2331        if let Some(b) = config.mptcp {
2332            nconfig.mptcp = b;
2333        }
2334
2335        // UDP
2336        nconfig.udp_timeout = config.udp_timeout.map(Duration::from_secs);
2337
2338        // Maximum associations to be kept simultaneously
2339        nconfig.udp_max_associations = config.udp_max_associations;
2340
2341        // MTU for UDP
2342        nconfig.udp_mtu = config.udp_mtu;
2343
2344        // RLIMIT_NOFILE
2345        #[cfg(all(unix, not(target_os = "android")))]
2346        {
2347            nconfig.nofile = config.nofile;
2348        }
2349
2350        // Uses IPv6 first
2351        if let Some(f) = config.ipv6_first {
2352            nconfig.ipv6_first = f;
2353        }
2354
2355        // IPV6_V6ONLY
2356        if let Some(o) = config.ipv6_only {
2357            nconfig.ipv6_only = o;
2358        }
2359
2360        // SO_MARK
2361        #[cfg(any(target_os = "linux", target_os = "android"))]
2362        if let Some(fwmark) = config.outbound_fwmark {
2363            nconfig.outbound_fwmark = Some(fwmark);
2364        }
2365
2366        // SO_USER_COOKIE
2367        #[cfg(target_os = "freebsd")]
2368        if let Some(user_cookie) = config.outbound_user_cookie {
2369            nconfig.outbound_user_cookie = Some(user_cookie);
2370        }
2371
2372        // Outbound bind() address
2373        if let Some(bind_addr) = config.outbound_bind_addr {
2374            match bind_addr.parse::<IpAddr>() {
2375                Ok(b) => nconfig.outbound_bind_addr = Some(b),
2376                Err(..) => {
2377                    let err = Error::new(ErrorKind::Invalid, "invalid outbound_bind_addr", None);
2378                    return Err(err);
2379                }
2380            }
2381        }
2382
2383        // Bind device / interface
2384        nconfig.outbound_bind_interface = config.outbound_bind_interface;
2385
2386        if let Some(b) = config.outbound_udp_allow_fragmentation {
2387            nconfig.outbound_udp_allow_fragmentation = b;
2388        }
2389
2390        // Security
2391        if let Some(sec) = config.security
2392            && let Some(replay_attack) = sec.replay_attack
2393                && let Some(policy) = replay_attack.policy {
2394                    match policy.parse::<ReplayAttackPolicy>() {
2395                        Ok(p) => nconfig.security.replay_attack.policy = p,
2396                        Err(..) => {
2397                            let err = Error::new(ErrorKind::Invalid, "invalid replay attack policy", None);
2398                            return Err(err);
2399                        }
2400                    }
2401                }
2402
2403        if let Some(balancer) = config.balancer {
2404            nconfig.balancer = BalancerConfig {
2405                max_server_rtt: balancer.max_server_rtt.map(Duration::from_secs),
2406                check_interval: balancer.check_interval.map(Duration::from_secs),
2407                check_best_interval: balancer.check_best_interval.map(Duration::from_secs),
2408            };
2409        }
2410
2411        if let Some(acl_path) = config.acl {
2412            let acl = match AccessControl::load_from_file(&acl_path) {
2413                Ok(acl) => acl,
2414                Err(err) => {
2415                    let err = Error::new(
2416                        ErrorKind::Invalid,
2417                        "acl loading failed",
2418                        Some(format!("file {acl_path}, error: {err}")),
2419                    );
2420                    return Err(err);
2421                }
2422            };
2423            nconfig.acl = Some(acl);
2424        }
2425
2426        #[cfg(feature = "local-online-config")]
2427        if let Some(online_config) = config.online_config {
2428            nconfig.online_config = Some(OnlineConfig {
2429                config_url: online_config.config_url,
2430                update_interval: online_config.update_interval.map(Duration::from_secs),
2431                allowed_plugins: online_config.allowed_plugins,
2432            });
2433        }
2434
2435        Ok(nconfig)
2436    }
2437
2438    /// Set DNS configuration in string format
2439    ///
2440    /// 1. `[(unix|tcp|udp)://]host[:port][,host[:port]]...`
2441    /// 2. Pre-defined. Like `google`, `cloudflare`
2442    pub fn set_dns_formatted(&mut self, dns: &str) -> Result<(), Error> {
2443        self.dns = match dns {
2444            "system" => DnsConfig::System,
2445
2446            #[cfg(feature = "hickory-dns")]
2447            "google" => DnsConfig::HickoryDns(ResolverConfig::google()),
2448            #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))]
2449            "google_tls" => DnsConfig::HickoryDns(ResolverConfig::google_tls()),
2450            #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))]
2451            "google_https" => DnsConfig::HickoryDns(ResolverConfig::google_https()),
2452            #[cfg(all(feature = "hickory-dns", feature = "dns-over-h3"))]
2453            "google_h3" => DnsConfig::HickoryDns(ResolverConfig::google_h3()),
2454
2455            #[cfg(feature = "hickory-dns")]
2456            "cloudflare" => DnsConfig::HickoryDns(ResolverConfig::cloudflare()),
2457            #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))]
2458            "cloudflare_tls" => DnsConfig::HickoryDns(ResolverConfig::cloudflare_tls()),
2459            #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))]
2460            "cloudflare_https" => DnsConfig::HickoryDns(ResolverConfig::cloudflare_https()),
2461
2462            #[cfg(feature = "hickory-dns")]
2463            "quad9" => DnsConfig::HickoryDns(ResolverConfig::quad9()),
2464            #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))]
2465            "quad9_tls" => DnsConfig::HickoryDns(ResolverConfig::quad9_tls()),
2466            #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))]
2467            "quad9_https" => DnsConfig::HickoryDns(ResolverConfig::quad9_https()),
2468
2469            nameservers => self.parse_dns_nameservers(nameservers)?,
2470        };
2471
2472        Ok(())
2473    }
2474
2475    #[cfg(any(feature = "hickory-dns", feature = "local-dns"))]
2476    fn parse_dns_nameservers(&mut self, nameservers: &str) -> Result<DnsConfig, Error> {
2477        use hickory_resolver::proto::xfer::Protocol;
2478
2479        #[cfg(all(unix, feature = "local-dns"))]
2480        if let Some(nameservers) = nameservers.strip_prefix("unix://") {
2481            // A special DNS server only for shadowsocks-android
2482            // It serves like a TCP DNS server but using unix domain sockets
2483
2484            return Ok(DnsConfig::LocalDns(NameServerAddr::UnixSocketAddr(PathBuf::from(
2485                nameservers,
2486            ))));
2487        }
2488
2489        enum DnsProtocol {
2490            Tcp,
2491            Udp,
2492            Both,
2493        }
2494
2495        impl DnsProtocol {
2496            fn enable_tcp(&self) -> bool {
2497                matches!(*self, Self::Tcp | Self::Both)
2498            }
2499
2500            fn enable_udp(&self) -> bool {
2501                matches!(*self, Self::Udp | Self::Both)
2502            }
2503        }
2504
2505        let mut protocol = DnsProtocol::Both;
2506
2507        let mut nameservers = nameservers;
2508        if nameservers.starts_with("tcp://") {
2509            protocol = DnsProtocol::Tcp;
2510            nameservers = &nameservers[6..];
2511        } else if nameservers.starts_with("udp://") {
2512            protocol = DnsProtocol::Udp;
2513            nameservers = &nameservers[6..];
2514        }
2515
2516        // If enables Trust-DNS, then it supports multiple nameservers
2517        //
2518        // Set ips directly
2519        // Similar to shadowsocks-libev's `ares_set_servers_ports_csv`
2520        //
2521        // ```
2522        // host[:port][,host[:port]]...
2523        // ```
2524        //
2525        // For example:
2526        //     `192.168.1.100,192.168.1.101,3.4.5.6`
2527        let mut c = ResolverConfig::new();
2528        for part in nameservers.split(',') {
2529            let socket_addr = if let Ok(socket_addr) = part.parse::<SocketAddr>() {
2530                socket_addr
2531            } else if let Ok(ipaddr) = part.parse::<IpAddr>() {
2532                SocketAddr::new(ipaddr, 53)
2533            } else {
2534                let e = Error::new(
2535                    ErrorKind::Invalid,
2536                    "invalid `dns` value, can only be [(tcp|udp)://]host[:port][,host[:port]]..., or unix:///path/to/dns, or predefined keys like \"google\", \"cloudflare\"",
2537                    None,
2538                );
2539                return Err(e);
2540            };
2541
2542            if protocol.enable_udp() {
2543                let ns_config = NameServerConfig::new(socket_addr, Protocol::Udp);
2544                c.add_name_server(ns_config);
2545            }
2546            if protocol.enable_tcp() {
2547                let ns_config = NameServerConfig::new(socket_addr, Protocol::Tcp);
2548                c.add_name_server(ns_config);
2549            }
2550        }
2551
2552        Ok(if c.name_servers().is_empty() {
2553            DnsConfig::System
2554        } else {
2555            DnsConfig::HickoryDns(c)
2556        })
2557    }
2558
2559    #[cfg(not(any(feature = "hickory-dns", feature = "local-dns")))]
2560    fn parse_dns_nameservers(&mut self, _nameservers: &str) -> Result<DnsConfig, Error> {
2561        Ok(DnsConfig::System)
2562    }
2563
2564    /// Load Config from a `str`
2565    pub fn load_from_str(s: &str, config_type: ConfigType) -> Result<Self, Error> {
2566        let c = json5::from_str::<SSConfig>(s)?;
2567        Self::load_from_ssconfig(c, config_type)
2568    }
2569
2570    /// Load Config from a JSON `str`
2571    pub fn load_from_json_str(s: &str, config_type: ConfigType) -> Result<Self, Error> {
2572        let c = serde_json::from_str::<SSConfig>(s)?;
2573        Self::load_from_ssconfig(c, config_type)
2574    }
2575
2576    /// Load Config from a File
2577    pub fn load_from_file<P: AsRef<Path>>(filename: P, config_type: ConfigType) -> Result<Self, Error> {
2578        let filename = filename.as_ref();
2579
2580        let mut reader = OpenOptions::new().read(true).open(filename)?;
2581        let mut content = String::new();
2582        reader.read_to_string(&mut content)?;
2583
2584        let mut config = Self::load_from_str(&content[..], config_type)?;
2585
2586        // Record the path of the configuration for auto-reloading
2587        config.config_path = Some(filename.to_owned());
2588
2589        Ok(config)
2590    }
2591
2592    /// Check if there are any plugin are enabled with servers
2593    pub fn has_server_plugins(&self) -> bool {
2594        for inst in &self.server {
2595            let server = &inst.config;
2596
2597            if server.plugin().is_some() {
2598                return true;
2599            }
2600        }
2601        false
2602    }
2603
2604    /// Check if all required fields are already set
2605    pub fn check_integrity(&self) -> Result<(), Error> {
2606        if self.config_type.is_local() {
2607            if self.local.is_empty() {
2608                let err = Error::new(
2609                    ErrorKind::MissingField,
2610                    "missing `locals` for client configuration",
2611                    None,
2612                );
2613                return Err(err);
2614            }
2615
2616            for local_config in &self.local {
2617                local_config.config.check_integrity()?;
2618            }
2619
2620            // Balancer related checks
2621            if let Some(rtt) = self.balancer.max_server_rtt
2622                && rtt.as_secs() == 0 {
2623                    let err = Error::new(ErrorKind::Invalid, "balancer.max_server_rtt must be > 0", None);
2624                    return Err(err);
2625                }
2626
2627            if let Some(intv) = self.balancer.check_interval
2628                && intv.as_secs() == 0 {
2629                    let err = Error::new(ErrorKind::Invalid, "balancer.check_interval must be > 0", None);
2630                    return Err(err);
2631                }
2632        }
2633
2634        if self.config_type.is_server() && self.server.is_empty() {
2635            let err = Error::new(
2636                ErrorKind::MissingField,
2637                "missing any valid servers in configuration",
2638                None,
2639            );
2640            return Err(err);
2641        }
2642
2643        #[cfg(feature = "local-online-config")]
2644        if self.config_type.is_online_config() && self.server.is_empty() {
2645            let err = Error::new(
2646                ErrorKind::MissingField,
2647                "missing any valid servers in configuration",
2648                None,
2649            );
2650            return Err(err);
2651        }
2652
2653        if self.config_type.is_manager() && self.manager.is_none() {
2654            let err = Error::new(
2655                ErrorKind::MissingField,
2656                "missing `manager_addr` and `manager_port` in configuration",
2657                None,
2658            );
2659            return Err(err);
2660        }
2661
2662        for inst in &self.server {
2663            let server = &inst.config;
2664
2665            // Plugin shouldn't be an empty string
2666            if let Some(plugin) = server.plugin()
2667                && plugin.plugin.trim().is_empty() {
2668                    let err = Error::new(ErrorKind::Malformed, "`plugin` shouldn't be an empty string", None);
2669                    return Err(err);
2670                }
2671
2672            // Server's domain name shouldn't be an empty string
2673            match server.addr() {
2674                ServerAddr::SocketAddr(sa) => {
2675                    if sa.port() == 0 {
2676                        let err = Error::new(ErrorKind::Malformed, "`server_port` shouldn't be 0", None);
2677                        return Err(err);
2678                    }
2679
2680                    if self.config_type.is_local() {
2681                        // Only server could bind to INADDR_ANY
2682                        let ip = sa.ip();
2683                        if ip.is_unspecified() {
2684                            let err = Error::new(
2685                                ErrorKind::Malformed,
2686                                "`server` shouldn't be an unspecified address (INADDR_ANY)",
2687                                None,
2688                            );
2689                            return Err(err);
2690                        }
2691                    }
2692
2693                    #[cfg(feature = "local-online-config")]
2694                    if self.config_type.is_online_config() {
2695                        // Only server could bind to INADDR_ANY
2696                        let ip = sa.ip();
2697                        if ip.is_unspecified() {
2698                            let err = Error::new(
2699                                ErrorKind::Malformed,
2700                                "`server` shouldn't be an unspecified address (INADDR_ANY)",
2701                                None,
2702                            );
2703                            return Err(err);
2704                        }
2705                    }
2706                }
2707                ServerAddr::DomainName(dn, port) => {
2708                    if dn.is_empty() || *port == 0 {
2709                        let err = Error::new(
2710                            ErrorKind::Malformed,
2711                            "`server` shouldn't be an empty string, `server_port` shouldn't be 0",
2712                            None,
2713                        );
2714                        return Err(err);
2715                    }
2716                }
2717            }
2718
2719            // Users' key must match key length
2720            if let Some(user_manager) = server.user_manager() {
2721                #[cfg(feature = "aead-cipher-2022")]
2722                if server.method().is_aead_2022() {
2723                    use shadowsocks::config::method_support_eih;
2724                    if user_manager.user_count() > 0 && !method_support_eih(server.method()) {
2725                        let err = Error::new(
2726                            ErrorKind::Invalid,
2727                            "server method doesn't support Extended Identity Header (EIH), remove `users`",
2728                            Some(format!("method {}", server.method())),
2729                        );
2730                        return Err(err);
2731                    }
2732                }
2733
2734                let key_len = server.method().key_len();
2735                for user in user_manager.users_iter() {
2736                    if user.key().len() != key_len {
2737                        let err = Error::new(
2738                            ErrorKind::Malformed,
2739                            "`users[].password` length must be exactly the same as method's key length",
2740                            None,
2741                        );
2742                        return Err(err);
2743                    }
2744                }
2745            }
2746        }
2747
2748        Ok(())
2749    }
2750}
2751
2752impl fmt::Display for Config {
2753    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2754        // Convert to json
2755
2756        let mut jconf = SSConfig::default();
2757
2758        // Locals
2759        if !self.local.is_empty() {
2760            if self.local.len() == 1 && self.local[0].config.is_basic() {
2761                let local_instance = &self.local[0];
2762                let local = &local_instance.config;
2763                if let Some(ref a) = local.addr {
2764                    jconf.local_address = Some(match a {
2765                        ServerAddr::SocketAddr(sa) => sa.ip().to_string(),
2766                        ServerAddr::DomainName(dm, ..) => dm.to_string(),
2767                    });
2768                    jconf.local_port = Some(match a {
2769                        ServerAddr::SocketAddr(sa) => sa.port(),
2770                        ServerAddr::DomainName(.., port) => *port,
2771                    });
2772                }
2773
2774                #[cfg(target_os = "macos")]
2775                {
2776                    jconf.launchd_tcp_socket_name.clone_from(&local.launchd_tcp_socket_name);
2777                    jconf.launchd_udp_socket_name.clone_from(&local.launchd_udp_socket_name);
2778                }
2779
2780                if local.protocol != ProtocolType::Socks {
2781                    jconf.protocol = Some(local.protocol.as_str().to_owned());
2782                }
2783
2784                // ACL
2785                if let Some(ref acl) = local_instance.acl {
2786                    jconf.acl = Some(acl.file_path().to_str().unwrap().to_owned());
2787                }
2788            } else {
2789                let mut jlocals = Vec::with_capacity(self.local.len());
2790                for local_instance in &self.local {
2791                    let local = &local_instance.config;
2792
2793                    let jlocal = SSLocalExtConfig {
2794                        local_address: local.addr.as_ref().map(|a| match a {
2795                            ServerAddr::SocketAddr(sa) => sa.ip().to_string(),
2796                            ServerAddr::DomainName(dm, ..) => dm.to_string(),
2797                        }),
2798                        local_port: local.addr.as_ref().map(|a| match a {
2799                            ServerAddr::SocketAddr(sa) => sa.port(),
2800                            ServerAddr::DomainName(.., port) => *port,
2801                        }),
2802                        disabled: None,
2803                        local_udp_address: local.udp_addr.as_ref().map(|udp_addr| match udp_addr {
2804                            ServerAddr::SocketAddr(sa) => sa.ip().to_string(),
2805                            ServerAddr::DomainName(dm, ..) => dm.to_string(),
2806                        }),
2807                        local_udp_port: local.udp_addr.as_ref().map(|udp_addr| match udp_addr {
2808                            ServerAddr::SocketAddr(sa) => sa.port(),
2809                            ServerAddr::DomainName(.., port) => *port,
2810                        }),
2811                        mode: Some(local.mode.to_string()),
2812                        protocol: match local.protocol {
2813                            ProtocolType::Socks => None,
2814                            #[allow(unreachable_patterns)]
2815                            p => Some(p.as_str().to_owned()),
2816                        },
2817                        #[cfg(target_os = "macos")]
2818                        launchd_tcp_socket_name: local.launchd_tcp_socket_name.clone(),
2819                        #[cfg(target_os = "macos")]
2820                        launchd_udp_socket_name: local.launchd_udp_socket_name.clone(),
2821                        #[cfg(feature = "local-redir")]
2822                        tcp_redir: if local.tcp_redir != RedirType::tcp_default() {
2823                            Some(local.tcp_redir.to_string())
2824                        } else {
2825                            None
2826                        },
2827                        #[cfg(feature = "local-redir")]
2828                        udp_redir: if local.udp_redir != RedirType::udp_default() {
2829                            Some(local.udp_redir.to_string())
2830                        } else {
2831                            None
2832                        },
2833                        #[cfg(feature = "local-tunnel")]
2834                        forward_address: match local.forward_addr {
2835                            None => None,
2836                            Some(ref forward_addr) => match forward_addr {
2837                                Address::SocketAddress(sa) => Some(sa.ip().to_string()),
2838                                Address::DomainNameAddress(dm, ..) => Some(dm.to_string()),
2839                            },
2840                        },
2841                        #[cfg(feature = "local-tunnel")]
2842                        forward_port: match local.forward_addr {
2843                            None => None,
2844                            Some(ref forward_addr) => match forward_addr {
2845                                Address::SocketAddress(sa) => Some(sa.port()),
2846                                Address::DomainNameAddress(.., port) => Some(*port),
2847                            },
2848                        },
2849                        #[cfg(feature = "local-dns")]
2850                        local_dns_address: match local.local_dns_addr {
2851                            None => None,
2852                            Some(ref local_dns_addr) => match local_dns_addr {
2853                                NameServerAddr::SocketAddr(sa) => Some(sa.ip().to_string()),
2854                                #[cfg(unix)]
2855                                NameServerAddr::UnixSocketAddr(path) => {
2856                                    Some(path.to_str().expect("path is not utf-8").to_owned())
2857                                }
2858                            },
2859                        },
2860                        #[cfg(feature = "local-dns")]
2861                        local_dns_port: match local.local_dns_addr {
2862                            None => None,
2863                            Some(ref local_dns_addr) => match local_dns_addr {
2864                                NameServerAddr::SocketAddr(sa) => Some(sa.port()),
2865                                #[cfg(unix)]
2866                                NameServerAddr::UnixSocketAddr(..) => None,
2867                            },
2868                        },
2869                        #[cfg(feature = "local-dns")]
2870                        remote_dns_address: match local.remote_dns_addr {
2871                            None => None,
2872                            Some(ref remote_dns_addr) => match remote_dns_addr {
2873                                Address::SocketAddress(sa) => Some(sa.ip().to_string()),
2874                                Address::DomainNameAddress(dm, ..) => Some(dm.to_string()),
2875                            },
2876                        },
2877                        #[cfg(feature = "local-dns")]
2878                        remote_dns_port: match local.remote_dns_addr {
2879                            None => None,
2880                            Some(ref remote_dns_addr) => match remote_dns_addr {
2881                                Address::SocketAddress(sa) => Some(sa.port()),
2882                                Address::DomainNameAddress(.., port) => Some(*port),
2883                            },
2884                        },
2885                        #[cfg(feature = "local-dns")]
2886                        client_cache_size: local.client_cache_size,
2887                        #[cfg(feature = "local-tun")]
2888                        tun_interface_name: local.tun_interface_name.clone(),
2889                        #[cfg(feature = "local-tun")]
2890                        tun_interface_address: local.tun_interface_address.as_ref().map(ToString::to_string),
2891                        #[cfg(feature = "local-tun")]
2892                        tun_interface_destination: local.tun_interface_destination.as_ref().map(ToString::to_string),
2893                        #[cfg(all(feature = "local-tun", unix))]
2894                        tun_device_fd_from_path: local
2895                            .tun_device_fd_from_path
2896                            .as_ref()
2897                            .map(|p| p.to_str().expect("tun_device_fd_from_path is not utf-8").to_owned()),
2898
2899                        #[cfg(feature = "local")]
2900                        socks5_auth_config_path: None,
2901
2902                        #[cfg(feature = "local-fake-dns")]
2903                        fake_dns_record_expire_duration: local.fake_dns_record_expire_duration.map(|d| d.as_secs()),
2904                        #[cfg(feature = "local-fake-dns")]
2905                        fake_dns_ipv4_network: local.fake_dns_ipv4_network.map(|n| n.to_string()),
2906                        #[cfg(feature = "local-fake-dns")]
2907                        fake_dns_ipv6_network: local.fake_dns_ipv6_network.map(|n| n.to_string()),
2908                        #[cfg(feature = "local-fake-dns")]
2909                        fake_dns_database_path: local
2910                            .fake_dns_database_path
2911                            .as_ref()
2912                            .and_then(|n| n.to_str().map(ToOwned::to_owned)),
2913
2914                        acl: local_instance
2915                            .acl
2916                            .as_ref()
2917                            .and_then(|a| a.file_path().to_str().map(ToOwned::to_owned)),
2918                    };
2919                    jlocals.push(jlocal);
2920                }
2921                jconf.locals = Some(jlocals);
2922            }
2923        }
2924
2925        // Servers
2926        match self.server.len() {
2927            0 => {}
2928            // For 1 server, uses standard configure format
2929            1 if self.server[0].config.is_basic() => {
2930                let inst = &self.server[0];
2931                let svr = &inst.config;
2932
2933                jconf.server = Some(match *svr.addr() {
2934                    ServerAddr::SocketAddr(ref sa) => sa.ip().to_string(),
2935                    ServerAddr::DomainName(ref dm, ..) => dm.to_string(),
2936                });
2937                jconf.server_port = Some(match *svr.addr() {
2938                    ServerAddr::SocketAddr(ref sa) => sa.port(),
2939                    ServerAddr::DomainName(.., port) => port,
2940                });
2941                jconf.method = Some(svr.method().to_string());
2942                jconf.password = if svr.method().is_none() {
2943                    None
2944                } else {
2945                    Some(svr.password().to_string())
2946                };
2947                jconf.plugin = svr.plugin().map(|p| p.plugin.to_string());
2948                jconf.plugin_opts = svr.plugin().and_then(|p| p.plugin_opts.clone());
2949                jconf.plugin_args = svr.plugin().and_then(|p| {
2950                    if p.plugin_args.is_empty() {
2951                        None
2952                    } else {
2953                        Some(p.plugin_args.clone())
2954                    }
2955                });
2956                jconf.plugin_mode = match svr.plugin() {
2957                    None => None,
2958                    Some(p) => match p.plugin_mode {
2959                        Mode::TcpOnly => None,
2960                        _ => Some(p.plugin_mode.to_string()),
2961                    },
2962                };
2963                jconf.timeout = svr.timeout().map(|t| t.as_secs());
2964                jconf.mode = Some(svr.mode().to_string());
2965
2966                if let Some(ref acl) = inst.acl {
2967                    jconf.acl = Some(acl.file_path().to_str().unwrap().to_owned());
2968                }
2969            }
2970            // For >1 servers, uses extended multiple server format
2971            _ => {
2972                let mut vsvr = Vec::new();
2973
2974                for inst in &self.server {
2975                    let svr = &inst.config;
2976
2977                    vsvr.push(SSServerExtConfig {
2978                        server: match *svr.addr() {
2979                            ServerAddr::SocketAddr(ref sa) => sa.ip().to_string(),
2980                            ServerAddr::DomainName(ref dm, ..) => dm.to_string(),
2981                        },
2982                        server_port: match *svr.addr() {
2983                            ServerAddr::SocketAddr(ref sa) => sa.port(),
2984                            ServerAddr::DomainName(.., port) => port,
2985                        },
2986                        password: if svr.method().is_none() {
2987                            None
2988                        } else {
2989                            Some(svr.password().to_string())
2990                        },
2991                        method: svr.method().to_string(),
2992                        users: svr.user_manager().map(|m| {
2993                            let mut vu = Vec::new();
2994                            for u in m.users_iter() {
2995                                vu.push(SSServerUserConfig {
2996                                    name: u.name().to_owned(),
2997                                    password: u.encoded_key(),
2998                                });
2999                            }
3000                            vu
3001                        }),
3002                        disabled: None,
3003                        plugin: svr.plugin().map(|p| p.plugin.to_string()),
3004                        plugin_opts: svr.plugin().and_then(|p| p.plugin_opts.clone()),
3005                        plugin_args: svr.plugin().and_then(|p| {
3006                            if p.plugin_args.is_empty() {
3007                                None
3008                            } else {
3009                                Some(p.plugin_args.clone())
3010                            }
3011                        }),
3012                        plugin_mode: match svr.plugin() {
3013                            None => None,
3014                            Some(p) => match p.plugin_mode {
3015                                Mode::TcpOnly => None,
3016                                _ => Some(p.plugin_mode.to_string()),
3017                            },
3018                        },
3019                        timeout: svr.timeout().map(|t| t.as_secs()),
3020                        remarks: svr.remarks().map(ToOwned::to_owned),
3021                        id: svr.id().map(ToOwned::to_owned),
3022                        mode: Some(svr.mode().to_string()),
3023                        tcp_weight: if (svr.weight().tcp_weight() - 1.0).abs() > f32::EPSILON {
3024                            Some(svr.weight().tcp_weight())
3025                        } else {
3026                            None
3027                        },
3028                        udp_weight: if (svr.weight().udp_weight() - 1.0).abs() > f32::EPSILON {
3029                            Some(svr.weight().udp_weight())
3030                        } else {
3031                            None
3032                        },
3033                        acl: inst
3034                            .acl
3035                            .as_ref()
3036                            .and_then(|a| a.file_path().to_str().map(ToOwned::to_owned)),
3037                        #[cfg(any(target_os = "linux", target_os = "android"))]
3038                        outbound_fwmark: inst.outbound_fwmark,
3039                        #[cfg(target_os = "freebsd")]
3040                        outbound_user_cookie: inst.outbound_user_cookie,
3041                        outbound_bind_addr: inst.outbound_bind_addr,
3042                        outbound_bind_interface: inst.outbound_bind_interface.clone(),
3043                        outbound_udp_allow_fragmentation: inst.outbound_udp_allow_fragmentation,
3044                    });
3045                }
3046
3047                jconf.servers = Some(vsvr);
3048            }
3049        }
3050
3051        if let Some(ref m) = self.manager {
3052            jconf.manager_address = Some(match m.addr {
3053                ManagerAddr::SocketAddr(ref saddr) => saddr.ip().to_string(),
3054                ManagerAddr::DomainName(ref dname, ..) => dname.clone(),
3055                #[cfg(unix)]
3056                ManagerAddr::UnixSocketAddr(ref path) => path.display().to_string(),
3057            });
3058
3059            jconf.manager_port = match m.addr {
3060                ManagerAddr::SocketAddr(ref saddr) => Some(saddr.port()),
3061                ManagerAddr::DomainName(.., port) => Some(port),
3062                #[cfg(unix)]
3063                ManagerAddr::UnixSocketAddr(..) => None,
3064            };
3065
3066            if jconf.mode.is_none() {
3067                jconf.mode = Some(m.mode.to_string());
3068            }
3069
3070            if jconf.method.is_none()
3071                && let Some(ref m) = m.method {
3072                    jconf.method = Some(m.to_string());
3073                }
3074
3075            if jconf.plugin.is_none()
3076                && let Some(ref p) = m.plugin {
3077                    jconf.plugin = Some(p.plugin.clone());
3078                    if let Some(ref o) = p.plugin_opts {
3079                        jconf.plugin_opts = Some(o.clone());
3080                    }
3081                    if !p.plugin_args.is_empty() {
3082                        jconf.plugin_args = Some(p.plugin_args.clone());
3083                    }
3084                }
3085        }
3086
3087        if self.no_delay {
3088            jconf.no_delay = Some(self.no_delay);
3089        }
3090
3091        if self.fast_open {
3092            jconf.fast_open = Some(self.fast_open);
3093        }
3094
3095        if let Some(keepalive) = self.keep_alive {
3096            jconf.keep_alive = Some(keepalive.as_secs());
3097        }
3098
3099        if self.mptcp {
3100            jconf.mptcp = Some(self.mptcp);
3101        }
3102
3103        match self.dns {
3104            DnsConfig::System => {}
3105            #[cfg(feature = "hickory-dns")]
3106            DnsConfig::HickoryDns(ref dns) => {
3107                jconf.dns = Some(SSDnsConfig::HickoryDns(dns.clone()));
3108            }
3109            #[cfg(feature = "local-dns")]
3110            DnsConfig::LocalDns(ref ns) => {
3111                jconf.dns = Some(SSDnsConfig::Simple(ns.to_string()));
3112            }
3113        }
3114
3115        jconf.udp_timeout = self.udp_timeout.map(|t| t.as_secs());
3116
3117        jconf.udp_max_associations = self.udp_max_associations;
3118
3119        jconf.udp_mtu = self.udp_mtu;
3120
3121        #[cfg(all(unix, not(target_os = "android")))]
3122        {
3123            jconf.nofile = self.nofile;
3124        }
3125
3126        if self.ipv6_first {
3127            jconf.ipv6_first = Some(self.ipv6_first);
3128        }
3129
3130        if self.ipv6_only {
3131            jconf.ipv6_only = Some(self.ipv6_only);
3132        }
3133
3134        #[cfg(any(target_os = "linux", target_os = "android"))]
3135        {
3136            jconf.outbound_fwmark = self.outbound_fwmark;
3137        }
3138
3139        #[cfg(target_os = "freebsd")]
3140        {
3141            jconf.outbound_user_cookie = self.outbound_user_cookie;
3142        }
3143
3144        jconf.outbound_bind_addr = self.outbound_bind_addr.map(|i| i.to_string());
3145        jconf.outbound_bind_interface.clone_from(&self.outbound_bind_interface);
3146        jconf.outbound_udp_allow_fragmentation = Some(self.outbound_udp_allow_fragmentation);
3147
3148        // Security
3149        if self.security.replay_attack.policy != ReplayAttackPolicy::default() {
3150            jconf.security = Some(SSSecurityConfig {
3151                replay_attack: Some(SSSecurityReplayAttackConfig {
3152                    policy: Some(self.security.replay_attack.policy.to_string()),
3153                }),
3154            });
3155        }
3156
3157        // Balancer
3158        if self.balancer.max_server_rtt.is_some() || self.balancer.check_interval.is_some() {
3159            jconf.balancer = Some(SSBalancerConfig {
3160                max_server_rtt: self.balancer.max_server_rtt.as_ref().map(Duration::as_secs),
3161                check_interval: self.balancer.check_interval.as_ref().map(Duration::as_secs),
3162                check_best_interval: self.balancer.check_best_interval.as_ref().map(Duration::as_secs),
3163            });
3164        }
3165
3166        // ACL
3167        if let Some(ref acl) = self.acl {
3168            jconf.acl = Some(acl.file_path().to_str().unwrap().to_owned());
3169        }
3170
3171        // OnlineConfig
3172        #[cfg(feature = "local-online-config")]
3173        if let Some(ref online_config) = self.online_config {
3174            jconf.online_config = Some(SSOnlineConfig {
3175                config_url: online_config.config_url.clone(),
3176                update_interval: online_config.update_interval.as_ref().map(Duration::as_secs),
3177                allowed_plugins: online_config.allowed_plugins.clone(),
3178            });
3179        }
3180
3181        write!(f, "{}", json5::to_string(&jconf).unwrap())
3182    }
3183}
3184
3185/// Parse variable value if it is an environment variable
3186///
3187/// If value is in format `${VAR_NAME}` then it will try to read from `VAR_NAME` environment variable.
3188/// It will return the original value if fails to read `${VAR_NAME}`.
3189pub fn read_variable_field_value(value: &str) -> Cow<'_, str> {
3190    if let Some(left_over) = value.strip_prefix("${")
3191        && let Some(var_name) = left_over.strip_suffix('}') {
3192            match env::var(var_name) {
3193                Ok(value) => return value.into(),
3194                Err(err) => {
3195                    warn!(
3196                        "couldn't read password from environment variable {}, error: {}",
3197                        var_name, err
3198                    );
3199                }
3200            }
3201        }
3202
3203    value.into()
3204}