Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
ylxdzsw committed Oct 30, 2021
1 parent 29cca11 commit 1bd1aa0
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 42 deletions.
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "v2socks"
version = "0.2.2"
version = "0.2.3"
authors = ["ylxdzsw <[email protected]>"]
edition = "2018"

Expand All @@ -9,6 +9,7 @@ panic = "abort"
lto = true

[dependencies]
oh-my-rust = { git = "https://github.com/ylxdzsw/oh-my-rust" }
oh-my-rust = { git = "https://github.com/ylxdzsw/oh-my-rust", default-features = false, features = ["std"]}
rust-crypto = "0.2"
rand = "0.7"
rand = "0.8"
anyhow = "1.0"
2 changes: 1 addition & 1 deletion PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pkgname=v2socks
pkgdesc="An opinioned lightweight socks5 server and vmess (v2ray) client."
pkgrel=1
pkgver=0.2.1
pkgver=0.2.3
arch=(any)
url='https://github.com/ylxdzsw/v2socks'
license=(GPL3)
Expand Down
9 changes: 1 addition & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
#![allow(irrefutable_let_patterns)]
#![allow(dead_code, unused_imports)]
#![allow(non_camel_case_types)]
#![deny(bare_trait_objects)]
#![warn(clippy::all)]

mod socks;
mod vmess;

use oh_my_rust::*;
pub use socks::*;
pub use vmess::*;

Expand All @@ -23,7 +16,7 @@ impl std::fmt::Display for Addr {
match self {
Addr::V4(x) => std::fmt::Display::fmt(&std::net::Ipv4Addr::from(*x), fmt),
Addr::V6(x) => std::fmt::Display::fmt(&std::net::Ipv6Addr::from(*x), fmt),
Addr::Domain(x) => std::fmt::Display::fmt(std::str::from_utf8(x).msg(std::fmt::Error)?, fmt)
Addr::Domain(x) => std::fmt::Display::fmt(std::str::from_utf8(x).map_err(|_| std::fmt::Error)?, fmt)
}
}
}
17 changes: 7 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::io::prelude::*;

// todo: use thread pool or async io

const USAGE: &'static str = "
const USAGE: &str = "
Usage: v2socks plain [local_port=1080]
v2socks vmess <server_addr>:<server_port> <userid> [local_port=1080]
";
Expand Down Expand Up @@ -40,14 +40,11 @@ fn parse_uid(x: &str) -> Option<[u8; 16]> {
}

fn is_normal_close(e: &std::io::Error) -> bool {
match e.kind() {
std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::UnexpectedEof | std::io::ErrorKind::ConnectionReset => true,
_ => false
}
matches!(e.kind(), std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::UnexpectedEof | std::io::ErrorKind::ConnectionReset)
}

