mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-02-09 01:59:16 +08:00
updated readme, appveyor and remove unused tool
This commit is contained in:
@@ -35,11 +35,6 @@ path = "src/bin/local.rs"
|
||||
name = "ssserver"
|
||||
path = "src/bin/server.rs"
|
||||
|
||||
#[[bin]]
|
||||
#
|
||||
#name = "socks5-tool"
|
||||
#path = "src/bin/socks5-tool.rs"
|
||||
|
||||
[[bin]]
|
||||
|
||||
name = "ssurl"
|
||||
|
||||
22
README.md
22
README.md
@@ -13,8 +13,6 @@ It is **unstable**! If you encounter any problems, please open an issue.
|
||||
## Dependencies
|
||||
|
||||
* libcrypto (OpenSSL)
|
||||
* Rust nightly
|
||||
* Cargo
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -87,7 +85,7 @@ In shadowsocks-rust, we also have an extended configuration file format, which i
|
||||
|
||||
The `sslocal` will use a load balancing algorithm to dispatch packages to all servers.
|
||||
|
||||
Start local and server shadowsocks with
|
||||
Start local and server ShadowSocks with
|
||||
|
||||
```
|
||||
cargo run --bin sslocal -- -c config.json
|
||||
@@ -98,23 +96,23 @@ List all available arguments with `-h`.
|
||||
|
||||
## Useful Tools
|
||||
|
||||
1. `socks5-tool` is to demonstrate how to write a Socks5 client.
|
||||
|
||||
2. `ssurl` is for encoding and decoding ShadowSocks URLs. Example: `ss://YWVzLTI1Ni1jZmI6aGVsbG93b3JsZF9mdWNrQDEyNy4wLjAuMTo4Mzg4`
|
||||
1. `ssurl` is for encoding and decoding ShadowSocks URLs. Example: `ss://YWVzLTI1Ni1jZmI6aGVsbG93b3JsZF9mdWNrQDEyNy4wLjAuMTo4Mzg4`
|
||||
|
||||
## Notes
|
||||
|
||||
It supports the following features:
|
||||
|
||||
* CONNECT, UDP ASSOCIATE commands
|
||||
* Crypto algorithms defined in `Cargo.toml`
|
||||
* **Load balancing**
|
||||
- [x] Socks5 CONNECT command
|
||||
- [ ] UDP ASSOCIATE command
|
||||
- [x] HTTP Proxy protocol
|
||||
- [x] Various crypto algorithms
|
||||
- [x] Load balancing (multiple servers)
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] Documentation
|
||||
- [ ] <del>`BIND` command</del>
|
||||
- [ ] Socks5 authentication
|
||||
- [ ] <del>Socks5 authentication</del>
|
||||
- [x] Extend configuration format
|
||||
- [ ] Fully testing on servers
|
||||
- [ ] Performance testing and improvement
|
||||
@@ -122,8 +120,8 @@ It supports the following features:
|
||||
- [ ] <del>PAC</del>
|
||||
- [x] Improved logging format (waiting for the new official log crate)
|
||||
- [ ] Support more ciphers without depending on `libcrypto` (waiting for an acceptable Rust crypto lib implementation)
|
||||
- [ ] Windows support. (Depending on mio and coio-rs)
|
||||
- [ ] Build with stable. (Depending on coio)
|
||||
- [x] Windows support. <del>(Depending on mio and coio-rs)</del>
|
||||
- [x] Build with stable. <del>(Depending on coio)</del>
|
||||
- [x] Support HTTP Proxy protocol
|
||||
|
||||
## License
|
||||
|
||||
@@ -7,12 +7,14 @@ environment:
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
BITS: 64
|
||||
OPENSSL_VERSION: 1_1_0b
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
BITS: 32
|
||||
OPENSSL_VERSION: 1_1_0b
|
||||
MSYS2: 1
|
||||
# - TARGET: i686-pc-windows-msvc
|
||||
# BITS: 32
|
||||
# OPENSSL_VERSION: 1_1_0b
|
||||
- TARGET: i686-pc-windows-gnu
|
||||
BITS: 32
|
||||
OPENSSL_VERSION: 1_1_0b
|
||||
MSYS2: 1
|
||||
install:
|
||||
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-${env:OPENSSL_VERSION}.exe"
|
||||
- Win%BITS%OpenSSL-%OPENSSL_VERSION%.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
#![feature(lookup_host)]
|
||||
|
||||
extern crate clap;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate shadowsocks;
|
||||
extern crate ip;
|
||||
|
||||
use clap::{App, Arg};
|
||||
|
||||
use std::net::UdpSocket;
|
||||
use std::net::TcpStream;
|
||||
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
use std::net::lookup_host;
|
||||
use std::io::Cursor;
|
||||
use std::io::stdout;
|
||||
use std::io::{self, Write};
|
||||
|
||||
use ip::IpAddr;
|
||||
|
||||
use shadowsocks::relay::socks5::*;
|
||||
|
||||
fn do_tcp(svr_addr: &Address, proxy_addr: &SocketAddr, msg: &str) {
|
||||
let mut proxy_stream = TcpStream::connect(proxy_addr).unwrap();
|
||||
|
||||
let shake_req = HandshakeRequest::new(vec![0x00]);
|
||||
shake_req.write_to(&mut proxy_stream).unwrap();
|
||||
let shake_resp = HandshakeResponse::read_from(&mut proxy_stream).unwrap();
|
||||
|
||||
if shake_resp.chosen_method != 0x00 {
|
||||
panic!("Proxy server needs authentication");
|
||||
}
|
||||
|
||||
let req_header = TcpRequestHeader::new(Command::TcpConnect, svr_addr.clone());
|
||||
req_header.write_to(&mut proxy_stream).unwrap();
|
||||
proxy_stream.write(msg.as_bytes()).unwrap();
|
||||
|
||||
let resp_header = TcpResponseHeader::read_from(&mut proxy_stream).unwrap();
|
||||
match resp_header.reply {
|
||||
Reply::Succeeded => {}
|
||||
_ => {
|
||||
panic!("Failed with error {:?}", resp_header.reply);
|
||||
}
|
||||
}
|
||||
|
||||
io::copy(&mut proxy_stream, &mut stdout()).unwrap();
|
||||
}
|
||||
|
||||
fn do_udp(svr_addr: &Address, proxy_addr: &SocketAddr, local_addr: &SocketAddr, msg: &str) {
|
||||
let udp_proxy_addr = {
|
||||
let mut proxy_stream = TcpStream::connect(proxy_addr).unwrap();
|
||||
|
||||
let shake_req = HandshakeRequest::new(vec![0x00]);
|
||||
shake_req.write_to(&mut proxy_stream).unwrap();
|
||||
let shake_resp = HandshakeResponse::read_from(&mut proxy_stream).unwrap();
|
||||
|
||||
if shake_resp.chosen_method != 0x00 {
|
||||
panic!("Proxy server needs authentication");
|
||||
}
|
||||
|
||||
let req_header = TcpRequestHeader::new(Command::UdpAssociate, svr_addr.clone());
|
||||
req_header.write_to(&mut proxy_stream).unwrap();
|
||||
|
||||
let resp_header = TcpResponseHeader::read_from(&mut proxy_stream).unwrap();
|
||||
match resp_header.reply {
|
||||
Reply::Succeeded => {}
|
||||
_ => {
|
||||
panic!("Failed with error {:?}", resp_header.reply);
|
||||
}
|
||||
}
|
||||
|
||||
resp_header.address
|
||||
};
|
||||
|
||||
let udp_socket = UdpSocket::bind(local_addr).unwrap();
|
||||
|
||||
let proxy_real_addr = match udp_proxy_addr {
|
||||
Address::SocketAddress(sock) => sock,
|
||||
Address::DomainNameAddress(dm, port) => {
|
||||
let host = match lookup_host(&dm) {
|
||||
Ok(mut hosts) => {
|
||||
match hosts.next() {
|
||||
Some(h) => h,
|
||||
None => panic!("No hosts could be found by {:?}", dm),
|
||||
}
|
||||
}
|
||||
Err(err) => panic!("LookupHost: {:?}", err),
|
||||
};
|
||||
|
||||
match host {
|
||||
SocketAddr::V4(v4) => SocketAddr::V4(SocketAddrV4::new(*v4.ip(), port)),
|
||||
SocketAddr::V6(v6) => {
|
||||
SocketAddr::V6(SocketAddrV6::new(*v6.ip(), port, v6.flowinfo(), v6.scope_id()))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut bufw = Vec::new();
|
||||
let udp_header = UdpAssociateHeader::new(0, svr_addr.clone());
|
||||
udp_header.write_to(&mut bufw).unwrap();
|
||||
bufw.write(msg.as_bytes()).unwrap();
|
||||
udp_socket.send_to(&bufw, proxy_real_addr).unwrap();
|
||||
|
||||
let mut buf = [0; 0xffff];
|
||||
let (len, _) = udp_socket.recv_from(&mut buf).unwrap();
|
||||
println!("Got buf: {:?}", &buf[..len]);
|
||||
|
||||
let mut bufr = Cursor::new(&buf[..len]);
|
||||
let _ = UdpAssociateHeader::read_from(&mut bufr).unwrap();
|
||||
|
||||
io::copy(&mut bufr, &mut stdout()).unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let matches = App::new("socks5-tool")
|
||||
.author("Y. T. Chung <zonyitoo@gmail.com>")
|
||||
.about("Socks5 protocol test tool")
|
||||
.arg(Arg::with_name("SERVER_ADDR")
|
||||
.short("s")
|
||||
.long("server-addr")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("Server address"))
|
||||
.arg(Arg::with_name("SERVER_PORT")
|
||||
.short("p")
|
||||
.long("server-port")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("Server port"))
|
||||
.arg(Arg::with_name("PROXY_ADDR")
|
||||
.short("x")
|
||||
.long("proxy-addr")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("Proxy address"))
|
||||
.arg(Arg::with_name("LOCAL_ADDR")
|
||||
.short("b")
|
||||
.long("local-addr")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.help("Local address"))
|
||||
.arg(Arg::with_name("PROTOCOL")
|
||||
.short("t")
|
||||
.long("protocol")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("Protocol to use"))
|
||||
.arg(Arg::with_name("MESSAGE")
|
||||
.short("m")
|
||||
.long("message")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("Message to be sent"))
|
||||
.get_matches();
|
||||
|
||||
let is_tcp = match matches.value_of("PROTOCOL").unwrap() {
|
||||
"tcp" => true,
|
||||
"udp" => false,
|
||||
protocol => panic!("Unsupported protocol {:?}", protocol),
|
||||
};
|
||||
|
||||
let proxy_addr: SocketAddr = matches.value_of("PROXY_ADDR").unwrap().parse().unwrap();
|
||||
|
||||
let svr_port: u16 = matches.value_of("SERVER_PORT").unwrap().parse().unwrap();
|
||||
let svr_addr_str = matches.value_of("SERVER_ADDR").unwrap();
|
||||
let svr_addr = match svr_addr_str.parse::<IpAddr>() {
|
||||
Ok(ip) => {
|
||||
let addr = match ip {
|
||||
IpAddr::V4(v4) => SocketAddr::V4(SocketAddrV4::new(v4, svr_port)),
|
||||
IpAddr::V6(v6) => SocketAddr::V6(SocketAddrV6::new(v6, svr_port, 0, 0)),
|
||||
};
|
||||
|
||||
Address::SocketAddress(addr)
|
||||
}
|
||||
Err(..) => Address::DomainNameAddress(svr_addr_str.to_owned(), svr_port),
|
||||
};
|
||||
|
||||
let msg = matches.value_of("MESSAGE").unwrap();
|
||||
|
||||
if is_tcp {
|
||||
do_tcp(&svr_addr, &proxy_addr, msg);
|
||||
} else {
|
||||
let local_addr: SocketAddr = matches.value_of("LOCAL_ADDR").unwrap().parse().unwrap();
|
||||
do_udp(&svr_addr, &proxy_addr, &local_addr, msg);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user