Former-commit-id: 2c8d8ac3845be86db0032025a127865f1f6d4ee7 [formerly 7550a9453455a95cb7583d582b5ac36d5a2c4e85] [formerly 39ce55e6191ae0f82e97708165be5fb27bffad51 [formerly e6c8f9d061578f0aad10fd974fb30bba6fb980d2]]
Former-commit-id: 29b3ac95435e35e66a93aada96692dde1d5d6213 [formerly afaaf09642072cec135a9fe451510be3ec2196e1]
Former-commit-id: 6ea160887038963bc34a6fb0b93baa318286f068
Former-commit-id: 40d8cad8790877c1d0712dfcd828939f4585dd38
Former-commit-id: a3de18cc4ac432e9aac64c30b05fc86f6fcf6b42
Former-commit-id: 7193a47d510ecd22b43a001b8b128b24643f6e42 [formerly 5a0575a31f03fe2754ed3a2c784f6181bc654456]
Former-commit-id: 9aef01bbe49921a4e0cc3eda2ecf929e476eacff
This commit is contained in:
Σrebe - Romain GERARD 2023-10-16 19:26:32 +02:00
parent ef112495ae
commit a15e8a2548
5 changed files with 169 additions and 12 deletions

View file

@ -1,4 +1,5 @@
mod embedded_certificate;
mod socks5;
#[cfg(target_family = "unix")]
mod stdio;
mod tcp;

101
src/socks5.rs Normal file
View file

@ -0,0 +1,101 @@
use anyhow::Context;
use fast_socks5::server::{Config, DenyAuthentication, Socks5Server};
use fast_socks5::util::target_addr::TargetAddr;
use futures_util::{stream, Stream, StreamExt};
use std::net::SocketAddr;
use std::pin::Pin;
use std::task::Poll;
use tokio::net::TcpStream;
use log::warn;
use tracing::{info, warn};
use url::Host;
pub struct Socks5Listener {
stream: Pin<Box<dyn Stream<Item = anyhow::Result<(TcpStream, Host, u16)>>>>,
}
impl Stream for Socks5Listener {
type Item = anyhow::Result<(TcpStream, Host, u16)>;
fn poll_next(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Option<Self::Item>> {
unsafe { self.map_unchecked_mut(|x| &mut x.stream) }.poll_next(cx)
}
}
pub async fn run_server(bind: SocketAddr) -> Result<Socks5Listener, anyhow::Error> {
info!("Starting TCP server listening cnx on {}", bind);
let server = Socks5Server::<DenyAuthentication>::bind(bind)
.await
.with_context(|| format!("Cannot create socks5 server {:?}", bind))?;
let mut cfg = Config::<DenyAuthentication>::default();
cfg.set_allow_no_auth(true);
cfg.set_dns_resolve(false);
cfg.set_execute_command(false);
let server = server.with_config(cfg);
let stream = stream::unfold(server, move |server| async {
let mut acceptor = server.incoming();
loop {
let cnx = match acceptor.next().await {
None => return None,
Some(Err(err)) => {
drop(acceptor);
return Some((Err(anyhow::Error::new(err)), server));
}
Some(Ok(cnx)) => cnx,
};
let cnx = match cnx.upgrade_to_socks5().await {
Ok(cnx) => cnx,
Err(err) => {
warn!("Rejecting socks5 cnx: {}", err);
continue;
}
};
let Some(target) = cnx.target_addr() else {
warn!("Rejecting socks5 cnx: no target addr");
continue;
};
let (host, port) = match target {
TargetAddr::Ip(SocketAddr::V4(ip)) => (Host::Ipv4(*ip.ip()), ip.port()),
TargetAddr::Ip(SocketAddr::V6(ip)) => (Host::Ipv6(*ip.ip()), ip.port()),
TargetAddr::Domain(host, port) => (Host::Domain(host.clone()), *port),
};
drop(acceptor);
return Some((Ok((cnx.into_inner(), host, port)), server));
}
});
let listener = Socks5Listener {
stream: Box::pin(stream),
};
Ok(listener)
}
#[cfg(test)]
mod test {
use super::*;
use futures_util::StreamExt;
use std::str::FromStr;
#[tokio::test]
async fn socks5_server() {
let mut x = run_server(SocketAddr::from_str("[::]:4343").unwrap())
.await
.unwrap();
loop {
let cnx = x.next().await.unwrap().unwrap();
eprintln!("{:?}", cnx);
}
}
}

View file

@ -10,7 +10,7 @@ use anyhow::Context;
use fastwebsockets::{
Frame, OpCode, Payload, WebSocket, WebSocketError, WebSocketRead, WebSocketWrite,
};
use futures_util::{pin_mut};
use futures_util::pin_mut;
use hyper::header::{AUTHORIZATION, SEC_WEBSOCKET_VERSION, UPGRADE};
use hyper::header::{CONNECTION, HOST, SEC_WEBSOCKET_KEY};
use hyper::server::conn::Http;