support multiple local servers in configuration file

ref #452

- support `locals` in configuration file, running multiple local server
  instance simultaneously
- support `unix://` in `dns` configuration

BREAKING CHANGE:

- `sslocal`'s `--dns-addr` is now only available in Android
- shadowsocks-service's `Config` struct have lots of changes
This commit is contained in:
zonyitoo
2021-03-13 12:56:33 +08:00
committed by ty
parent b632d35689
commit 6bebb6c6c0
33 changed files with 1111 additions and 703 deletions

6
Cargo.lock generated
View File

@@ -1471,7 +1471,7 @@ dependencies = [
[[package]]
name = "shadowsocks"
version = "1.9.2"
version = "1.10.0"
dependencies = [
"arc-swap 1.2.0",
"async-trait",
@@ -1515,7 +1515,7 @@ dependencies = [
[[package]]
name = "shadowsocks-rust"
version = "1.9.2"
version = "1.10.0"
dependencies = [
"byte_string",
"byteorder",
@@ -1536,7 +1536,7 @@ dependencies = [
[[package]]
name = "shadowsocks-service"
version = "1.9.2"
version = "1.10.0"
dependencies = [
"async-trait",
"byte_string",

View File

@@ -1,6 +1,6 @@
[package]
name = "shadowsocks-rust"
version = "1.9.2"
version = "1.10.0"
authors = ["Shadowsocks Contributors"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/shadowsocks/shadowsocks-rust"
@@ -122,7 +122,7 @@ mimalloc = { version = "0.1", optional = true }
tcmalloc = { version = "0.3", optional = true }
jemallocator = { version = "0.3", optional = true }
shadowsocks-service = { version = "1.9.2", path = "./crates/shadowsocks-service" }
shadowsocks-service = { version = "1.10.0", path = "./crates/shadowsocks-service" }
[target.'cfg(unix)'.dependencies]
daemonize = "0.4"

View File

@@ -2,7 +2,7 @@
#![allow(dead_code)]
use std::net::SocketAddr;
use std::net::{IpAddr, SocketAddr};
#[cfg(feature = "local-dns")]
use shadowsocks_service::local::dns::NameServerAddr;
@@ -24,6 +24,7 @@ validate_type!(
ServerAddr,
"should be either ip:port or domain:port"
);
validate_type!(validate_ip_addr, IpAddr, "should be a valid IPv4 or IPv6 address");
validate_type!(validate_socket_addr, SocketAddr, "should be ip:port");
validate_type!(validate_address, Address, "should be either ip:port or domain:port");
validate_type!(

View File

@@ -17,7 +17,7 @@ use shadowsocks_service::config::RedirType;
use shadowsocks_service::shadowsocks::relay::socks5::Address;
use shadowsocks_service::{
acl::AccessControl,
config::{Config, ConfigType, Mode, ProtocolType},
config::{Config, ConfigType, LocalConfig, Mode, ProtocolType},
run_local,
shadowsocks::{
config::{ServerAddr, ServerConfig},
@@ -151,8 +151,15 @@ fn main() {
app = clap_app!(@app (app)
(@arg LOCAL_DNS_ADDR: --("local-dns-addr") +takes_value required_if("PROTOCOL", "dns") {validator::validate_name_server_addr} "Specify the address of local DNS server, send queries directly")
(@arg REMOTE_DNS_ADDR: --("remote-dns-addr") +takes_value required_if("PROTOCOL", "dns") {validator::validate_address} "Specify the address of remote DNS server, send queries through shadowsocks' tunnel")
(@arg DNS_LOCAL_ADDR: --("dns-addr") +takes_value requires_all(&["REMOTE_DNS_ADDR"]) {validator::validate_server_addr} "DNS address, listen to this address if specified")
);
#[cfg(target_os = "android")]
{
app = clap_app!(@app (app)
(@arg DNS_LOCAL_ADDR: --("dns-addr") +takes_value requires_all(&["REMOTE_DNS_ADDR"]) {validator::validate_server_addr} "DNS address, listen to this address if specified")
);
}
}
#[cfg(unix)]
@@ -193,22 +200,6 @@ fn main() {
None => Config::new(ConfigType::Local),
};
let protocol = match matches.value_of("PROTOCOL") {
Some("socks") => ProtocolType::Socks,
#[cfg(feature = "local-http")]
Some("http") => ProtocolType::Http,
#[cfg(feature = "local-tunnel")]
Some("tunnel") => ProtocolType::Tunnel,
#[cfg(feature = "local-redir")]
Some("redir") => ProtocolType::Redir,
#[cfg(feature = "local-dns")]
Some("dns") => ProtocolType::Dns,
Some(p) => panic!("not supported `protocol` \"{}\"", p),
None => ProtocolType::Socks,
};
config.local_protocol = protocol;
if let Some(svr_addr) = matches.value_of("SERVER_ADDR") {
let password = matches.value_of("PASSWORD").expect("password");
let method = matches
@@ -253,26 +244,6 @@ fn main() {
}
}
#[cfg(feature = "local-dns")]
{
use shadowsocks_service::local::dns::NameServerAddr;
if let Some(local_dns_addr) = matches.value_of("LOCAL_DNS_ADDR") {
let addr = local_dns_addr.parse::<NameServerAddr>().expect("local dns address");
config.local_dns_addr = Some(addr);
}
if let Some(remote_dns_addr) = matches.value_of("REMOTE_DNS_ADDR") {
let addr = remote_dns_addr.parse::<Address>().expect("remote dns address");
config.remote_dns_addr = Some(addr);
}
if let Some(dns_relay_addr) = matches.value_of("DNS_LOCAL_ADDR") {
let addr = dns_relay_addr.parse::<ServerAddr>().expect("dns relay address");
config.dns_bind_addr = Some(addr);
}
}
#[cfg(target_os = "android")]
if matches.is_present("VPN_MODE") {
// A socket `protect_path` in CWD
@@ -282,7 +253,78 @@ fn main() {
if let Some(local_addr) = matches.value_of("LOCAL_ADDR") {
let local_addr = local_addr.parse::<ServerAddr>().expect("local bind addr");
config.local_addr = Some(local_addr);
let protocol = match matches.value_of("PROTOCOL") {
Some("socks") => ProtocolType::Socks,
#[cfg(feature = "local-http")]
Some("http") => ProtocolType::Http,
#[cfg(feature = "local-tunnel")]
Some("tunnel") => ProtocolType::Tunnel,
#[cfg(feature = "local-redir")]
Some("redir") => ProtocolType::Redir,
#[cfg(feature = "local-dns")]
Some("dns") => ProtocolType::Dns,
Some(p) => panic!("not supported `protocol` \"{}\"", p),
None => ProtocolType::Socks,
};
let mut local_config = LocalConfig::new(local_addr, protocol);
if let Some(udp_bind_addr) = matches.value_of("UDP_BIND_ADDR") {
local_config.udp_addr = Some(udp_bind_addr.parse::<ServerAddr>().expect("udp-bind-addr"));
}
#[cfg(feature = "local-tunnel")]
if let Some(faddr) = matches.value_of("FORWARD_ADDR") {
let addr = faddr.parse::<Address>().expect("forward-addr");
local_config.forward_addr = Some(addr);
}
#[cfg(feature = "local-redir")]
{
if let Some(tcp_redir) = matches.value_of("TCP_REDIR") {
local_config.tcp_redir = tcp_redir.parse::<RedirType>().expect("TCP redir type");
}
if let Some(udp_redir) = matches.value_of("UDP_REDIR") {
local_config.udp_redir = udp_redir.parse::<RedirType>().expect("UDP redir type");
}
}
#[cfg(feature = "local-dns")]
{
use shadowsocks_service::local::dns::NameServerAddr;
if let Some(local_dns_addr) = matches.value_of("LOCAL_DNS_ADDR") {
let addr = local_dns_addr.parse::<NameServerAddr>().expect("local dns address");
local_config.local_dns_addr = Some(addr);
}
if let Some(remote_dns_addr) = matches.value_of("REMOTE_DNS_ADDR") {
let addr = remote_dns_addr.parse::<Address>().expect("remote dns address");
local_config.remote_dns_addr = Some(addr);
}
}
#[cfg(target_os = "android")]
if protocol != ProtocolType::Dns {
// Start a DNS local server binding to DNS_LOCAL_ADDR
//
// This is a special route only for shadowsocks-android
if let Some(dns_relay_addr) = matches.value_of("DNS_LOCAL_ADDR") {
let addr = dns_relay_addr.parse::<ServerAddr>().expect("dns relay address");
let mut local_dns_config = LocalConfig::new(addr, ProtocolType::Dns);
// The `local_dns_addr` and `remote_dns_addr` are for this DNS server (for compatibility)
local_dns_config.local_dns_addr = local_config.local_dns_addr.take();
local_dns_config.remote_dns_addr = local_config.remote_dns_addr.take();
config.local.push(local_dns_config);
}
}
config.local.push(local_config);
}
// override the config's mode if UDP_ONLY is set
@@ -326,23 +368,6 @@ fn main() {
config.ipv6_first = true;
}
#[cfg(feature = "local-tunnel")]
if let Some(faddr) = matches.value_of("FORWARD_ADDR") {
let addr = faddr.parse::<Address>().expect("forward-addr");
config.forward = Some(addr);
}
#[cfg(feature = "local-redir")]
{
if let Some(tcp_redir) = matches.value_of("TCP_REDIR") {
config.tcp_redir = tcp_redir.parse::<RedirType>().expect("TCP redir type");
}
if let Some(udp_redir) = matches.value_of("UDP_REDIR") {
config.udp_redir = udp_redir.parse::<RedirType>().expect("UDP redir type");
}
}
if let Some(udp_timeout) = matches.value_of("UDP_TIMEOUT") {
config.udp_timeout = Some(Duration::from_secs(udp_timeout.parse::<u64>().expect("udp-timeout")));
}
@@ -351,10 +376,6 @@ fn main() {
config.udp_max_associations = Some(udp_max_assoc.parse::<usize>().expect("udp-max-associations"));
}
if let Some(udp_bind_addr) = matches.value_of("UDP_BIND_ADDR") {
config.udp_bind_addr = Some(udp_bind_addr.parse::<ServerAddr>().expect("udp-bind-addr"));
}
if let Some(bs) = matches.value_of("INBOUND_SEND_BUFFER_SIZE") {
config.inbound_send_buffer_size = Some(bs.parse::<u32>().expect("inbound-send-buffer-size"));
}
@@ -370,7 +391,7 @@ fn main() {
// DONE READING options
if config.local_addr.is_none() {
if config.local.is_empty() {
eprintln!(
"missing `local_address`, consider specifying it by --local-addr command line option, \
or \"local_address\" and \"local_port\" in configuration file"

View File

@@ -7,10 +7,7 @@
//! *It should be notice that the extented configuration file is not suitable for the server
//! side.*
use std::{
net::{IpAddr, SocketAddr},
time::Duration,
};
use std::{net::IpAddr, time::Duration};
use clap::{clap_app, Arg};
use futures::future::{self, Either};
@@ -22,7 +19,7 @@ use shadowsocks_service::{
config::{Config, ConfigType, ManagerConfig, ManagerServerHost, Mode},
run_manager,
shadowsocks::{
config::{ManagerAddr, ServerAddr},
config::ManagerAddr,
crypto::v1::{available_ciphers, CipherKind},
},
};
@@ -50,7 +47,7 @@ fn main() {
the only required fields are \"manager_address\" and \"manager_port\". \
Servers defined will be created when process is started.")
(@arg BIND_ADDR: -b --("bind-addr") +takes_value "Bind address, outbound socket will bind this address")
(@arg BIND_ADDR: -b --("bind-addr") +takes_value {validator::validate_ip_addr} "Bind address, outbound socket will bind this address")
(@arg SERVER_HOST: -s --("server-host") +takes_value "Host name or IP address of your remote server")
(@arg NO_DELAY: --("no-delay") !takes_value "Set TCP_NODELAY option for socket")
@@ -137,11 +134,7 @@ fn main() {
};
if let Some(bind_addr) = matches.value_of("BIND_ADDR") {
let bind_addr = match bind_addr.parse::<IpAddr>() {
Ok(ip) => ServerAddr::from(SocketAddr::new(ip, 0)),
Err(..) => ServerAddr::from((bind_addr, 0)),
};
let bind_addr = bind_addr.parse::<IpAddr>().expect("bind-addr");
config.local_addr = Some(bind_addr);
}

View File

@@ -7,10 +7,7 @@
//! *It should be notice that the extented configuration file is not suitable for the server
//! side.*
use std::{
net::{IpAddr, SocketAddr},
time::Duration,
};
use std::{net::IpAddr, time::Duration};
use clap::{clap_app, Arg};
use futures::future::{self, Either};
@@ -48,7 +45,7 @@ fn main() {
(@arg CONFIG: -c --config +takes_value required_unless("SERVER_ADDR") "Shadowsocks configuration file (https://shadowsocks.org/en/config/quick-guide.html)")
(@arg BIND_ADDR: -b --("bind-addr") +takes_value "Bind address, outbound socket will bind this address")
(@arg BIND_ADDR: -b --("bind-addr") +takes_value {validator::validate_ip_addr} "Bind address, outbound socket will bind this address")
(@arg SERVER_ADDR: -s --("server-addr") +takes_value {validator::validate_server_addr} requires[PASSWORD ENCRYPT_METHOD] "Server address")
(@arg PASSWORD: -k --password +takes_value requires[SERVER_ADDR] "Server's password")
@@ -175,11 +172,7 @@ fn main() {
}
if let Some(bind_addr) = matches.value_of("BIND_ADDR") {
let bind_addr = match bind_addr.parse::<IpAddr>() {
Ok(ip) => ServerAddr::from(SocketAddr::new(ip, 0)),
Err(..) => ServerAddr::from((bind_addr, 0)),
};
let bind_addr = bind_addr.parse::<IpAddr>().expect("bind-addr");
config.local_addr = Some(bind_addr);
}

View File

@@ -1,6 +1,6 @@
[package]
name = "shadowsocks-service"
version = "1.9.2"
version = "1.10.0"
authors = ["Shadowsocks Contributors"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/shadowsocks/shadowsocks-rust"
@@ -105,7 +105,7 @@ regex = "1.4"
serde = { version = "1.0", features = ["derive"] }
json5 = "0.3"
shadowsocks = { version = "1.9.2", path = "../shadowsocks" }
shadowsocks = { version = "1.10.0", path = "../shadowsocks" }
strum = { version = "0.20", optional = true }
strum_macros = { version = "0.20", optional = true }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
//! DNS resolvers
use shadowsocks::{dns_resolver::DnsResolver, net::ConnectOpts};
use crate::config::DnsConfig;
#[allow(unused_variables)]
pub async fn build_dns_resolver(dns: DnsConfig, ipv6_first: bool, connect_opts: &ConnectOpts) -> Option<DnsResolver> {
match dns {
DnsConfig::System => {
#[cfg(feature = "trust-dns")]
if crate::hint_support_default_system_resolver() {
use log::warn;
return match DnsResolver::trust_dns_system_resolver(ipv6_first).await {
Ok(r) => Some(r),
Err(err) => {
warn!(
"initialize trust-dns DNS system resolver failed, fallback to default system resolver, error: {}",
err
);
None
}
};
}
None
}
#[cfg(feature = "trust-dns")]
DnsConfig::TrustDns(dns) => match DnsResolver::trust_dns_resolver(dns, ipv6_first).await {
Ok(r) => Some(r),
Err(err) => {
use log::warn;
warn!(
"initialize trust-dns DNS resolver failed, fallback to default system resolver, error: {}",
err
);
None
}
},
#[cfg(feature = "local-dns")]
DnsConfig::LocalDns(ns) => {
use crate::{config::Mode, local::dns::dns_resolver::DnsResolver as LocalDnsResolver};
use log::trace;
trace!("initializing direct DNS resolver for {}", ns);
let mut resolver = LocalDnsResolver::new(ns);
resolver.set_mode(Mode::TcpAndUdp);
resolver.set_ipv6_first(ipv6_first);
resolver.set_connect_opts(connect_opts.clone());
Some(DnsResolver::custom_resolver(resolver))
}
}
}

View File

@@ -60,6 +60,7 @@ pub use shadowsocks;
pub mod acl;
pub mod config;
mod dns;
#[cfg(feature = "local")]
pub mod local;
#[cfg(feature = "manager")]

View File

@@ -19,6 +19,7 @@ use shadowsocks::{
lookup_then,
net::{TcpListener, UdpSocket as ShadowUdpSocket},
relay::{udprelay::MAXIMUM_UDP_PAYLOAD_SIZE, Address},
ServerAddr,
};
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
@@ -32,7 +33,7 @@ use trust_dns_resolver::proto::{
use crate::{
acl::AccessControl,
config::{ClientConfig, Mode},
config::Mode,
local::{context::ServiceContext, loadbalancing::PingBalancer},
};
@@ -69,7 +70,7 @@ impl Dns {
}
/// Run server
pub async fn run(self, bind_addr: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
pub async fn run(self, bind_addr: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let client = Arc::new(DnsClient::new(self.context.clone(), balancer, self.mode));
let tcp_fut = self.run_tcp_server(bind_addr, client.clone());
@@ -83,12 +84,10 @@ impl Dns {
}
}
async fn run_tcp_server(&self, bind_addr: &ClientConfig, client: Arc<DnsClient>) -> io::Result<()> {
async fn run_tcp_server(&self, bind_addr: &ServerAddr, client: Arc<DnsClient>) -> io::Result<()> {
let listener = match *bind_addr {
ClientConfig::SocketAddr(ref saddr) => {
TcpListener::bind_with_opts(saddr, self.context.accept_opts()).await?
}
ClientConfig::DomainName(ref dname, port) => {
ServerAddr::SocketAddr(ref saddr) => TcpListener::bind_with_opts(saddr, self.context.accept_opts()).await?,
ServerAddr::DomainName(ref dname, port) => {
lookup_then!(self.context.context_ref(), dname, port, |addr| {
TcpListener::bind_with_opts(&addr, self.context.accept_opts()).await
})?
@@ -190,10 +189,10 @@ impl Dns {
Ok(())
}
async fn run_udp_server(&self, bind_addr: &ClientConfig, client: Arc<DnsClient>) -> io::Result<()> {
async fn run_udp_server(&self, bind_addr: &ServerAddr, client: Arc<DnsClient>) -> io::Result<()> {
let socket = match *bind_addr {
ClientConfig::SocketAddr(ref saddr) => ShadowUdpSocket::listen(&saddr).await?,
ClientConfig::DomainName(ref dname, port) => {
ServerAddr::SocketAddr(ref saddr) => ShadowUdpSocket::listen(&saddr).await?,
ServerAddr::DomainName(ref dname, port) => {
lookup_then!(&self.context.context_ref(), dname, port, |addr| {
ShadowUdpSocket::listen(&addr).await
})?

View File

@@ -17,10 +17,7 @@ use hyper::{
use log::{error, info};
use shadowsocks::{config::ServerAddr, lookup_then};
use crate::{
config::ClientConfig,
local::{context::ServiceContext, loadbalancing::PingBalancer},
};
use crate::local::{context::ServiceContext, loadbalancing::PingBalancer};
use super::{client_cache::ProxyClientCache, connector::BypassConnector, dispatcher::HttpDispatcher};
@@ -47,7 +44,7 @@ impl Http {
}
/// Run server
pub async fn run(self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
pub async fn run(self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let bypass_client = Client::builder().build::<_, Body>(BypassConnector::new(self.context.clone()));
let context = self.context.clone();

View File

@@ -4,18 +4,23 @@
use std::path::PathBuf;
use std::{io, sync::Arc, time::Duration};
use futures::{future, FutureExt};
use futures::{
future,
stream::{FuturesUnordered, StreamExt},
FutureExt,
};
use log::{error, trace, warn};
#[cfg(any(feature = "local-dns", feature = "trust-dns"))]
use shadowsocks::dns_resolver::DnsResolver;
use shadowsocks::{
net::{AcceptOpts, ConnectOpts},
plugin::{Plugin, PluginMode},
};
use crate::config::{Config, ConfigType, ProtocolType};
#[cfg(feature = "local-flow-stat")]
use crate::net::FlowStat;
use crate::{
config::{Config, ConfigType, ProtocolType},
dns::build_dns_resolver,
};
use self::{
context::ServiceContext,
@@ -38,7 +43,7 @@ pub mod utils;
/// Starts a shadowsocks local server
pub async fn run(mut config: Config) -> io::Result<()> {
assert!(config.config_type == ConfigType::Local && config.local_addr.is_some());
assert!(config.config_type == ConfigType::Local && !config.local.is_empty());
assert!(config.server.len() > 0);
trace!("{:?}", config);
@@ -83,101 +88,34 @@ pub async fn run(mut config: Config) -> io::Result<()> {
accept_opts.tcp.recv_buffer_size = config.inbound_recv_buffer_size;
accept_opts.tcp.nodelay = config.no_delay;
// #[cfg(all(feature = "local-dns", feature = "trust-dns"))]
// if let Some(socket_addr) = config.local_dns_addr {
// use trust_dns_resolver::config::{NameServerConfig, Protocol, ResolverConfig};
//
// trace!("initializing direct DNS resolver for {}", socket_addr);
//
// let mut resolver_config = ResolverConfig::new();
//
// resolver_config.add_name_server(NameServerConfig {
// socket_addr,
// protocol: Protocol::Udp,
// tls_dns_name: None,
// trust_nx_responses: false,
// #[cfg(feature = "dns-over-tls")]
// tls_config: None,
// });
// resolver_config.add_name_server(NameServerConfig {
// socket_addr,
// protocol: Protocol::Tcp,
// tls_dns_name: None,
// trust_nx_responses: false,
// #[cfg(feature = "dns-over-tls")]
// tls_config: None,
// });
//
// match DnsResolver::trust_dns_resolver(Some(resolver_config), config.ipv6_first).await {
// Ok(r) => {
// context.set_dns_resolver(Arc::new(r));
// }
// Err(err) => {
// error!(
// "initialize DNS resolver failed, nameserver: {}, error: {}",
// socket_addr, err
// );
// return Err(err);
// }
// }
// }
#[cfg(feature = "local-dns")]
if let Some(ref ns) = config.local_dns_addr {
use crate::{config::Mode, local::dns::dns_resolver::DnsResolver as LocalDnsResolver};
trace!("initializing direct DNS resolver for {}", ns);
let mut resolver = LocalDnsResolver::new(ns.clone());
resolver.set_mode(Mode::TcpAndUdp);
resolver.set_ipv6_first(config.ipv6_first);
resolver.set_connect_opts(context.connect_opts_ref().clone());
context.set_dns_resolver(Arc::new(DnsResolver::custom_resolver(resolver)));
}
#[cfg(feature = "trust-dns")]
if context.dns_resolver().is_system_resolver() {
if config.dns.is_some() || crate::hint_support_default_system_resolver() {
let r = match config.dns {
None => DnsResolver::trust_dns_system_resolver(config.ipv6_first).await,
Some(dns) => DnsResolver::trust_dns_resolver(dns, config.ipv6_first).await,
};
match r {
Ok(r) => {
context.set_dns_resolver(Arc::new(r));
}
Err(err) => {
warn!(
"initialize DNS resolver failed, fallback to system resolver, error: {}",
err
);
}
}
}
if let Some(resolver) = build_dns_resolver(config.dns, config.ipv6_first, context.connect_opts_ref()).await {
context.set_dns_resolver(Arc::new(resolver));
}
if let Some(acl) = config.acl {
context.set_acl(acl);
}
let client_config = config.local_addr.expect("local server requires local address");
assert!(!config.local.is_empty(), "no valid local server configuration");
let context = Arc::new(context);
let mut vfut = Vec::new();
let vfut = FuturesUnordered::new();
let enable_tcp = match config.local_protocol {
ProtocolType::Socks => config.mode.enable_tcp(),
// Check if any of the local servers enable TCP connections
let mode = config.mode;
let enable_tcp = config.local.iter().any(|local_config| match local_config.protocol {
ProtocolType::Socks => mode.enable_tcp(),
#[cfg(feature = "local-tunnel")]
ProtocolType::Tunnel => config.mode.enable_tcp(),
ProtocolType::Tunnel => mode.enable_tcp(),
#[cfg(feature = "local-http")]
ProtocolType::Http => true,
#[cfg(feature = "local-redir")]
ProtocolType::Redir => config.mode.enable_tcp(),
ProtocolType::Redir => mode.enable_tcp(),
#[cfg(feature = "local-dns")]
ProtocolType::Dns => config.mode.enable_tcp(),
};
ProtocolType::Dns => mode.enable_tcp(),
});
if enable_tcp {
// Start plugins for TCP proxies
@@ -241,20 +179,20 @@ pub async fn run(mut config: Config) -> io::Result<()> {
balancer
};
#[cfg(feature = "local-dns")]
if matches!(config.local_protocol, ProtocolType::Dns) || config.dns_bind_addr.is_some() {
use self::dns::Dns;
// #[cfg(feature = "local-dns")]
// if matches!(config.local_protocol, ProtocolType::Dns) || config.dns_bind_addr.is_some() {
// use self::dns::Dns;
let local_addr = config.local_dns_addr.expect("missing local_dns_addr");
let remote_addr = config.remote_dns_addr.expect("missing remote_dns_addr");
// let local_addr = config.local_dns_addr.expect("missing local_dns_addr");
// let remote_addr = config.remote_dns_addr.expect("missing remote_dns_addr");
let bind_addr = config.dns_bind_addr.as_ref().unwrap_or_else(|| &client_config);
// let bind_addr = config.dns_bind_addr.as_ref().unwrap_or_else(|| &client_config);
let mut server = Dns::with_context(context.clone(), local_addr, remote_addr);
server.set_mode(config.mode);
// let mut server = Dns::with_context(context.clone(), local_addr, remote_addr);
// server.set_mode(config.mode);
vfut.push(server.run(bind_addr, balancer.clone()).boxed());
}
// vfut.push(server.run(bind_addr, balancer.clone()).boxed());
// }
#[cfg(feature = "local-flow-stat")]
if let Some(stat_path) = config.stat_path {
@@ -264,82 +202,100 @@ pub async fn run(mut config: Config) -> io::Result<()> {
vfut.push(report_fut.boxed());
}
match config.local_protocol {
ProtocolType::Socks => {
use self::socks::Socks;
for local_config in config.local {
let balancer = balancer.clone();
let client_addr = local_config.addr;
let mut server = Socks::with_context(context);
server.set_mode(config.mode);
match local_config.protocol {
ProtocolType::Socks => {
use self::socks::Socks;
if let Some(c) = config.udp_max_associations {
server.set_udp_capacity(c);
}
if let Some(d) = config.udp_timeout {
server.set_udp_expiry_duration(d);
}
if let Some(b) = config.udp_bind_addr {
server.set_udp_bind_addr(b);
}
if config.no_delay {
server.set_nodelay(true);
}
let mut server = Socks::with_context(context.clone());
server.set_mode(config.mode);
vfut.push(server.run(&client_config, balancer).boxed());
if let Some(c) = config.udp_max_associations {
server.set_udp_capacity(c);
}
if let Some(d) = config.udp_timeout {
server.set_udp_expiry_duration(d);
}
if let Some(b) = local_config.udp_addr {
server.set_udp_bind_addr(b.clone());
}
if config.no_delay {
server.set_nodelay(true);
}
vfut.push(async move { server.run(&client_addr, balancer).await }.boxed());
}
#[cfg(feature = "local-tunnel")]
ProtocolType::Tunnel => {
use self::tunnel::Tunnel;
let forward_addr = local_config.forward_addr.expect("tunnel requires forward address");
let mut server = Tunnel::with_context(context.clone(), forward_addr.clone());
if let Some(c) = config.udp_max_associations {
server.set_udp_capacity(c);
}
if let Some(d) = config.udp_timeout {
server.set_udp_expiry_duration(d);
}
server.set_mode(config.mode);
if config.no_delay {
server.set_nodelay(true);
}
vfut.push(async move { server.run(&client_addr, balancer).await }.boxed());
}
#[cfg(feature = "local-http")]
ProtocolType::Http => {
use self::http::Http;
let server = Http::with_context(context.clone());
vfut.push(async move { server.run(&client_addr, balancer).await }.boxed());
}
#[cfg(feature = "local-redir")]
ProtocolType::Redir => {
use self::redir::Redir;
let mut server = Redir::with_context(context.clone());
if let Some(c) = config.udp_max_associations {
server.set_udp_capacity(c);
}
if let Some(d) = config.udp_timeout {
server.set_udp_expiry_duration(d);
}
server.set_mode(config.mode);
if config.no_delay {
server.set_nodelay(true);
}
server.set_tcp_redir(local_config.tcp_redir);
server.set_udp_redir(local_config.udp_redir);
vfut.push(async move { server.run(&client_addr, balancer).await }.boxed());
}
#[cfg(feature = "local-dns")]
ProtocolType::Dns => {
use self::dns::Dns;
let mut server = {
let local_addr = local_config.local_dns_addr.expect("missing local_dns_addr");
let remote_addr = local_config.remote_dns_addr.expect("missing remote_dns_addr");
Dns::with_context(context.clone(), local_addr.clone(), remote_addr.clone())
};
server.set_mode(config.mode);
vfut.push(async move { server.run(&client_addr, balancer).await }.boxed());
}
}
#[cfg(feature = "local-tunnel")]
ProtocolType::Tunnel => {
use self::tunnel::Tunnel;
let forward_addr = config.forward.expect("tunnel requires forward address");
let mut server = Tunnel::with_context(context, forward_addr);
if let Some(c) = config.udp_max_associations {
server.set_udp_capacity(c);
}
if let Some(d) = config.udp_timeout {
server.set_udp_expiry_duration(d);
}
server.set_mode(config.mode);
if config.no_delay {
server.set_nodelay(true);
}
vfut.push(server.run(&client_config, balancer).boxed());
}
#[cfg(feature = "local-http")]
ProtocolType::Http => {
use self::http::Http;
let server = Http::with_context(context);
vfut.push(server.run(&client_config, balancer).boxed());
}
#[cfg(feature = "local-redir")]
ProtocolType::Redir => {
use self::redir::Redir;
let mut server = Redir::with_context(context);
if let Some(c) = config.udp_max_associations {
server.set_udp_capacity(c);
}
if let Some(d) = config.udp_timeout {
server.set_udp_expiry_duration(d);
}
server.set_mode(config.mode);
if config.no_delay {
server.set_nodelay(true);
}
server.set_tcp_redir(config.tcp_redir);
server.set_udp_redir(config.udp_redir);
vfut.push(server.run(&client_config, balancer).boxed());
}
#[cfg(feature = "local-dns")]
ProtocolType::Dns => {}
}
let (res, ..) = future::select_all(vfut).await;
res
// let (res, ..) = future::select_all(vfut).await;
let (res, _) = vfut.into_future().await;
res.unwrap()
}
#[cfg(feature = "local-flow-stat")]

View File

@@ -3,9 +3,10 @@
use std::{io, sync::Arc, time::Duration};
use futures::{future, FutureExt};
use shadowsocks::ServerAddr;
use crate::{
config::{ClientConfig, Mode, RedirType},
config::{Mode, RedirType},
local::{context::ServiceContext, loadbalancing::PingBalancer},
};
@@ -73,7 +74,7 @@ impl Redir {
}
/// Start serving
pub async fn run(self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
pub async fn run(self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let mut vfut = Vec::new();
if self.mode.enable_tcp() {
@@ -88,7 +89,7 @@ impl Redir {
res
}
async fn run_tcp_tunnel(&self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
async fn run_tcp_tunnel(&self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
run_tcp_redir(
self.context.clone(),
client_config,
@@ -99,7 +100,7 @@ impl Redir {
.await
}
async fn run_udp_tunnel(&self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
async fn run_udp_tunnel(&self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let server = UdpRedir::new(
self.context.clone(),
self.udp_redir,

View File

@@ -8,14 +8,14 @@ use std::{
};
use log::{debug, error, info, trace};
use shadowsocks::{lookup_then, net::TcpListener as ShadowTcpListener, relay::socks5::Address};
use shadowsocks::{lookup_then, net::TcpListener as ShadowTcpListener, relay::socks5::Address, ServerAddr};
use tokio::{
net::{TcpListener, TcpStream},
time,
};
use crate::{
config::{ClientConfig, RedirType},
config::RedirType,
local::{
context::ServiceContext,
loadbalancing::PingBalancer,
@@ -111,14 +111,14 @@ async fn handle_redir_client(
pub async fn run_tcp_redir(
context: Arc<ServiceContext>,
client_config: &ClientConfig,
client_config: &ServerAddr,
balancer: PingBalancer,
redir_ty: RedirType,
nodelay: bool,
) -> io::Result<()> {
let listener = match *client_config {
ClientConfig::SocketAddr(ref saddr) => TcpListener::bind_redir(redir_ty, *saddr).await?,
ClientConfig::DomainName(ref dname, port) => {
ServerAddr::SocketAddr(ref saddr) => TcpListener::bind_redir(redir_ty, *saddr).await?,
ServerAddr::DomainName(ref dname, port) => {
lookup_then!(context.context_ref(), dname, port, |addr| {
TcpListener::bind_redir(redir_ty, addr).await
})?

View File

@@ -12,10 +12,11 @@ use log::{error, info, trace, warn};
use shadowsocks::{
lookup_then,
relay::{socks5::Address, udprelay::MAXIMUM_UDP_PAYLOAD_SIZE},
ServerAddr,
};
use crate::{
config::{ClientConfig, RedirType},
config::RedirType,
local::{
context::ServiceContext,
loadbalancing::PingBalancer,
@@ -112,10 +113,10 @@ impl UdpRedir {
}
}
pub async fn run(&self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
pub async fn run(&self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let listener = match *client_config {
ClientConfig::SocketAddr(ref saddr) => UdpRedirSocket::listen(self.redir_ty, *saddr)?,
ClientConfig::DomainName(ref dname, port) => {
ServerAddr::SocketAddr(ref saddr) => UdpRedirSocket::listen(self.redir_ty, *saddr)?,
ServerAddr::DomainName(ref dname, port) => {
lookup_then!(self.context.context_ref(), dname, port, |addr| {
UdpRedirSocket::listen(self.redir_ty, addr)
})?

View File

@@ -4,11 +4,11 @@ use std::{io, net::SocketAddr, sync::Arc, time::Duration};
use futures::{future, FutureExt};
use log::{error, info};
use shadowsocks::{lookup_then, net::TcpListener as ShadowTcpListener};
use shadowsocks::{lookup_then, net::TcpListener as ShadowTcpListener, ServerAddr};
use tokio::{net::TcpStream, time};
use crate::{
config::{ClientConfig, Mode},
config::Mode,
local::{context::ServiceContext, loadbalancing::PingBalancer},
};
@@ -26,7 +26,7 @@ pub struct Socks {
mode: Mode,
udp_expiry_duration: Option<Duration>,
udp_capacity: Option<usize>,
udp_bind_addr: Option<ClientConfig>,
udp_bind_addr: Option<ServerAddr>,
nodelay: bool,
}
@@ -68,7 +68,7 @@ impl Socks {
///
/// * If `mode` is `tcp_only`, then it will still return this address for `UDP_ASSOCIATE` command
/// * Otherwise, UDP relay will bind to this address
pub fn set_udp_bind_addr(&mut self, a: ClientConfig) {
pub fn set_udp_bind_addr(&mut self, a: ServerAddr) {
self.udp_bind_addr = Some(a);
}
@@ -78,7 +78,7 @@ impl Socks {
}
/// Start serving
pub async fn run(self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
pub async fn run(self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let mut vfut = Vec::new();
if self.mode.enable_tcp() {
@@ -96,12 +96,12 @@ impl Socks {
res
}
async fn run_tcp_server(&self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
async fn run_tcp_server(&self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let listener = match *client_config {
ClientConfig::SocketAddr(ref saddr) => {
ServerAddr::SocketAddr(ref saddr) => {
ShadowTcpListener::bind_with_opts(saddr, self.context.accept_opts()).await?
}
ClientConfig::DomainName(ref dname, port) => {
ServerAddr::DomainName(ref dname, port) => {
lookup_then!(self.context.context_ref(), dname, port, |addr| {
ShadowTcpListener::bind_with_opts(&addr, self.context.accept_opts()).await
})?
@@ -157,7 +157,7 @@ impl Socks {
#[cfg(feature = "local-socks4")]
async fn handle_tcp_client(
context: Arc<ServiceContext>,
udp_bind_addr: Option<Arc<ClientConfig>>,
udp_bind_addr: Option<Arc<ServerAddr>>,
stream: TcpStream,
balancer: PingBalancer,
peer_addr: SocketAddr,
@@ -194,7 +194,7 @@ impl Socks {
#[cfg(not(feature = "local-socks4"))]
async fn handle_tcp_client(
context: Arc<ServiceContext>,
udp_bind_addr: Option<Arc<ClientConfig>>,
udp_bind_addr: Option<Arc<ServerAddr>>,
stream: TcpStream,
balancer: PingBalancer,
peer_addr: SocketAddr,
@@ -205,7 +205,7 @@ impl Socks {
handler.handle_socks5_client(stream, peer_addr).await
}
async fn run_udp_server(&self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
async fn run_udp_server(&self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let server = Socks5UdpServer::new(self.context.clone(), self.udp_expiry_duration, self.udp_capacity);
let udp_bind_addr = self.udp_bind_addr.as_ref().unwrap_or(client_config);

View File

@@ -7,20 +7,23 @@ use std::{
};
use log::{debug, error, trace, warn};
use shadowsocks::relay::socks5::{
self,
Address,
Command,
HandshakeRequest,
HandshakeResponse,
Reply,
TcpRequestHeader,
TcpResponseHeader,
use shadowsocks::{
relay::socks5::{
self,
Address,
Command,
HandshakeRequest,
HandshakeResponse,
Reply,
TcpRequestHeader,
TcpResponseHeader,
},
ServerAddr,
};
use tokio::net::TcpStream;
use crate::{
config::{ClientConfig, Mode},
config::Mode,
local::{
context::ServiceContext,
loadbalancing::PingBalancer,
@@ -32,7 +35,7 @@ use crate::{
pub struct Socks5TcpHandler {
context: Arc<ServiceContext>,
udp_bind_addr: Option<Arc<ClientConfig>>,
udp_bind_addr: Option<Arc<ServerAddr>>,
nodelay: bool,
balancer: PingBalancer,
mode: Mode,
@@ -41,7 +44,7 @@ pub struct Socks5TcpHandler {
impl Socks5TcpHandler {
pub fn new(
context: Arc<ServiceContext>,
udp_bind_addr: Option<Arc<ClientConfig>>,
udp_bind_addr: Option<Arc<ServerAddr>>,
nodelay: bool,
balancer: PingBalancer,
mode: Mode,

View File

@@ -18,16 +18,14 @@ use shadowsocks::{
socks5::{Address, UdpAssociateHeader},
udprelay::MAXIMUM_UDP_PAYLOAD_SIZE,
},
ServerAddr,
};
use tokio::{net::UdpSocket, time};
use crate::{
config::ClientConfig,
local::{
context::ServiceContext,
loadbalancing::PingBalancer,
net::{UdpAssociationManager, UdpInboundWrite},
},
use crate::local::{
context::ServiceContext,
loadbalancing::PingBalancer,
net::{UdpAssociationManager, UdpInboundWrite},
};
#[derive(Clone)]
@@ -69,10 +67,10 @@ impl Socks5UdpServer {
}
}
pub async fn run(&self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
pub async fn run(&self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let socket = match *client_config {
ClientConfig::SocketAddr(ref saddr) => ShadowUdpSocket::listen(&saddr).await?,
ClientConfig::DomainName(ref dname, port) => {
ServerAddr::SocketAddr(ref saddr) => ShadowUdpSocket::listen(&saddr).await?,
ServerAddr::DomainName(ref dname, port) => {
lookup_then!(&self.context.context_ref(), dname, port, |addr| {
ShadowUdpSocket::listen(&addr).await
})?

View File

@@ -3,10 +3,10 @@
use std::{io, sync::Arc, time::Duration};
use futures::{future, FutureExt};
use shadowsocks::relay::socks5::Address;
use shadowsocks::{relay::socks5::Address, ServerAddr};
use crate::{
config::{ClientConfig, Mode},
config::Mode,
local::{context::ServiceContext, loadbalancing::PingBalancer},
};
@@ -62,7 +62,7 @@ impl Tunnel {
}
/// Start serving
pub async fn run(self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
pub async fn run(self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let mut vfut = Vec::new();
if self.mode.enable_tcp() {
@@ -77,7 +77,7 @@ impl Tunnel {
res
}
async fn run_tcp_tunnel(&self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
async fn run_tcp_tunnel(&self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
run_tcp_tunnel(
self.context.clone(),
client_config,
@@ -88,7 +88,7 @@ impl Tunnel {
.await
}
async fn run_udp_tunnel(&self, client_config: &ClientConfig, balancer: PingBalancer) -> io::Result<()> {
async fn run_udp_tunnel(&self, client_config: &ServerAddr, balancer: PingBalancer) -> io::Result<()> {
let mut server = UdpTunnel::new(self.context.clone(), self.udp_expiry_duration, self.udp_capacity);
server.run(client_config, balancer, &self.forward_addr).await
}

View File

@@ -3,29 +3,26 @@
use std::{io, net::SocketAddr, sync::Arc, time::Duration};
use log::{error, info, trace};
use shadowsocks::{lookup_then, net::TcpListener as ShadowTcpListener, relay::socks5::Address};
use shadowsocks::{lookup_then, net::TcpListener as ShadowTcpListener, relay::socks5::Address, ServerAddr};
use tokio::{net::TcpStream, time};
use crate::{
config::ClientConfig,
local::{
context::ServiceContext,
loadbalancing::PingBalancer,
net::AutoProxyClientStream,
utils::establish_tcp_tunnel,
},
use crate::local::{
context::ServiceContext,
loadbalancing::PingBalancer,
net::AutoProxyClientStream,
utils::establish_tcp_tunnel,
};
pub async fn run_tcp_tunnel(
context: Arc<ServiceContext>,
client_config: &ClientConfig,
client_config: &ServerAddr,
balancer: PingBalancer,
forward_addr: &Address,
nodelay: bool,
) -> io::Result<()> {
let listener = match *client_config {
ClientConfig::SocketAddr(ref saddr) => ShadowTcpListener::bind_with_opts(saddr, context.accept_opts()).await?,
ClientConfig::DomainName(ref dname, port) => {
ServerAddr::SocketAddr(ref saddr) => ShadowTcpListener::bind_with_opts(saddr, context.accept_opts()).await?,
ServerAddr::DomainName(ref dname, port) => {
lookup_then!(context.context_ref(), dname, port, |addr| {
ShadowTcpListener::bind_with_opts(&addr, context.accept_opts()).await
})?

View File

@@ -14,6 +14,7 @@ use shadowsocks::{
socks5::Address,
udprelay::{ProxySocket, MAXIMUM_UDP_PAYLOAD_SIZE},
},
ServerAddr,
};
use spin::Mutex as SpinMutex;
use tokio::{
@@ -23,7 +24,6 @@ use tokio::{
};
use crate::{
config::ClientConfig,
local::{context::ServiceContext, loadbalancing::PingBalancer},
net::MonProxySocket,
};
@@ -71,13 +71,13 @@ impl UdpTunnel {
pub async fn run(
&mut self,
client_config: &ClientConfig,
client_config: &ServerAddr,
balancer: PingBalancer,
forward_addr: &Address,
) -> io::Result<()> {
let socket = match *client_config {
ClientConfig::SocketAddr(ref saddr) => ShadowUdpSocket::listen(&saddr).await?,
ClientConfig::DomainName(ref dname, port) => {
ServerAddr::SocketAddr(ref saddr) => ShadowUdpSocket::listen(&saddr).await?,
ServerAddr::DomainName(ref dname, port) => {
lookup_then!(&self.context.context_ref(), dname, port, |addr| {
ShadowUdpSocket::listen(&addr).await
})?

View File

@@ -2,17 +2,15 @@
//!
//! Service for managing multiple relay servers. [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users)
use std::io::{self, ErrorKind};
#[cfg(feature = "trust-dns")]
use std::sync::Arc;
use std::{io, sync::Arc};
use log::{trace, warn};
use shadowsocks::{
config::ServerAddr,
net::{AcceptOpts, ConnectOpts},
};
use shadowsocks::net::{AcceptOpts, ConnectOpts};
use crate::config::{Config, ConfigType};
use crate::{
config::{Config, ConfigType},
dns::build_dns_resolver,
};
pub use self::server::Manager;
@@ -35,28 +33,6 @@ pub async fn run(config: Config) -> io::Result<()> {
let mut manager = Manager::new(config.manager.expect("missing manager config"));
manager.set_mode(config.mode);
#[cfg(feature = "trust-dns")]
if config.dns.is_some() || crate::hint_support_default_system_resolver() {
use shadowsocks::dns_resolver::DnsResolver;
let r = match config.dns {
None => DnsResolver::trust_dns_system_resolver(config.ipv6_first).await,
Some(dns) => DnsResolver::trust_dns_resolver(dns, config.ipv6_first).await,
};
match r {
Ok(r) => {
manager.set_dns_resolver(Arc::new(r));
}
Err(err) => {
warn!(
"initialize DNS resolver failed, fallback to system resolver, error: {}",
err
);
}
}
}
let mut connect_opts = ConnectOpts {
#[cfg(any(target_os = "linux", target_os = "android"))]
fwmark: config.outbound_fwmark,
@@ -64,16 +40,7 @@ pub async fn run(config: Config) -> io::Result<()> {
#[cfg(target_os = "android")]
vpn_protect_path: config.outbound_vpn_protect_path,
bind_local_addr: match config.local_addr {
None => None,
Some(ServerAddr::SocketAddr(sa)) => Some(sa.ip()),
Some(ServerAddr::DomainName(..)) => {
return Err(io::Error::new(
ErrorKind::InvalidInput,
"local_addr must be a SocketAddr",
));
}
},
bind_local_addr: config.local_addr,
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
bind_interface: config.outbound_bind_interface,
@@ -90,6 +57,10 @@ pub async fn run(config: Config) -> io::Result<()> {
accept_opts.tcp.recv_buffer_size = config.inbound_recv_buffer_size;
accept_opts.tcp.nodelay = config.no_delay;
if let Some(resolver) = build_dns_resolver(config.dns, config.ipv6_first, &connect_opts).await {
manager.set_dns_resolver(Arc::new(resolver));
}
manager.set_connect_opts(connect_opts);
manager.set_accept_opts(accept_opts);

View File

@@ -1,20 +1,15 @@
//! Shadowsocks server
use std::{
io::{self, ErrorKind},
sync::Arc,
};
use std::{io, sync::Arc};
use futures::{future, FutureExt};
use log::{trace, warn};
#[cfg(feature = "trust-dns")]
use shadowsocks::dns_resolver::DnsResolver;
use shadowsocks::{
config::ServerAddr,
net::{AcceptOpts, ConnectOpts},
};
use shadowsocks::net::{AcceptOpts, ConnectOpts};
use crate::config::{Config, ConfigType};
use crate::{
config::{Config, ConfigType},
dns::build_dns_resolver,
};
pub use self::server::Server;
@@ -56,16 +51,7 @@ pub async fn run(config: Config) -> io::Result<()> {
#[cfg(target_os = "android")]
vpn_protect_path: config.outbound_vpn_protect_path,
bind_local_addr: match config.local_addr {
None => None,
Some(ServerAddr::SocketAddr(sa)) => Some(sa.ip()),
Some(ServerAddr::DomainName(..)) => {
return Err(io::Error::new(
ErrorKind::InvalidInput,
"local_addr must be a SocketAddr",
));
}
},
bind_local_addr: config.local_addr,
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
bind_interface: config.outbound_bind_interface,
@@ -82,25 +68,9 @@ pub async fn run(config: Config) -> io::Result<()> {
accept_opts.tcp.recv_buffer_size = config.inbound_recv_buffer_size;
accept_opts.tcp.nodelay = config.no_delay;
#[cfg(feature = "trust-dns")]
let resolver = if config.dns.is_some() || crate::hint_support_default_system_resolver() {
let r = match config.dns {
None => DnsResolver::trust_dns_system_resolver(config.ipv6_first).await,
Some(dns) => DnsResolver::trust_dns_resolver(dns, config.ipv6_first).await,
};
match r {
Ok(r) => Some(Arc::new(r)),
Err(err) => {
warn!(
"initialize DNS resolver failed, fallback to system resolver, error: {}",
err
);
None
}
}
} else {
None
let resolver = match build_dns_resolver(config.dns, config.ipv6_first, &connect_opts).await {
Some(resolver) => Some(Arc::new(resolver)),
None => None,
};
let acl = config.acl.map(Arc::new);
@@ -108,7 +78,6 @@ pub async fn run(config: Config) -> io::Result<()> {
for svr_cfg in config.server {
let mut server = Server::new(svr_cfg);
#[cfg(feature = "trust-dns")]
if let Some(ref r) = resolver {
server.set_dns_resolver(r.clone());
}

View File

@@ -7,7 +7,7 @@ use std::{
time::Duration,
};
use futures::{future, FutureExt};
use futures::{stream::FuturesUnordered, FutureExt, StreamExt};
use log::{error, trace};
use shadowsocks::{
config::{ManagerAddr, ServerConfig},
@@ -112,7 +112,7 @@ impl Server {
/// Start serving
pub async fn run(mut self) -> io::Result<()> {
let mut vfut = Vec::new();
let vfut = FuturesUnordered::new();
if self.mode.enable_tcp() {
if let Some(plugin_cfg) = self.svr_cfg.plugin() {
@@ -149,7 +149,10 @@ impl Server {
vfut.push(manager_fut);
}
let _ = future::select_all(vfut).await;
let (res, _) = vfut.into_future().await;
if let Some(Err(err)) = res {
error!("servers exited with error: {}", err);
}
let err = io::Error::new(ErrorKind::Other, "server exited unexpectly");
Err(err)

View File

@@ -1,6 +1,6 @@
[package]
name = "shadowsocks"
version = "1.9.2"
version = "1.10.0"
authors = ["Shadowsocks Contributors"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/shadowsocks/shadowsocks-rust"

View File

@@ -1,22 +1,34 @@
{
"locals": [
{
"local_address": "127.0.0.1",
"local_port": 1080
},
{
"local_address": "127.0.0.1",
"local_port": 3128,
"protocol": "http"
},
{
"local_address": "127.0.0.1",
"local_port": 53,
"protocol": "tunnel",
"forward_address": "8.8.8.8",
"forward_port": 53
}
],
"servers": [
{
"address": "127.0.0.1",
"port": 8388,
"password": "password-svr1",
"method": "bf-cfb"
},
{
"address": "127.0.0.1",
"port": 8384,
"server": "127.0.0.1",
"server_port": 8384,
"password": "password-svr2",
"method": "aes-256-cfb"
"method": "chacha20-ietf-poly1305"
},
{
"address": "127.0.0.1",
"port": 8385,
"server": "127.0.0.1",
"server_port": 8385,
"password": "password-svr3",
"method": "rc4-md5"
"method": "aes-128-gcm"
}
]
}

View File

@@ -10,7 +10,7 @@ use tokio::{
};
use shadowsocks_service::{
config::{Config, ConfigType, ProtocolType},
config::{Config, ConfigType},
run_local,
run_server,
};
@@ -19,10 +19,17 @@ use shadowsocks_service::{
async fn dns_relay() {
let _ = env_logger::try_init();
let mut local_config = Config::load_from_str(
let local_config = Config::load_from_str(
r#"{
"local_port": 6110,
"local_address": "127.0.0.1",
"locals": [
{
"local_address": "127.0.0.1",
"local_port": 6110,
"protocol": "dns",
"local_dns_address": "114.114.114.114",
"remote_dns_address": "8.8.8.8"
}
],
"server": "127.0.0.1",
"server_port": 6120,
"password": "password",
@@ -31,9 +38,6 @@ async fn dns_relay() {
ConfigType::Local,
)
.unwrap();
local_config.local_protocol = ProtocolType::Dns;
local_config.local_dns_addr = Some("114.114.114.114:53".parse().unwrap());
local_config.remote_dns_addr = Some("8.8.8.8:53".parse().unwrap());
let server_config = Config::load_from_str(
r#"{

View File

@@ -9,7 +9,7 @@ use tokio::{
};
use shadowsocks_service::{
config::{Config, ConfigType, ProtocolType},
config::{Config, ConfigType},
run_local,
run_server,
};
@@ -18,10 +18,15 @@ use shadowsocks_service::{
async fn http_proxy() {
let _ = env_logger::try_init();
let mut local_config = Config::load_from_str(
let local_config = Config::load_from_str(
r#"{
"local_port": 5110,
"local_address": "127.0.0.1",
"locals": [
{
"local_port": 5110,
"local_address": "127.0.0.1",
"protocol": "http"
}
],
"server": "127.0.0.1",
"server_port": 5120,
"password": "password",
@@ -30,7 +35,6 @@ async fn http_proxy() {
ConfigType::Local,
)
.unwrap();
local_config.local_protocol = ProtocolType::Http;
let server_config = Config::load_from_str(
r#"{

View File

@@ -11,7 +11,7 @@ use tokio::{
};
use shadowsocks_service::{
config::{Config, ConfigType, ProtocolType},
config::{Config, ConfigType, LocalConfig, ProtocolType},
local::socks::client::Socks4TcpClient,
run_local,
run_server,
@@ -45,9 +45,8 @@ impl Socks4TestServer {
},
cli_config: {
let mut cfg = Config::new(ConfigType::Local);
cfg.local_addr = Some(ServerAddr::from(local_addr));
cfg.local = vec![LocalConfig::new(ServerAddr::from(local_addr), ProtocolType::Socks)];
cfg.server = vec![ServerConfig::new(svr_addr, pwd.to_owned(), method)];
cfg.local_protocol = ProtocolType::Socks;
cfg
},
}

View File

@@ -11,7 +11,7 @@ use tokio::{
};
use shadowsocks_service::{
config::{Config, ConfigType, Mode, ProtocolType},
config::{Config, ConfigType, LocalConfig, Mode, ProtocolType},
local::socks::client::socks5::Socks5TcpClient,
run_local,
run_server,
@@ -47,10 +47,9 @@ impl Socks5TestServer {
},
cli_config: {
let mut cfg = Config::new(ConfigType::Local);
cfg.local_addr = Some(ServerAddr::from(local_addr));
cfg.local = vec![LocalConfig::new(ServerAddr::from(local_addr), ProtocolType::Socks)];
cfg.server = vec![ServerConfig::new(svr_addr, pwd.to_owned(), method)];
cfg.mode = if enable_udp { Mode::TcpAndUdp } else { Mode::TcpOnly };
cfg.local_protocol = ProtocolType::Socks;
cfg
},
}

View File

@@ -11,20 +11,26 @@ use tokio::{
};
use shadowsocks_service::{
config::{Config, ConfigType, ProtocolType},
config::{Config, ConfigType},
run_local,
run_server,
shadowsocks::relay::socks5::Address,
};
#[tokio::test]
async fn tcp_tunnel() {
let _ = env_logger::try_init();
let mut local_config = Config::load_from_str(
let local_config = Config::load_from_str(
r#"{
"local_port": 9110,
"local_address": "127.0.0.1",
"locals": [
{
"local_port": 9110,
"local_address": "127.0.0.1",
"protocol": "tunnel",
"forward_address": "www.example.com",
"forward_port": 80
}
],
"server": "127.0.0.1",
"server_port": 9120,
"password": "password",
@@ -33,8 +39,6 @@ async fn tcp_tunnel() {
ConfigType::Local,
)
.unwrap();
local_config.local_protocol = ProtocolType::Tunnel;
local_config.forward = Some("www.example.com:80".parse::<Address>().unwrap());
let server_config = Config::load_from_str(
r#"{
@@ -75,10 +79,17 @@ async fn udp_tunnel() {
let _ = env_logger::try_init();
let mut local_config = Config::load_from_str(
let local_config = Config::load_from_str(
r#"{
"local_port": 9210,
"local_address": "127.0.0.1",
"locals": [
{
"local_port": 9210,
"local_address": "127.0.0.1",
"protocol": "tunnel",
"forward_address": "8.8.8.8",
"forward_port": 53
}
],
"server": "127.0.0.1",
"server_port": 9220,
"password": "password",
@@ -88,8 +99,6 @@ async fn udp_tunnel() {
ConfigType::Local,
)
.unwrap();
local_config.local_protocol = ProtocolType::Tunnel;
local_config.forward = Some("8.8.8.8:53".parse::<Address>().unwrap());
let server_config = Config::load_from_str(
r#"{

View File

@@ -7,7 +7,7 @@ use log::debug;
use tokio::time::{self, Duration};
use shadowsocks_service::{
config::{Config, ConfigType, Mode, ProtocolType},
config::{Config, ConfigType, LocalConfig, Mode, ProtocolType},
local::socks::client::socks5::Socks5UdpClient,
run_local,
run_server,
@@ -35,14 +35,13 @@ fn get_svr_config() -> Config {
fn get_cli_config() -> Config {
let mut cfg = Config::new(ConfigType::Local);
cfg.local_addr = Some(LOCAL_ADDR.parse().unwrap());
cfg.local = vec![LocalConfig::new(LOCAL_ADDR.parse().unwrap(), ProtocolType::Socks)];
cfg.server = vec![ServerConfig::new(
SERVER_ADDR.parse::<SocketAddr>().unwrap(),
PASSWORD.to_owned(),
METHOD,
)];
cfg.mode = Mode::TcpAndUdp;
cfg.local_protocol = ProtocolType::Socks;
cfg
}