mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-02-09 01:59:16 +08:00
default configuration file (config.json) for Windows, Linux, macOS
- $XDG_CONFIG_PATH/shadowsocks-rust/config.json
- $HOME/.config/shadowsocks-rust/config.json
- {FOLDERID_RoamingAppData}\shadowsocks\shadowsocks-rust\config\config.json
- $HOME/Library/Application Support/org.shadowsocks.shadowsocks-rust/config.json
fixes #688
This commit is contained in:
58
Cargo.lock
generated
58
Cargo.lock
generated
@@ -299,6 +299,35 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "4.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.8"
|
||||
@@ -1291,6 +1320,16 @@ dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall 0.2.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
@@ -1524,9 +1563,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.71"
|
||||
version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063bf466a64011ac24040a49009724ee60a57da1b437617ceb32e53ad61bfb19"
|
||||
checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -1624,6 +1663,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"clap",
|
||||
"daemonize",
|
||||
"directories",
|
||||
"env_logger",
|
||||
"exitcode",
|
||||
"futures",
|
||||
@@ -1638,6 +1678,7 @@ dependencies = [
|
||||
"snmalloc-rs",
|
||||
"tcmalloc",
|
||||
"tokio",
|
||||
"xdg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1774,9 +1815,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.81"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
|
||||
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2438,6 +2479,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xdg"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a23fe958c70412687039c86f578938b4a0bb50ec788e96bce4d6ab00ddd5803"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
|
||||
@@ -128,6 +128,8 @@ cfg-if = "1"
|
||||
qrcode = { version = "0.12", default-features = false }
|
||||
exitcode = "1"
|
||||
build-time = "0.1"
|
||||
directories = "4.0"
|
||||
xdg = "2.4"
|
||||
|
||||
futures = "0.3"
|
||||
tokio = { version = "1", features = ["rt", "signal"] }
|
||||
|
||||
@@ -49,6 +49,8 @@ Related Projects:
|
||||
|
||||
* `local-dns` - Allow using dns protocol for `sslocal`, serves as a DNS server proxying queries to local or remote DNS servers by ACL rules
|
||||
|
||||
* `local-tun` - [TUN](https://en.wikipedia.org/wiki/TUN/TAP) interface support for `sslocal`
|
||||
|
||||
* `stream-cipher` - Enable deprecated stream ciphers. WARN: stream ciphers are UNSAFE!
|
||||
|
||||
* `aead-cipher-extra` - Enable non-standard AEAD ciphers
|
||||
|
||||
41
bin/common/config.rs
Normal file
41
bin/common/config.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use directories::ProjectDirs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Default configuration file path
|
||||
pub fn get_default_config_path() -> Option<PathBuf> {
|
||||
// System standard directories
|
||||
if let Some(project_dirs) = ProjectDirs::from("org", "shadowsocks", "shadowsocks-rust") {
|
||||
// Linux: $XDG_CONFIG_HOME/shadowsocks-rust/config.json
|
||||
// $HOME/.config/shadowsocks-rust/config.json
|
||||
// macOS: $HOME/Library/Application Support/org.shadowsocks.shadowsocks-rust/config.json
|
||||
// Windows: {FOLDERID_RoamingAppData}/shadowsocks/shadowsocks-rust/config/config.json
|
||||
|
||||
let mut config_path = project_dirs.config_dir().to_path_buf();
|
||||
config_path.push("config.json");
|
||||
|
||||
if config_path.exists() {
|
||||
return Some(config_path);
|
||||
}
|
||||
}
|
||||
|
||||
// UNIX systems, XDG Base Directory
|
||||
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
#[cfg(unix)]
|
||||
if let Ok(base_directories) = xdg::BaseDirectories::with_prefix("shadowsocks-rust") {
|
||||
// $XDG_CONFIG_HOME/shadowsocks-rust/config.json
|
||||
// for dir in $XDG_CONFIG_DIRS; $dir/shadowsocks-rust/config.json
|
||||
if let Some(config_path) = base_directories.find_config_file("config.json") {
|
||||
return Some(config_path);
|
||||
}
|
||||
}
|
||||
|
||||
// UNIX global configuration file
|
||||
if cfg!(unix) {
|
||||
let global_config_path = Path::new("/etc/shadowsocks-rust/config.json");
|
||||
if global_config_path.exists() {
|
||||
return Some(global_config_path.to_path_buf());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
@@ -7,6 +7,7 @@ pub mod daemonize;
|
||||
pub mod logging;
|
||||
pub mod monitor;
|
||||
pub mod validator;
|
||||
pub mod config;
|
||||
|
||||
pub const EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY: i32 = exitcode::SOFTWARE;
|
||||
pub const EXIT_CODE_SERVER_ABORTED: i32 = exitcode::SOFTWARE;
|
||||
|
||||
@@ -42,7 +42,7 @@ fn main() {
|
||||
(version: VERSION)
|
||||
(about: "A fast tunnel proxy that helps you bypass firewalls.")
|
||||
|
||||
(@arg CONFIG: -c --config +takes_value required_unless("SERVER_CONFIG") "Shadowsocks configuration file (https://shadowsocks.org/en/config/quick-guide.html)")
|
||||
(@arg CONFIG: -c --config +takes_value "Shadowsocks configuration file (https://shadowsocks.org/en/config/quick-guide.html)")
|
||||
|
||||
(@arg LOCAL_ADDR: -b --("local-addr") +takes_value {validator::validate_server_addr} "Local address, listen only to this address if specified")
|
||||
(@arg UDP_ONLY: -u conflicts_with[TCP_AND_UDP] requires[LOCAL_ADDR] "Server mode UDP_ONLY")
|
||||
@@ -207,11 +207,19 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let mut config = match matches.value_of("CONFIG") {
|
||||
Some(cpath) => match Config::load_from_file(cpath, ConfigType::Local) {
|
||||
let config_path_opt = matches.value_of("CONFIG").map(|c| PathBuf::from(c)).or_else(|| {
|
||||
if !matches.is_present("SERVER_CONFIG") {
|
||||
common::config::get_default_config_path()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let mut config = match config_path_opt {
|
||||
Some(cpath) => match Config::load_from_file(&cpath, ConfigType::Local) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
eprintln!("loading config \"{}\", {}", cpath, err);
|
||||
eprintln!("loading config \"{}\", {}", cpath.display(), err);
|
||||
process::exit(common::EXIT_CODE_LOAD_CONFIG_FAILURE);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//! *It should be notice that the extended configuration file is not suitable for the server
|
||||
//! side.*
|
||||
|
||||
use std::{net::IpAddr, process, time::Duration};
|
||||
use std::{net::IpAddr, path::PathBuf, process, time::Duration};
|
||||
|
||||
use clap::{clap_app, Arg};
|
||||
use futures::future::{self, Either};
|
||||
@@ -44,7 +44,7 @@ fn main() {
|
||||
(@arg UDP_ONLY: -u conflicts_with[TCP_AND_UDP] "Server mode UDP_ONLY")
|
||||
(@arg TCP_AND_UDP: -U conflicts_with[UDP_ONLY] "Server mode TCP_AND_UDP")
|
||||
|
||||
(@arg CONFIG: -c --config +takes_value required_unless("MANAGER_ADDR")
|
||||
(@arg CONFIG: -c --config +takes_value
|
||||
"Shadowsocks configuration file (https://shadowsocks.org/en/config/quick-guide.html), \
|
||||
the only required fields are \"manager_address\" and \"manager_port\". \
|
||||
Servers defined will be created when process is started.")
|
||||
@@ -136,11 +136,19 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let mut config = match matches.value_of("CONFIG") {
|
||||
Some(cpath) => match Config::load_from_file(cpath, ConfigType::Manager) {
|
||||
let config_path_opt = matches.value_of("CONFIG").map(|c| PathBuf::from(c)).or_else(|| {
|
||||
if !matches.is_present("MANAGER_ADDR") {
|
||||
common::config::get_default_config_path()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let mut config = match config_path_opt {
|
||||
Some(cpath) => match Config::load_from_file(&cpath, ConfigType::Manager) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
eprintln!("loading config \"{}\", {}", cpath, err);
|
||||
eprintln!("loading config \"{}\", {}", cpath.display(), err);
|
||||
process::exit(common::EXIT_CODE_LOAD_CONFIG_FAILURE);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//! *It should be notice that the extended configuration file is not suitable for the server
|
||||
//! side.*
|
||||
|
||||
use std::{net::IpAddr, process, time::Duration};
|
||||
use std::{net::IpAddr, path::PathBuf, process, time::Duration};
|
||||
|
||||
use clap::{clap_app, Arg};
|
||||
use futures::future::{self, Either};
|
||||
@@ -41,7 +41,7 @@ fn main() {
|
||||
(version: VERSION)
|
||||
(about: "A fast tunnel proxy that helps you bypass firewalls.")
|
||||
|
||||
(@arg CONFIG: -c --config +takes_value required_unless("SERVER_ADDR") "Shadowsocks configuration file (https://shadowsocks.org/en/config/quick-guide.html)")
|
||||
(@arg CONFIG: -c --config +takes_value "Shadowsocks configuration file (https://shadowsocks.org/en/config/quick-guide.html)")
|
||||
|
||||
(@arg OUTBOUND_BIND_ADDR: -b --("outbound-bind-addr") +takes_value alias("bind-addr") {validator::validate_ip_addr} "Bind address, outbound socket will bind this address")
|
||||
(@arg OUTBOUND_BIND_INTERFACE: --("outbound-bind-interface") +takes_value "Set SO_BINDTODEVICE / IP_BOUND_IF / IP_UNICAST_IF option for outbound socket")
|
||||
@@ -131,11 +131,19 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let mut config = match matches.value_of("CONFIG") {
|
||||
Some(cpath) => match Config::load_from_file(cpath, ConfigType::Server) {
|
||||
let config_path_opt = matches.value_of("CONFIG").map(|c| PathBuf::from(c)).or_else(|| {
|
||||
if !matches.is_present("SERVER_ADDR") {
|
||||
common::config::get_default_config_path()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let mut config = match config_path_opt {
|
||||
Some(cpath) => match Config::load_from_file(&cpath, ConfigType::Server) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
eprintln!("loading config \"{}\", {}", cpath, err);
|
||||
eprintln!("loading config \"{}\", {}", cpath.display(), err);
|
||||
process::exit(common::EXIT_CODE_LOAD_CONFIG_FAILURE);
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user