reading client config from socks5 server
This commit is contained in:
parent
bcc79d7c5d
commit
7d395ca825
@ -12,6 +12,7 @@ quinn = { version = "0.9.3", default-features = false, features = ["futures-io",
|
|||||||
register-count = { version = "0.1.0", default-features = false, features = ["std"] }
|
register-count = { version = "0.1.0", default-features = false, features = ["std"] }
|
||||||
serde = { version = "1.0.152", default-features = false, features = ["derive", "std"] }
|
serde = { version = "1.0.152", default-features = false, features = ["derive", "std"] }
|
||||||
serde_json = { version = "1.0.91", default-features = false, features = ["std"] }
|
serde_json = { version = "1.0.91", default-features = false, features = ["std"] }
|
||||||
|
socket2 = { version = "0.4.7", default-features = false }
|
||||||
socks5-proto = { version = "0.3.3", default-features = false }
|
socks5-proto = { version = "0.3.3", default-features = false }
|
||||||
socks5-server = { version = "0.8.3", default-features = false }
|
socks5-server = { version = "0.8.3", default-features = false }
|
||||||
thiserror = { version = "1.0.38", default-features = false }
|
thiserror = { version = "1.0.38", default-features = false }
|
||||||
|
@ -15,4 +15,6 @@ pub enum Error {
|
|||||||
Model(#[from] ModelError),
|
Model(#[from] ModelError),
|
||||||
#[error("timeout")]
|
#[error("timeout")]
|
||||||
Timeout,
|
Timeout,
|
||||||
|
#[error("invalid authentication")]
|
||||||
|
InvalidAuth,
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match Server::set_config(cfg.local).await {
|
match Server::set_config(cfg.local) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{err}");
|
eprintln!("{err}");
|
||||||
|
@ -2,16 +2,17 @@ use crate::{config::Local, connection::Connection as TuicConnection, error::Erro
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use once_cell::sync::{Lazy, OnceCell};
|
use once_cell::sync::{Lazy, OnceCell};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use socket2::{Domain, Protocol, SockAddr, Socket, Type};
|
||||||
use socks5_proto::{Address, Reply};
|
use socks5_proto::{Address, Reply};
|
||||||
use socks5_server::{
|
use socks5_server::{
|
||||||
auth::NoAuth,
|
auth::{NoAuth, Password},
|
||||||
connection::{associate, bind, connect},
|
connection::{associate, bind, connect},
|
||||||
Associate, AssociatedUdpSocket, Bind, Connect, Connection, Server as Socks5Server,
|
Associate, AssociatedUdpSocket, Auth, Bind, Connect, Connection, Server as Socks5Server,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::{Error as IoError, ErrorKind},
|
io::{Error as IoError, ErrorKind},
|
||||||
net::SocketAddr,
|
net::{IpAddr, SocketAddr, TcpListener as StdTcpListener, UdpSocket as StdUdpSocket},
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicU16, Ordering},
|
atomic::{AtomicU16, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
@ -19,7 +20,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{self, AsyncWriteExt},
|
io::{self, AsyncWriteExt},
|
||||||
net::UdpSocket,
|
net::{TcpListener, UdpSocket},
|
||||||
};
|
};
|
||||||
use tokio_util::compat::FuturesAsyncReadCompatExt;
|
use tokio_util::compat::FuturesAsyncReadCompatExt;
|
||||||
use tuic::Address as TuicAddress;
|
use tuic::Address as TuicAddress;
|
||||||
@ -31,16 +32,41 @@ static UDP_SESSIONS: Lazy<Mutex<HashMap<u16, Arc<AssociatedUdpSocket>>>> =
|
|||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
inner: Socks5Server,
|
inner: Socks5Server,
|
||||||
|
addr: SocketAddr,
|
||||||
dual_stack: Option<bool>,
|
dual_stack: Option<bool>,
|
||||||
max_packet_size: usize,
|
max_packet_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
pub async fn set_config(cfg: Local) -> Result<(), Error> {
|
pub fn set_config(cfg: Local) -> Result<(), Error> {
|
||||||
let server = Socks5Server::bind(cfg.server, Arc::new(NoAuth)).await?;
|
let socket = {
|
||||||
|
let domain = match cfg.server.ip() {
|
||||||
|
IpAddr::V4(_) => Domain::IPV4,
|
||||||
|
IpAddr::V6(_) => Domain::IPV6,
|
||||||
|
};
|
||||||
|
|
||||||
|
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
|
||||||
|
|
||||||
|
if let Some(dual_stack) = cfg.dual_stack {
|
||||||
|
socket.set_only_v6(!dual_stack)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.set_reuse_address(true)?;
|
||||||
|
socket.bind(&SockAddr::from(cfg.server))?;
|
||||||
|
TcpListener::from_std(StdTcpListener::from(socket))?
|
||||||
|
};
|
||||||
|
|
||||||
|
let auth: Arc<dyn Auth + Send + Sync> = match (cfg.username, cfg.password) {
|
||||||
|
(Some(username), Some(password)) => {
|
||||||
|
Arc::new(Password::new(username.into_bytes(), password.into_bytes()))
|
||||||
|
}
|
||||||
|
(None, None) => Arc::new(NoAuth),
|
||||||
|
_ => return Err(Error::InvalidAuth),
|
||||||
|
};
|
||||||
|
|
||||||
let server = Self {
|
let server = Self {
|
||||||
inner: server,
|
inner: Socks5Server::new(socket, auth),
|
||||||
|
addr: cfg.server,
|
||||||
dual_stack: cfg.dual_stack,
|
dual_stack: cfg.dual_stack,
|
||||||
max_packet_size: cfg.max_packet_size,
|
max_packet_size: cfg.max_packet_size,
|
||||||
};
|
};
|
||||||
@ -86,15 +112,31 @@ impl Server {
|
|||||||
assoc: Associate<associate::NeedReply>,
|
assoc: Associate<associate::NeedReply>,
|
||||||
_addr: Address,
|
_addr: Address,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let assoc_socket = UdpSocket::bind(SocketAddr::from((assoc.local_addr()?.ip(), 0)))
|
async fn get_assoc_socket() -> Result<(Arc<AssociatedUdpSocket>, SocketAddr), IoError> {
|
||||||
.await
|
let domain = match SERVER.get().unwrap().addr.ip() {
|
||||||
.and_then(|socket| {
|
IpAddr::V4(_) => Domain::IPV4,
|
||||||
socket
|
IpAddr::V6(_) => Domain::IPV6,
|
||||||
.local_addr()
|
};
|
||||||
.map(|addr| (Arc::new(AssociatedUdpSocket::from((socket, 1500))), addr))
|
|
||||||
});
|
|
||||||
|
|
||||||
match assoc_socket {
|
let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))?;
|
||||||
|
|
||||||
|
if let Some(dual_stack) = SERVER.get().unwrap().dual_stack {
|
||||||
|
socket.set_only_v6(!dual_stack)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.set_reuse_address(true)?;
|
||||||
|
socket.bind(&SockAddr::from(SERVER.get().unwrap().addr))?;
|
||||||
|
|
||||||
|
let socket = AssociatedUdpSocket::from((
|
||||||
|
UdpSocket::from_std(StdUdpSocket::from(socket))?,
|
||||||
|
SERVER.get().unwrap().max_packet_size,
|
||||||
|
));
|
||||||
|
|
||||||
|
let addr = socket.local_addr()?;
|
||||||
|
Ok((Arc::new(socket), addr))
|
||||||
|
}
|
||||||
|
|
||||||
|
match get_assoc_socket().await {
|
||||||
Ok((assoc_socket, assoc_addr)) => {
|
Ok((assoc_socket, assoc_addr)) => {
|
||||||
let assoc = assoc
|
let assoc = assoc
|
||||||
.reply(Reply::Succeeded, Address::SocketAddress(assoc_addr))
|
.reply(Reply::Succeeded, Address::SocketAddress(assoc_addr))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user