diff --git a/Cargo.lock b/Cargo.lock index 277fdc4a..d92c1905 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1619,8 +1619,6 @@ dependencies = [ "shadowsocks-crypto", "socket2", "spin 0.7.0", - "strum", - "strum_macros", "tcmalloc", "tokio", "tokio-native-tls", @@ -1690,24 +1688,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -[[package]] -name = "strum" -version = "0.19.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89a286a7e3b5720b9a477b23253bc50debac207c8d21505f8e70b36792f11b5" - -[[package]] -name = "strum_macros" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e61bb0be289045cb80bfce000512e32d09f8337e54c186725da381377ad1f8d5" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "syn" version = "1.0.48" diff --git a/Cargo.toml b/Cargo.toml index 34120fe2..277714c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -134,8 +134,6 @@ trust-dns-proto = { git = "https://github.com/bluejekyll/trust-dns.git", optiona hyper = { git = "https://github.com/hyperium/hyper.git", optional = true, features = ["full"] } tower = { git = "https://github.com/tower-rs/tower.git", optional = true } -strum = "0.19" -strum_macros = "0.19" ipnet = "2.2" iprange = "0.6" diff --git a/Cross.toml b/Cross.toml index 1490154c..89eef268 100644 --- a/Cross.toml +++ b/Cross.toml @@ -1,6 +1,5 @@ [build.env] passthrough = [ - "SODIUM_BUILD_STATIC", "HTTP_PROXY", "HTTPS_PROXY", ] diff --git a/README.md b/README.md index f40c75ff..b4f4aa2b 100644 --- a/README.md +++ b/README.md @@ -361,7 +361,7 @@ Example configuration: * `camellia-128-cfb`, `camellia-128-cfb1`, `camellia-128-cfb8`, `camellia-128-cfb128` * `camellia-192-cfb`, `camellia-192-cfb1`, `camellia-192-cfb8`, `camellia-192-cfb128` * `camellia-256-cfb`, `camellia-256-cfb1`, `camellia-256-cfb8`, `camellia-256-cfb128` -* `rc4`, `rc4-md5` +* `rc4-md5` * `chacha20-ietf` * `plain` (No encryption, just for debugging) diff --git a/build/Dockerfile.x86_64-pc-windows-gnu b/build/Dockerfile.x86_64-pc-windows-gnu index 502e7b08..f5f2049a 100644 --- a/build/Dockerfile.x86_64-pc-windows-gnu +++ b/build/Dockerfile.x86_64-pc-windows-gnu @@ -1,23 +1,3 @@ -ARG HTTP_PROXY -ARG HTTPS_PROXY - FROM rustembedded/cross:x86_64-pc-windows-gnu -ARG SODIUM_VERS="1.0.18" - -RUN apt-get update && \ - apt-get install --no-install-recommends -y curl - -# Build a static copy of libsodium. -# https://github.com/jedisct1/libsodium/blob/master/dist-build/msys2-win64.sh -# -# Could be removed in the future when this issue is fixed: -# https://github.com/sodiumoxide/sodiumoxide/issues/386 -RUN curl -LO https://download.libsodium.org/libsodium/releases/libsodium-$SODIUM_VERS.tar.gz && \ - tar xzf libsodium-$SODIUM_VERS.tar.gz && cd libsodium-$SODIUM_VERS && \ - AR="x86_64-w64-mingw32-ar" CC="x86_64-w64-mingw32-gcc" CFLAGS="-Ofast -fomit-frame-pointer -m64 -mtune=westmere" ./configure --prefix=/usr/x86_64-w64-mingw32 --enable-shared=no --host=x86_64-w64-mingw32 && \ - V=1 make -j${nprocs} && make install && \ - cd .. && rm -rf libsodium-$SODIUM_VERS.tar.gz libsodium-$SODIUM_VERS - -ENV RUSTFLAGS="-Ctarget-feature=+aes,+ssse3" \ - SODIUM_LIB_DIR=/usr/x86_64-w64-mingw32/lib +ENV RUSTFLAGS="-Ctarget-feature=+aes,+ssse3" diff --git a/build/build-release b/build/build-release index 94d853e4..7081ead1 100755 --- a/build/build-release +++ b/build/build-release @@ -55,18 +55,8 @@ function build() { EXTRA_FEATURES+="local-redir" fi - EXTRA_FLAG="" - if [[ "$TARGET" == "mips"* ]]; then - # This is because `ring` doesn't support MIPS - # https://github.com/shadowsocks/shadowsocks-rust/issues/273 - # https://github.com/briansmith/ring/issues/562 - EXTRA_FEATURES="sodium rc4 aes-cfb aes-ctr local-http local-http-native-tls local-tunnel local-socks4 local-redir" - EXTRA_FLAG="--no-default-features" - fi - cross build --target "${TARGET}" \ --features "aes-pmac-siv openssl-vendored ${EXTRA_FEATURES}" \ - ${EXTRA_FLAG} \ --release if [[ $? != "0" ]]; then diff --git a/debian/control b/debian/control index 132e593a..933d8276 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: shadowsocks-rust Section: net Priority: optional Maintainer: Y. T. Chung -Build-Depends: debhelper (>=9), rustc, cargo, apg | pwgen, libcap2-bin [linux-any], libsodium-dev +Build-Depends: debhelper (>=9), rustc, cargo, apg | pwgen, libcap2-bin [linux-any] Standards-Version: 3.9.6 Homepage: https://github.com/shadowsocks/shadowsocks-rust diff --git a/src/config.rs b/src/config.rs index e94d729b..5d2db932 100644 --- a/src/config.rs +++ b/src/config.rs @@ -57,24 +57,22 @@ use std::{ }; use base64::{decode_config, encode_config, URL_SAFE_NO_PAD}; +use bytes::Bytes; use cfg_if::cfg_if; use log::error; use serde::{Deserialize, Serialize}; #[cfg(feature = "trust-dns")] use trust_dns_resolver::config::{NameServerConfig, Protocol, ResolverConfig}; use url::{self, Url}; -use bytes::Bytes; -use shadowsocks_crypto::v1::{CipherKind, openssl_bytes_to_key}; - use crate::{ acl::AccessControl, context::Context, + crypto::v1::{openssl_bytes_to_key, CipherKind}, plugin::PluginConfig, relay::{dns_resolver::resolve_bind_addr, socks5::Address}, }; - #[cfg(feature = "trust-dns")] #[derive(Serialize, Deserialize, Debug)] #[serde(untagged)] @@ -285,7 +283,7 @@ pub struct ServerConfig { timeout: Option, // Encryption key enc_key: Bytes, - + /// Plugin config plugin: Option, /// Plugin address diff --git a/src/context.rs b/src/context.rs index 653eaa89..06b7a3ac 100644 --- a/src/context.rs +++ b/src/context.rs @@ -23,8 +23,6 @@ use tokio::sync::Mutex as AsyncMutex; #[cfg(feature = "trust-dns")] use trust_dns_resolver::TokioAsyncResolver; -#[cfg(any(feature = "sodium", feature = "rc4"))] -use crate::crypto::CipherType; #[cfg(feature = "trust-dns")] use crate::relay::dns_resolver::create_resolver; #[cfg(feature = "local-dns")] @@ -34,6 +32,7 @@ use crate::relay::flow::ServerFlowStatistic; use crate::{ acl::AccessControl, config::{Config, ConfigType, ServerConfig}, + crypto::v1::CipherKind, relay::{dns_resolver::resolve, socks5::Address}, }; @@ -207,13 +206,7 @@ impl Context { // Warning for deprecated ciphers // The following stream ciphers have inherent weaknesses (see discussion at https://github.com/shadowsocks/shadowsocks-org/issues/36). // DO NOT USE. Implementors are advised to remove them as soon as possible. - let deprecated = match t { - #[cfg(feature = "sodium")] - CipherType::ChaCha20 | CipherType::Salsa20 => true, - #[cfg(feature = "rc4")] - CipherType::Rc4Md5 => true, - _ => false, - }; + let deprecated = matches!(t, CipherKind::SS_RC4_MD5); if deprecated { warn!( "stream cipher {} (for server {}) have inherent weaknesses \ diff --git a/src/relay/loadbalancing/server.rs b/src/relay/loadbalancing/server.rs index 2f881f70..9fd39861 100644 --- a/src/relay/loadbalancing/server.rs +++ b/src/relay/loadbalancing/server.rs @@ -539,7 +539,7 @@ impl PingBalancer { b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07firefox\x03com\x00\x00\x01\x00\x01"; let addr = Address::SocketAddress(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)), 53)); - + let client = UdpServerClient::new(stat.context(), stat.server_config()).await?; client.send_to(stat.context(), &addr, DNS_QUERY).await?; diff --git a/src/relay/local.rs b/src/relay/local.rs index 3dc71d9a..51478e15 100644 --- a/src/relay/local.rs +++ b/src/relay/local.rs @@ -11,11 +11,7 @@ use crate::{ config::{Config, ConfigType}, context::{Context, ServerState}, plugin::{PluginMode, Plugins}, - relay::{ - tcprelay::local::run as run_tcp, - udprelay::local::run as run_udp, - utils::set_nofile, - }, + relay::{tcprelay::local::run as run_tcp, udprelay::local::run as run_udp, utils::set_nofile}, }; /// Relay server running under local environment. diff --git a/src/relay/manager.rs b/src/relay/manager.rs index 9d67757d..0cb82c5f 100644 --- a/src/relay/manager.rs +++ b/src/relay/manager.rs @@ -16,12 +16,11 @@ use log::{debug, error, info, trace, warn}; #[cfg(unix)] use tokio::net::{unix::SocketAddr as UnixSocketAddr, UnixDatagram}; use tokio::{self, net::UdpSocket}; -use shadowsocks_crypto::v1::CipherKind; - use crate::{ config::{Config, ConfigType, ManagerAddr, Mode, ServerAddr, ServerConfig}, context::{Context, ServerState, SharedContext, SharedServerState}, + crypto::v1::CipherKind, plugin::PluginConfig, relay::{ flow::{MultiServerFlowStatistic, SharedServerFlowStatistic}, diff --git a/src/relay/tcprelay/aead.rs b/src/relay/tcprelay/aead.rs index 478ddb28..f49249c7 100644 --- a/src/relay/tcprelay/aead.rs +++ b/src/relay/tcprelay/aead.rs @@ -31,12 +31,6 @@ //! | 2 | Fixed | Variable | Fixed | //! +--------------+---------------+--------------+------------+ //! ``` -use futures::ready; -use bytes::{Buf, BufMut, BytesMut}; -use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; -use shadowsocks_crypto::v1::{CipherKind, Cipher}; - - use std::{ cmp, io, @@ -47,6 +41,11 @@ use std::{ u16, }; +use bytes::{Buf, BufMut, BytesMut}; +use futures::ready; +use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; + +use crate::crypto::v1::{Cipher, CipherKind}; /// AEAD packet payload must be smaller than 0x3FFF const MAX_PACKET_SIZE: usize = 0x3FFF; @@ -117,7 +116,7 @@ impl DecryptedReader { { let mlen = 2 + self.tag_size; ready!(self.poll_read_exact(ctx, r, mlen, true))?; - + if self.got_final { return Poll::Ready(Ok(())); } diff --git a/src/relay/tcprelay/crypto_io.rs b/src/relay/tcprelay/crypto_io.rs index 13e5e3b8..ff355e77 100644 --- a/src/relay/tcprelay/crypto_io.rs +++ b/src/relay/tcprelay/crypto_io.rs @@ -21,14 +21,13 @@ use tokio::io::{AsyncRead, AsyncWrite, ReadBuf, ReadHalf, WriteHalf}; use crate::{ config::ServerConfig, context::SharedContext, + crypto::v1::{random_iv_or_salt, CipherCategory, CipherKind}, }; use super::{ aead::{DecryptedReader as AeadDecryptedReader, EncryptedWriter as AeadEncryptedWriter}, stream::{DecryptedReader as StreamDecryptedReader, EncryptedWriter as StreamEncryptedWriter}, }; -use shadowsocks_crypto::v1::{CipherCategory, CipherKind, random_iv_or_salt, }; - enum DecryptedReader { None, @@ -66,9 +65,9 @@ impl Unpin for CryptoStream {} impl CryptoStream { /// Create a new CryptoStream with the underlying stream connection pub fn new(context: SharedContext, stream: S, svr_cfg: &ServerConfig) -> CryptoStream { - let method = svr_cfg.method(); + let method = svr_cfg.method(); let category = method.category(); - let key = svr_cfg.clone_key(); + let key = svr_cfg.clone_key(); if category == CipherCategory::None { return CryptoStream::::new_none(stream); @@ -87,7 +86,7 @@ impl CryptoStream { if prev_len > 0 { random_iv_or_salt(&mut iv); } - + if context.check_nonce_and_set(&iv) { // IV exist, generate another one continue; @@ -103,7 +102,7 @@ impl CryptoStream { if prev_len > 0 { random_iv_or_salt(&mut salt); } - + if context.check_nonce_and_set(&salt) { // Salt exist, generate another one continue; @@ -121,17 +120,12 @@ impl CryptoStream { CipherCategory::Aead => EncryptedWriter::Aead(AeadEncryptedWriter::new(method, &key, &iv)), CipherCategory::None => EncryptedWriter::None, }; - + CryptoStream { stream, dec: None, enc, - read_status: ReadStatus::WaitIv( - context, - BytesMut::with_capacity(prev_len).limit(prev_len), - method, - key, - ), + read_status: ReadStatus::WaitIv(context, BytesMut::with_capacity(prev_len).limit(prev_len), method, key), } } diff --git a/src/relay/tcprelay/mod.rs b/src/relay/tcprelay/mod.rs index 0401c827..6d1b3ed1 100644 --- a/src/relay/tcprelay/mod.rs +++ b/src/relay/tcprelay/mod.rs @@ -14,8 +14,8 @@ use tokio::{ }; mod aead; -mod stream; mod crypto_io; +mod stream; pub mod client; mod connection; diff --git a/src/relay/tcprelay/stream.rs b/src/relay/tcprelay/stream.rs index a6c795b6..8ccf8da3 100644 --- a/src/relay/tcprelay/stream.rs +++ b/src/relay/tcprelay/stream.rs @@ -1,9 +1,4 @@ //! Stream protocol implementation -use futures::ready; -use bytes::{Buf, BufMut, BytesMut}; -use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; -use shadowsocks_crypto::v1::{CipherKind, Cipher}; - use std::{ cmp, io, @@ -12,6 +7,12 @@ use std::{ task::{Context, Poll}, }; +use bytes::{Buf, BufMut, BytesMut}; +use futures::ready; +use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; + +use crate::crypto::v1::{Cipher, CipherKind}; + // use super::BUFFER_SIZE; /// Reader wrapper that will decrypt data automatically @@ -60,8 +61,8 @@ impl DecryptedReader { continue; } - let m = buffer.filled_mut(); - + let m = buffer.filled_mut(); + assert_eq!(self.cipher.decrypt_packet(m), true); // Reset pointers diff --git a/src/relay/udprelay/association.rs b/src/relay/udprelay/association.rs index d72e80f1..0fa6f8d7 100644 --- a/src/relay/udprelay/association.rs +++ b/src/relay/udprelay/association.rs @@ -24,11 +24,11 @@ use tokio::{ sync::{mpsc, Mutex}, time, }; -use shadowsocks_crypto::v1::CipherCategory; use crate::{ config::{Config, ServerAddr, ServerConfig}, context::{Context, SharedContext}, + crypto::v1::CipherCategory, relay::{ flow::SharedServerFlowStatistic, loadbalancing::server::{ServerData, SharedServerStatistic}, diff --git a/src/relay/udprelay/client.rs b/src/relay/udprelay/client.rs index e2d5e334..ca2fa644 100644 --- a/src/relay/udprelay/client.rs +++ b/src/relay/udprelay/client.rs @@ -6,16 +6,14 @@ use std::{ net::{IpAddr, Ipv4Addr, SocketAddr}, }; - use bytes::{BufMut, Bytes, BytesMut}; use log::{error, trace, warn}; use tokio::net::UdpSocket; -use shadowsocks_crypto::v1::{CipherCategory, CipherKind}; - use crate::{ config::{ServerAddr, ServerConfig}, context::Context, + crypto::v1::{CipherCategory, CipherKind}, relay::{ socks5::{Address, UdpAssociateHeader}, sys::{create_outbound_udp_socket, create_udp_socket}, @@ -112,10 +110,10 @@ impl ServerClient { } }; - let key = svr_cfg.clone_key(); + let key = svr_cfg.clone_key(); let method = svr_cfg.method(); - Ok(ServerClient { socket, method, key, }) + Ok(ServerClient { socket, method, key }) } async fn pack_req( diff --git a/src/relay/udprelay/crypto_io.rs b/src/relay/udprelay/crypto_io.rs index 5783a44f..255fd7cb 100644 --- a/src/relay/udprelay/crypto_io.rs +++ b/src/relay/udprelay/crypto_io.rs @@ -19,15 +19,16 @@ //! | Fixed | Variable | Fixed | //! +--------+-----------+-----------+ //! ``` -use crate::context::Context; - -use log::{debug, trace}; -use byte_string::ByteStr; -use bytes::{BufMut, BytesMut}; -use shadowsocks_crypto::v1::{CipherCategory, CipherKind, Cipher, random_iv_or_salt}; - use std::io; +use byte_string::ByteStr; +use bytes::{BufMut, BytesMut}; +use log::{debug, trace}; + +use crate::{ + context::Context, + crypto::v1::{random_iv_or_salt, Cipher, CipherCategory, CipherKind}, +}; /// Encrypt payload into ShadowSocks UDP encrypted packet pub fn encrypt_payload( @@ -42,13 +43,9 @@ pub fn encrypt_payload( // FIXME: Is there a better way to prevent copying? dst.put_slice(payload); Ok(()) - }, - CipherCategory::Stream => { - encrypt_payload_stream(context, method, key, payload, dst) - }, - CipherCategory::Aead => { - encrypt_payload_aead(context, method, key, payload, dst) - }, + } + CipherCategory::Stream => encrypt_payload_stream(context, method, key, payload, dst), + CipherCategory::Aead => encrypt_payload_aead(context, method, key, payload, dst), } } @@ -59,7 +56,7 @@ fn encrypt_payload_stream( payload: &[u8], dst: &mut BytesMut, ) -> io::Result<()> { - let plen = payload.len(); + let plen = payload.len(); let iv_len = method.iv_len(); let mut iv = [0u8; 32]; @@ -75,7 +72,6 @@ fn encrypt_payload_stream( context.check_nonce_and_set(&iv); } - let mut cipher = Cipher::new(method, &key, &iv); trace!("UDP packet generated stream iv {:?}", ByteStr::new(&iv)); @@ -98,7 +94,7 @@ fn encrypt_payload_aead( payload: &[u8], dst: &mut BytesMut, ) -> io::Result<()> { - let plen = payload.len(); + let plen = payload.len(); let salt_len = method.salt_len(); let mut salt = [0u8; 32]; @@ -135,27 +131,32 @@ fn encrypt_payload_aead( Ok(()) } - /// Decrypt payload from ShadowSocks UDP encrypted packet -pub fn decrypt_payload(context: &Context, method: CipherKind, key: &[u8], payload: &[u8]) -> io::Result>> { +pub fn decrypt_payload( + context: &Context, + method: CipherKind, + key: &[u8], + payload: &[u8], +) -> io::Result>> { match method.category() { CipherCategory::None => { // FIXME: Is there a better way to prevent copying? let mut buf = Vec::with_capacity(payload.len()); buf.extend_from_slice(payload); Ok(Some(buf)) - }, - CipherCategory::Stream => { - decrypt_payload_stream(context, method, key, payload) - }, - CipherCategory::Aead => { - decrypt_payload_aead(context, method, key, payload) - }, + } + CipherCategory::Stream => decrypt_payload_stream(context, method, key, payload), + CipherCategory::Aead => decrypt_payload_aead(context, method, key, payload), } } -fn decrypt_payload_stream(context: &Context, method: CipherKind, key: &[u8], payload: &[u8]) -> io::Result>> { - let plen = payload.len(); +fn decrypt_payload_stream( + context: &Context, + method: CipherKind, + key: &[u8], + payload: &[u8], +) -> io::Result>> { + let plen = payload.len(); let iv_len = method.iv_len(); if plen < iv_len { @@ -170,19 +171,24 @@ fn decrypt_payload_stream(context: &Context, method: CipherKind, key: &[u8], pay } let data = &payload[iv_len..]; - + trace!("UDP packet got stream IV {:?}", ByteStr::new(iv)); let mut cipher = Cipher::new(method, key, iv); let mut buf = vec![0u8; data.len()]; buf[..data.len()].copy_from_slice(data); - + assert_eq!(cipher.decrypt_packet(&mut buf), true); - + Ok(Some(buf)) } -fn decrypt_payload_aead(context: &Context, method: CipherKind, key: &[u8], payload: &[u8]) -> io::Result>> { +fn decrypt_payload_aead( + context: &Context, + method: CipherKind, + key: &[u8], + payload: &[u8], +) -> io::Result>> { let salt_len = method.salt_len(); if payload.len() < salt_len { return Ok(None); @@ -206,7 +212,6 @@ fn decrypt_payload_aead(context: &Context, method: CipherKind, key: &[u8], paylo let mut buf = vec![0u8; payload.len()]; buf[..payload.len()].copy_from_slice(payload); - if !cipher.decrypt_packet(&mut buf) { return Err(io::Error::new(io::ErrorKind::Other, "invalid tag-in")); } diff --git a/tests/socks4.rs b/tests/socks4.rs index 623aee81..30dff1cd 100644 --- a/tests/socks4.rs +++ b/tests/socks4.rs @@ -10,10 +10,10 @@ use tokio::{ prelude::*, time::{self, Duration}, }; -use shadowsocks_crypto::v1::CipherKind; use shadowsocks::{ config::{Config, ConfigType, ServerAddr, ServerConfig}, + crypto::v1::CipherKind, relay::socks4::{Address, Command, HandshakeRequest, HandshakeResponse, ResultCode}, run_local, run_server, diff --git a/tests/socks5.rs b/tests/socks5.rs index 25adc3d9..454dc1c9 100644 --- a/tests/socks5.rs +++ b/tests/socks5.rs @@ -7,10 +7,10 @@ use tokio::{ prelude::*, time::{self, Duration}, }; -use shadowsocks_crypto::v1::CipherKind; use shadowsocks::{ config::{Config, ConfigType, Mode, ServerAddr, ServerConfig}, + crypto::v1::CipherKind, relay::{socks5::Address, tcprelay::client::Socks5Client}, run_local, run_server, diff --git a/tests/udp.rs b/tests/udp.rs index 58996219..fcd27284 100644 --- a/tests/udp.rs +++ b/tests/udp.rs @@ -4,10 +4,10 @@ use std::net::SocketAddr; use log::debug; use tokio::time::{self, Duration}; -use shadowsocks_crypto::v1::CipherKind; use shadowsocks::{ config::{Config, ConfigType, Mode, ServerConfig}, + crypto::v1::CipherKind, relay::{socks5::Address, udprelay::client::Socks5Client}, run_local, run_server,