mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-11-15 08:15:31 +00:00
* Refactored and separate library into crates
- shadowsocks: the core feature of shadowsocks
- shadowsocks-service: library for building shadowsocks services
- dns, http, redir, socks, tunnel
- load balancer
- shadowsocks-rust: release binaries
fix #347
* unified DnsResolver implementation
* unified local service common parameters into ServiceContext
- ServiceContext is common parameters shared between all local
implementations
- Completely removed https local support
* add #292 reply attack protection
* migrated redir local server
* support customizing outbound socket bind address
* manager outbound socket should accepts connect_opts
* republic local implementations
* socks5 udp server should always listen to client address
* socks4 controlled by local-socks4 feature
* socks4 also obey mode configuration
* socks server tcp cannot be disable. add support of udp-bind-addr parameter
* add udp-bind-addr for customizing udp-relay bind-addr
* local-dns infra, support customizing resolver
* fully implements DNS relay server
* support binding to specific interface on Linux-like platform
* tcp cannot be disabled in socks
* enable local-flow-stat
* fixed windows build
* fixed android specific warnings and compile errors
* allow udp_only mode in socks5
* dns relay listens to both TCP and UDP, mode controls outbound upstreams
* dns relay retries twice if request failed
* doc
* fix DnsClient typo
* fix stream EncryptWriter bug
* allow disable logging output
updated dependencies
* add readme
* refine doc
* remove depending on trust-dns-client
* socks4/4a client
* allow socks5 udp_only mode, fixes compile warning
* create standalone socks5 UDP relay server
- socks5 UDP association full cone (NAT2)
* server udp relay supports full cone (NAT2)
* acl moved to crate root
* redir udp relay support full cone (NAT2)
* standard socks5 udp test must use tcp_and_udp mode
* set server context fields with pub APIs
* udp_max_associations and udp_timeout default value set in Config
* local dns resolver retry with fixed attempts
* max_udp_association keeps unlimited by default
* fixed logging binary name
* pops first exited future result for local and server
* update reverse target index cache
* fix ProxyClientStreamWriteHalf that allows sending empty buffers
ref #232
* remove unused import when socks4 is disabled
* make balancer become a globally shared object
* print plugin exit status
* control local, server, manager services in features
112 lines
2.9 KiB
Rust
112 lines
2.9 KiB
Rust
#![cfg_attr(clippy, allow(blacklisted_name))]
|
|
#![cfg(all(feature = "local", feature = "server"))]
|
|
|
|
use std::net::SocketAddr;
|
|
|
|
use log::debug;
|
|
use tokio::time::{self, Duration};
|
|
|
|
use shadowsocks_service::{
|
|
config::{Config, ConfigType, Mode, ProtocolType},
|
|
local::socks::client::socks5::Socks5UdpClient,
|
|
run_local,
|
|
run_server,
|
|
shadowsocks::{crypto::v1::CipherKind, relay::socks5::Address, ServerConfig},
|
|
};
|
|
|
|
const SERVER_ADDR: &str = "127.0.0.1:8093";
|
|
const LOCAL_ADDR: &str = "127.0.0.1:8291";
|
|
|
|
const UDP_ECHO_SERVER_ADDR: &str = "127.0.0.1:50403";
|
|
|
|
const PASSWORD: &str = "test-password";
|
|
const METHOD: CipherKind = CipherKind::AES_128_GCM;
|
|
|
|
fn get_svr_config() -> Config {
|
|
let mut cfg = Config::new(ConfigType::Server);
|
|
cfg.server = vec![ServerConfig::new(
|
|
SERVER_ADDR.parse::<SocketAddr>().unwrap(),
|
|
PASSWORD.to_owned(),
|
|
METHOD,
|
|
)];
|
|
cfg.mode = Mode::TcpAndUdp;
|
|
cfg
|
|
}
|
|
|
|
fn get_cli_config() -> Config {
|
|
let mut cfg = Config::new(ConfigType::Local);
|
|
cfg.local_addr = Some(LOCAL_ADDR.parse().unwrap());
|
|
cfg.server = vec![ServerConfig::new(
|
|
SERVER_ADDR.parse::<SocketAddr>().unwrap(),
|
|
PASSWORD.to_owned(),
|
|
METHOD,
|
|
)];
|
|
cfg.mode = Mode::TcpAndUdp;
|
|
cfg.local_protocol = ProtocolType::Socks;
|
|
cfg
|
|
}
|
|
|
|
fn get_client_addr() -> SocketAddr {
|
|
LOCAL_ADDR.parse().unwrap()
|
|
}
|
|
|
|
fn start_server() {
|
|
tokio::spawn(run_server(get_svr_config()));
|
|
}
|
|
|
|
fn start_local() {
|
|
tokio::spawn(run_local(get_cli_config()));
|
|
}
|
|
|
|
fn start_udp_echo_server() {
|
|
use tokio::net::UdpSocket;
|
|
|
|
tokio::spawn(async {
|
|
let l = UdpSocket::bind(UDP_ECHO_SERVER_ADDR).await.unwrap();
|
|
|
|
debug!("UDP echo server started {}", UDP_ECHO_SERVER_ADDR);
|
|
|
|
let mut buf = vec![0u8; 65536];
|
|
let (amt, src) = l.recv_from(&mut buf).await.unwrap();
|
|
|
|
debug!("UDP echo received {} bytes from {}", amt, src);
|
|
|
|
l.send_to(&buf[..amt], &src).await.unwrap();
|
|
|
|
debug!("UDP echo sent {} bytes to {}", amt, src);
|
|
});
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn udp_relay() {
|
|
let _ = env_logger::try_init();
|
|
|
|
let remote_addr = Address::SocketAddress(UDP_ECHO_SERVER_ADDR.parse().unwrap());
|
|
|
|
start_server();
|
|
start_local();
|
|
|
|
start_udp_echo_server();
|
|
|
|
// Wait until all server starts
|
|
time::sleep(Duration::from_secs(1)).await;
|
|
|
|
let mut l = Socks5UdpClient::bind("127.0.0.1:0".parse::<SocketAddr>().unwrap())
|
|
.await
|
|
.unwrap();
|
|
l.associate(&get_client_addr()).await.unwrap();
|
|
|
|
let payload = b"HEllo WORld";
|
|
l.send_to(0, payload, &remote_addr).await.unwrap();
|
|
|
|
let mut buf = vec![0u8; 65536];
|
|
let (amt, _, recv_addr) = time::timeout(Duration::from_secs(5), l.recv_from(&mut buf))
|
|
.await
|
|
.unwrap()
|
|
.unwrap();
|
|
println!("Received {} buf size={} {:?}", recv_addr, amt, &buf[..amt]);
|
|
|
|
assert_eq!(recv_addr, remote_addr);
|
|
assert_eq!(&buf[..amt], payload);
|
|
}
|