https://github.com/nashaofu/rusocks
A socks4(a)/5 server
https://github.com/nashaofu/rusocks
socks socks4 socks4a socks5
Last synced: 3 months ago
JSON representation
A socks4(a)/5 server
- Host: GitHub
- URL: https://github.com/nashaofu/rusocks
- Owner: nashaofu
- License: apache-2.0
- Created: 2024-11-01T14:47:39.000Z (11 months ago)
- Default Branch: master
- Last Pushed: 2024-11-10T03:38:55.000Z (11 months ago)
- Last Synced: 2025-06-29T01:07:53.445Z (3 months ago)
- Topics: socks, socks4, socks4a, socks5
- Language: Rust
- Homepage: https://crates.io/crates/rusocks
- Size: 46.9 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# rusocks
A socks4(a)/5 server
## features:
- socks4/4a protocol
- [x] connect
- [x] bind- socks5 protocol
- [x] no authentication
- [x] username/password- socks5 command
- [x] connect
- [x] bind
- [ ] udp associate## example
```rust
use std::net::SocketAddr;use async_trait::async_trait;
use rusocks::{
address::Address,
error::Error,
socks4::{reply::Socks4Reply, request::Socks4Request, Socks4Handler},
socks5::{method::Socks5Method, reply::Socks5Reply, request::Socks5Request, Socks5Handler},
Socks,
};
use tokio::{
io::{self, AsyncReadExt, AsyncWriteExt},
net::{TcpListener, TcpStream},
select, time,
};#[tokio::main]
async fn main() {
// curl -x socks4://127.0.0.1:1080 http://127.0.0.1:8080
// curl -x socks5://127.0.0.1:1080 http://127.0.0.1:8080
let listener = TcpListener::bind("127.0.0.1:1080").await.unwrap();while let Ok((mut stream, _)) = listener.accept().await {
tokio::spawn(async move {
let peer_addr = stream.peer_addr().unwrap();
let local_addr = stream.local_addr().unwrap();let handler = Handler {};
let mut socks = Socks::from_stream(&mut stream, peer_addr, local_addr, handler)
.await
.unwrap();match socks.accept(&mut stream).await {
Ok(_) => {
println!("success");
}
Err(e) => {
println!("error: {}", e);
}
}
});
}
}struct Handler {}
#[async_trait]
impl Socks4Handler for Handler {
type ConnectStream = TcpStream;async fn connect(&self, address: &Address) -> Result<(Self::ConnectStream, SocketAddr), Error> {
let stream = TcpStream::connect((address.domain(), address.port())).await?;
let bind_addr = stream.local_addr()?;Ok((stream, bind_addr))
}async fn bind(
&self,
request: &mut Socks4Request,
bind_addr: &Address,
) -> Result<(), Error>
where
S: AsyncReadExt + AsyncWriteExt + Unpin + Send,
{
let listener = TcpListener::bind((bind_addr.domain(), bind_addr.port())).await?;
let bind_addr = listener.local_addr()?.clone();
request.reply(Socks4Reply::Granted, bind_addr).await?;let (mut connect, peer_addr) = listener.accept().await?;
// 异步处理连接
println!("Accepted connection from {:?}", peer_addr);
io::copy_bidirectional(&mut request.stream, &mut connect)
.await
.unwrap();Ok(())
}
}#[async_trait]
impl Socks5Handler for Handler {
type ConnectStream = TcpStream;async fn negotiate_method(&self, _methods: &[Socks5Method]) -> Result {
Ok(Socks5Method::None)
}async fn auth_by_user_pass(&self, username: &str, password: &str) -> Result {
println!("username: {}, password: {}", username, password);
Ok(false)
}async fn connect(&self, address: &Address) -> Result<(Self::ConnectStream, SocketAddr), Error> {
let stream = TcpStream::connect((address.domain(), address.port())).await?;
let bind_addr = stream.local_addr()?;Ok((stream, bind_addr))
}async fn bind(
&self,
request: &mut Socks5Request,
bind_addr: &Address,
) -> Result<(), Error>
where
S: AsyncReadExt + AsyncWriteExt + Unpin + Send,
{
let listener = TcpListener::bind((bind_addr.domain(), bind_addr.port())).await?;
let bind_addr = listener.local_addr()?.clone();request.reply(Socks5Reply::Succeeded, bind_addr).await?;
select! {
// 超时关闭
_ = time::sleep(time::Duration::from_secs(20)) => {
println!("Shutdown signal received. Stopping the listener...");
return Ok(());
}
Ok((mut connect, peer_addr)) = listener.accept() => {
println!("Accepted connection from {:?}", peer_addr);
request.reply(Socks5Reply::Succeeded, peer_addr).await?;
io::copy_bidirectional(&mut request.stream, &mut connect).await?;
}
}Ok(())
}
}
```