Skip to content

Commit

Permalink
[#184] Basic supports for TCP Fast Open on Windows, macOS, Linux
Browse files Browse the repository at this point in the history
Removed `trust-dns` feature gate, uses trust-dns-resolver as default
  • Loading branch information
zonyitoo committed Jan 1, 2020
1 parent af958e8 commit e905aa2
Show file tree
Hide file tree
Showing 24 changed files with 830 additions and 315 deletions.
18 changes: 13 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "shadowsocks-rust"
version = "1.8.0"
version = "1.9.0"
authors = ["Y. T. CHUNG <[email protected]>"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/zonyitoo/shadowsocks-rust"
Expand Down Expand Up @@ -32,14 +32,14 @@ path = "src/bin/ssurl.rs"
lto = true

[features]
default = ["sodium", "rc4", "aes-cfb", "aes-ctr", "trust-dns"]
default = ["sodium", "rc4", "aes-cfb", "aes-ctr", "tfo"]
sodium = ["libsodium-sys"]
rc4 = ["openssl"]
aes-cfb = ["openssl"]
aes-ctr = ["openssl"]
camellia-cfb = ["openssl"]
single-threaded = []
trust-dns = ["trust-dns-resolver"]
tfo = []

[dependencies]
log = "0.4"
Expand All @@ -66,14 +66,22 @@ url = "2.1"
byte_string = "1.0"
libsodium-sys = { version = "0.2", optional = true }
miscreant = { version = "0.5", optional = true }
trust-dns-resolver = { version = "0.18", features = ["dns-over-rustls", "dns-over-https-rustls"], optional = true }
trust-dns-resolver = { version = "0.18", features = ["dns-over-rustls", "dns-over-https-rustls"] }
hkdf = "0.8"
hmac = "0.7"
sha-1 = "0.8"
lru_time_cache = "0.9"
hyper = "0.13"
tower = "0.3"
pin-project = "0.4"
net2 = "0.2"
cfg-if = "0.1"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["mswsock", "winsock2"] }
winapi = { version = "0.3", features = ["mswsock", "winsock2"] }

# [patch.crates-io]
# libc = { git = "https://github.com/zonyitoo/libc.git", branch = "feature-linux-fastopen-connect", optional = true }

[patch.crates-io]
libc = { git = "https://github.com/zonyitoo/libc.git", branch = "feature-macos-fastopen", optional = true }
4 changes: 2 additions & 2 deletions build/build-release
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ function build() {
echo "* Done build package ${PKG_NAME}"
}

build "x86_64-unknown-linux-musl"
build "x86_64-pc-windows-gnu"
#build "x86_64-unknown-linux-musl"
build "x86_64-pc-windows-gnu"
11 changes: 9 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ use json5;
use log::error;
use serde::{Deserialize, Serialize};
use serde_urlencoded;
#[cfg(feature = "trust-dns")]
use trust_dns_resolver::config::{NameServerConfigGroup, ResolverConfig};
use url::{self, Url};

Expand Down Expand Up @@ -101,6 +100,8 @@ struct SSConfig {
mode: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
no_delay: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
fast_open: Option<bool>,
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down Expand Up @@ -535,6 +536,7 @@ pub struct Config {
pub manager_address: Option<ServerAddr>,
pub config_type: ConfigType,
pub udp_timeout: Option<Duration>,
pub fast_open: bool,
}

/// Configuration parsing error kind
Expand Down Expand Up @@ -596,6 +598,7 @@ impl Config {
manager_address: None,
config_type,
udp_timeout: None,
fast_open: false,
}
}

Expand Down Expand Up @@ -765,6 +768,9 @@ impl Config {
// UDP
nconfig.udp_timeout = config.udp_timeout.map(Duration::from_secs);

// TCP Fast Open
nconfig.fast_open = config.fast_open.unwrap_or(false);

Ok(nconfig)
}

Expand All @@ -780,7 +786,6 @@ impl Config {
Config::load_from_str(&content[..], config_type)
}

#[cfg(feature = "trust-dns")]
pub fn get_dns_config(&self) -> Option<ResolverConfig> {
self.dns.as_ref().and_then(|ds| {
match &ds[..] {
Expand Down Expand Up @@ -900,6 +905,8 @@ impl fmt::Display for Config {

jconf.udp_timeout = self.udp_timeout.map(|t| t.as_secs());

jconf.fast_open = Some(self.fast_open);

write!(f, "{}", json5::to_string(&jconf).unwrap())
}
}
10 changes: 1 addition & 9 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,19 @@ use std::{
};

use tokio::runtime::Handle;
#[cfg(feature = "trust-dns")]
use trust_dns_resolver::TokioAsyncResolver;

use crate::config::Config;
#[cfg(feature = "trust-dns")]
use crate::relay::dns_resolver::create_resolver;
use crate::{config::Config, relay::dns_resolver::create_resolver};

#[derive(Clone)]
pub struct SharedServerState {
#[cfg(feature = "trust-dns")]
dns_resolver: Arc<TokioAsyncResolver>,
server_running: Arc<AtomicBool>,
}

impl SharedServerState {
#[allow(unused_variables)]
pub async fn new(config: &Config, rt: Handle) -> io::Result<SharedServerState> {
let state = SharedServerState {
#[cfg(feature = "trust-dns")]
dns_resolver: Arc::new(create_resolver(config.get_dns_config(), rt).await?),
server_running: Arc::new(AtomicBool::new(true)),
};
Expand All @@ -46,7 +40,6 @@ impl SharedServerState {
}

/// Get the global shared resolver
#[cfg(feature = "trust-dns")]
pub fn dns_resolver(&self) -> &TokioAsyncResolver {
&*self.dns_resolver
}
Expand Down Expand Up @@ -83,7 +76,6 @@ impl Context {
}

/// Get the global shared resolver
#[cfg(feature = "trust-dns")]
pub fn dns_resolver(&self) -> &TokioAsyncResolver {
self.server_state.dns_resolver()
}
Expand Down
77 changes: 0 additions & 77 deletions src/relay/dns_resolver/tokio_dns_resolver.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/relay/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Relay server in local and server side implementations.

#[cfg(feature = "trust-dns")]
pub(crate) mod dns_resolver;
pub(crate) mod loadbalancing;
pub mod local;
Expand Down
5 changes: 0 additions & 5 deletions src/relay/tcprelay/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,12 @@ impl TcpServerContext {
ServerAddr::SocketAddr(ref addr) => {
socket.send_to(payload.as_ref(), addr).await?;
}
#[cfg(feature = "trust-dns")]
ServerAddr::DomainName(ref domain, ref port) => {
use crate::relay::dns_resolver::resolve;

let addrs = resolve(&*self.context, &domain[..], *port, false).await?;
socket.send_to(payload.as_ref(), addrs[0]).await?;
}
#[cfg(not(feature = "trust-dns"))]
ServerAddr::DomainName(ref domain, ref port) => {
socket.send_to(payload.as_ref(), (domain.as_str(), *port)).await?;
}
}

Ok(())
Expand Down
61 changes: 13 additions & 48 deletions src/relay/tcprelay/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,23 @@ use std::{
time::Duration,
};

use crate::{
config::{ConfigType, ServerAddr, ServerConfig},
context::Context,
relay::{socks5::Address, utils::try_timeout},
};

use bytes::BytesMut;
use futures::{future::FusedFuture, ready, select, Future};
use log::{debug, error, trace};
use tokio::{
self,
io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, BufReader, ReadHalf, WriteHalf},
net::TcpStream,
time::{self, Delay},
};

use crate::{
config::{ConfigType, ServerAddr, ServerConfig},
context::Context,
relay::socks5::Address,
};

use self::utils::TcpStream;

mod aead;
pub mod client;
mod context;
Expand Down Expand Up @@ -191,47 +192,11 @@ async fn connect_proxy_server_internal(
context: &Context,
svr_addr: &ServerAddr,
timeout: Option<Duration>,
fast_open: bool,
) -> io::Result<STcpStream> {
match svr_addr {
ServerAddr::SocketAddr(ref addr) => {
let stream = try_timeout(TcpStream::connect(addr), timeout).await?;
Ok(STcpStream::new(stream, timeout))
}
#[cfg(feature = "trust-dns")]
ServerAddr::DomainName(ref domain, port) => {
use crate::relay::dns_resolver::resolve;

let vec_ipaddr = try_timeout(resolve(context, &domain[..], *port, false), timeout).await?;

assert!(!vec_ipaddr.is_empty());

let mut last_err: Option<io::Error> = None;
for addr in &vec_ipaddr {
match try_timeout(TcpStream::connect(addr), timeout).await {
Ok(s) => return Ok(STcpStream::new(s, timeout)),
Err(e) => {
error!(
"Failed to connect {}:{}, resolved address {}, try another (err: {})",
domain, port, addr, e
);
last_err = Some(e);
}
}
}

let err = last_err.unwrap();
error!(
"Failed to connect {}:{}, tried all addresses but still failed (last err: {})",
domain, port, err
);
Err(err)
}
#[cfg(not(feature = "trust-dns"))]
ServerAddr::DomainName(ref domain, port) => {
let stream = try_timeout(TcpStream::connect((domain.as_str(), *port)), timeout).await?;
Ok(STcpStream::new(stream, timeout))
}
}
TcpStream::connect_server(context, svr_addr, timeout, fast_open)
.await
.map(|s| STcpStream::new(s, timeout))
}

/// Connect to proxy server with `ServerConfig`
Expand All @@ -256,7 +221,7 @@ async fn connect_proxy_server(context: &Context, svr_cfg: &ServerConfig) -> io::
trace!("Connecting to proxy {}, timeout: {:?}", svr_addr, timeout);
let mut last_err = None;
for retry_time in 0..RETRY_TIMES {
match connect_proxy_server_internal(context, svr_addr, timeout).await {
match connect_proxy_server_internal(context, svr_addr, timeout, context.config().fast_open).await {
Ok(s) => return Ok(s),
Err(err) => {
// Connection failure, retry
Expand Down
Loading

0 comments on commit e905aa2

Please sign in to comment.