fn vmess(server: &Socks5Server, proxy: String, user_id: [u8; 16]) {
let connect = leak(move |dest, port| {
let connect = move |dest, port| {
let client = std::net::TcpStream::connect(&proxy)?;
debug!("connect {}:{} through proxy", &dest, port);

Expand All @@ -59,10 +56,10 @@ fn vmess(server: &Socks5Server, proxy: String, user_id: [u8; 16]) {
let local_port = local.port();

Ok((local_addr, local_port, (dest, port, client)))
});
};

#[allow(non_snake_case)]
let pass = leak(move |(dest, port, conn): (Addr, u16, std::net::TcpStream), mut stream: std::net::TcpStream| {
let pass = move |(dest, port, conn): (Addr, u16, std::net::TcpStream), mut stream: std::net::TcpStream| {
let key = [0; 16].apply(|x| thread_rng().fill_bytes(x));
let IV = [0; 16].apply(|x| thread_rng().fill_bytes(x));

Expand Down Expand Up @@ -117,9 +114,9 @@ fn vmess(server: &Socks5Server, proxy: String, user_id: [u8; 16]) {

writer.close();
debug!("closed writing");
});
};

server.listen(connect, pass)
server.listen(connect.box_and_leak(), pass.box_and_leak())
}

fn plain(server: &Socks5Server) {
Expand Down
41 changes: 21 additions & 20 deletions src/socks.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use super::*;
use oh_my_rust::*;
use anyhow::{Context, Result, anyhow};
use std::net::{TcpListener, TcpStream};
use std::io::{prelude::*, BufRead, BufReader};
use std::io::prelude::*;

macro_rules! read_exact {
($stream: expr, $array: expr) => {{
Expand Down Expand Up @@ -49,53 +50,53 @@ impl Socks5Server {
}
}

fn initialize(stream: &mut (impl ReadExt + Write)) -> Result<(), String> {
let header = read_exact!(stream, [0, 0]).msg("read initial bits failed")?;
fn initialize(stream: &mut (impl ReadExt + Write)) -> Result<()> {
let header = read_exact!(stream, [0, 0]).context("read initial bits failed")?;

if header[0] != 5 {
let hint = "if the version is 71, the software probabily used it as an HTTP proxy";
return Err(format!("unsupported socks version {}. Hint: {}", header[0], hint))
return Err(anyhow!("unsupported socks version {}. Hint: {}", header[0], hint))
}

let list: Vec<u8> = stream.read_exact_alloc(header[1] as usize).msg("read methods failed")?;
let list: Vec<u8> = stream.read_exact_alloc(header[1] as usize).context("read methods failed")?;

if !list.contains(&0) {
stream.write(&[5, 0xff]).msg("write response failed")?;
return Err("client do not support NO AUTH method".to_string())
stream.write(&[5, 0xff]).context("write response failed")?;
return Err(anyhow!("client do not support NO AUTH method"))
}

stream.write(&[5, 0]).msg("write response failed")?;
stream.write(&[5, 0]).context("write response failed")?;
Ok(())
}

fn read_request(stream: &mut (impl ReadExt + Write)) -> Result<(Addr, u16), String> {
let [ver, cmd, _rev, atyp] = read_exact!(stream, [0; 4]).msg("read request header failed")?;
fn read_request(stream: &mut (impl ReadExt + Write)) -> Result<(Addr, u16)> {
let [ver, cmd, _rev, atyp] = read_exact!(stream, [0; 4]).context("read request header failed")?;

if ver != 5 {
return Err(format!("unsupported socks version {}", ver))
return Err(anyhow!("unsupported socks version {}", ver))
}

if cmd != 1 {
return Err(format!("unsupported command type {}", cmd))
return Err(anyhow!("unsupported command type {}", cmd))
}

let addr = match atyp {
0x01 => Addr::V4(read_exact!(stream, [0; 4]).msg("read v4 address failed")?),
0x04 => Addr::V6(read_exact!(stream, [0; 16]).msg("read v6 address failed")?),
0x01 => Addr::V4(read_exact!(stream, [0; 4]).context("read v4 address failed")?),
0x04 => Addr::V6(read_exact!(stream, [0; 16]).context("read v6 address failed")?),
0x03 => {
let len = read_exact!(stream, [0]).msg("read domain length failed")?[0];
Addr::Domain(stream.read_exact_alloc(len as usize).msg("read domain failed")?.into_boxed_slice())
let len = read_exact!(stream, [0]).context("read domain length failed")?[0];
Addr::Domain(stream.read_exact_alloc(len as usize).context("read domain failed")?.into_boxed_slice())
},
_ => return Err("unknown ATYP".to_string())
_ => return Err(anyhow!("unknown ATYP"))
};

let port = read_exact!(stream, [0; 2]).msg("read port failed")?;
let port = read_exact!(stream, [0; 2]).context("read port failed")?;
let port = (port[0] as u16) << 8 | port[1] as u16;

Ok((addr, port))
}

fn reply_request(stream: &mut (impl ReadExt + Write), addr: Addr, port: u16) -> Result<(), String> {
fn reply_request(stream: &mut (impl ReadExt + Write), addr: Addr, port: u16) -> Result<()> {
let mut reply = Vec::with_capacity(22); // cover V4 and V6
reply.extend_from_slice(&[5, 0, 0]);

Expand All @@ -118,7 +119,7 @@ fn reply_request(stream: &mut (impl ReadExt + Write), addr: Addr, port: u16) ->
reply.push((port >> 8) as u8);
reply.push(port as u8);

stream.write(&reply).msg("write reply failed")?;
stream.write(&reply).context("write reply failed")?;

Ok(())
}
Expand Down

0 comments on commit 1bd1aa0

Please sign in to comment.