### Bash Command Line Examples for Fast Socks5 Server and Client Source: https://context7.com/dizda/fast-socks5/llms.txt Provides bash commands to test the Fast Socks5 library. It includes examples for starting a SOCKS5 server with and without authentication, enabling UDP support, and testing connectivity using cURL and the built-in client examples. Requires Rust and Cargo to be installed. ```bash # Start a SOCKS5 server without authentication RUST_LOG=debug cargo run --example server -- --listen-addr 127.0.0.1:1080 no-auth # Start a server with password authentication RUST_LOG=debug cargo run --example server -- \ --listen-addr 127.0.0.1:1080 \ password --username admin --password secret # Start a server with UDP support RUST_LOG=debug cargo run --example server -- \ --listen-addr 127.0.0.1:1080 \ --allow-udp \ --public-addr 127.0.0.1 \ password --username admin --password secret # Test with cURL (no auth) curl -v --proxy socks5://127.0.0.1:1080 https://httpbin.org/ip # Test with cURL (with auth) curl -v --proxy socks5://admin:secret@127.0.0.1:1080 https://httpbin.org/ip # Use the built-in client example RUST_LOG=debug cargo run --example client -- \ --socks-server 127.0.0.1:1080 \ --username admin \ --password secret \ -a httpbin.org \ -p 80 # UDP client example (DNS query through proxy) RUST_LOG=debug cargo run --example udp_client -- \ --socks-server 127.0.0.1:1080 \ --username admin \ --password secret \ -a 8.8.8.8 \ -d github.com ``` -------------------------------- ### Create SOCKS5 Server With Password Authentication (Rust) Source: https://context7.com/dizda/fast-socks5/llms.txt This example demonstrates setting up a SOCKS5 server that requires username and password authentication. It uses `Socks5ServerProtocol::accept_password_auth`, providing a closure to validate credentials. The server then proceeds to handle TCP connect commands after successful authentication. ```rust use fast_socks5::server::{run_tcp_proxy, DnsResolveHelper, Socks5ServerProtocol}; use fast_socks5::{ReplyError, Result, Socks5Command, SocksError}; use std::time::Duration; use tokio::net::TcpListener; #[tokio::main] async fn main() -> Result<()> { let listener = TcpListener::bind("127.0.0.1:1080").await?; loop { let (socket, _) = listener.accept().await?; tokio::spawn(async move { // Authenticate with closure that validates credentials let (proto, auth_result) = Socks5ServerProtocol::accept_password_auth( socket, |username, password| { // Return true/false, Option, or Result if username == "admin" && password == "secret123" { Some(username) // Return authenticated username } else { None // Reject authentication } }, ).await?; println!("Authenticated user: {:?}", auth_result); let (proto, cmd, target_addr) = proto .read_command() .await? .resolve_dns() .await?; if cmd == Socks5Command::TCPConnect { run_tcp_proxy(proto, &target_addr, Duration::from_secs(10), false).await?; } else { proto.reply_error(&ReplyError::CommandNotSupported).await?; } Ok::<_, SocksError>(()) }); } } ``` -------------------------------- ### Connect to TCP server with username/password authentication Source: https://context7.com/dizda/fast-socks5/llms.txt Demonstrates connecting through a SOCKS5 proxy requiring authentication using connect_with_password. This example also shows how to configure connection timeouts and access the underlying socket. ```rust use fast_socks5::client::{Config, Socks5Stream}; use fast_socks5::Result; use std::time::Duration; use tokio::io::{AsyncReadExt, AsyncWriteExt}; #[tokio::main] async fn main() -> Result<()> { let mut config = Config::default(); config.set_connect_timeout(Duration::from_secs(10)); let mut stream = Socks5Stream::connect_with_password( "127.0.0.1:1080", "httpbin.org".to_string(), 443, "admin".to_string(), "password".to_string(), config, ).await?; let socket = stream.get_socket_mut(); socket.write_all(b"GET /get HTTP/1.1\r\nHost: httpbin.org\r\n\r\n").await?; let mut buf = [0u8; 2048]; let n = socket.read(&mut buf).await?; println!("Received {} bytes", n); Ok(()) } ``` -------------------------------- ### Install fast-socks5 dependency Source: https://context7.com/dizda/fast-socks5/llms.txt Configuration snippet for adding the fast-socks5 library to a Rust project's Cargo.toml file, including optional feature flags. ```toml [dependencies] fast-socks5 = "1.0.0" # Enable SOCKS4/4a client support (optional) [features] socks4 = [] ``` -------------------------------- ### Manually handle SOCKS5 protocol flow Source: https://context7.com/dizda/fast-socks5/llms.txt Demonstrates how to manually accept connections, read commands, and perform custom routing or proxy chaining. This approach allows for granular control over the SOCKS5 handshake and connection lifecycle. ```rust use fast_socks5::client; use fast_socks5::server::{transfer, Socks5ServerProtocol}; use fast_socks5::util::target_addr::TargetAddr; use fast_socks5::{ReplyError, Result, Socks5Command}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use tokio::net::TcpListener; #[tokio::main] async fn main() -> Result<()> { let listener = TcpListener::bind("127.0.0.1:1080").await?; loop { let (socket, _) = listener.accept().await?; tokio::spawn(async move { let proto = Socks5ServerProtocol::accept_no_auth(socket).await?; // Read command WITHOUT resolving DNS let (proto, cmd, target_addr) = proto.read_command().await?; if cmd != Socks5Command::TCPConnect { proto.reply_error(&ReplyError::CommandNotSupported).await?; return Ok::<_, fast_socks5::SocksError>(()); } // Custom routing based on target if let TargetAddr::Domain(ref domain, _) = target_addr { if domain.ends_with(".blocked.com") { proto.reply_error(&ReplyError::ConnectionNotAllowed).await?; return Ok(()); } if domain == "internal.service" { // Handle in-process instead of proxying let inner = proto.reply_success( SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0) ).await?; return Ok(()); } } // Route through another SOCKS5 proxy (chaining) let (target_str, port) = target_addr.into_string_and_port(); let mut config = client::Config::default(); config.set_skip_auth(true); let upstream = client::Socks5Stream::connect( "upstream-proxy:1081", target_str, port, config, ).await?; let inner = proto.reply_success( SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0) ).await?; // Bidirectional transfer between client and upstream transfer(inner, upstream).await; Ok(()) }); } } ``` -------------------------------- ### Authenticate UDP Tunneling Source: https://context7.com/dizda/fast-socks5/llms.txt Shows how to establish a UDP tunnel using credentials with the bind_with_password method. This is required for proxies that enforce user authentication. ```rust use fast_socks5::client::Socks5Datagram; use fast_socks5::Result; use std::net::SocketAddr; use tokio::net::TcpStream; #[tokio::main] async fn main() -> Result<()> { let socks_server: SocketAddr = "127.0.0.1:1080".parse().unwrap(); let backing_socket = TcpStream::connect(socks_server).await?; let tunnel = Socks5Datagram::bind_with_password( backing_socket, "0.0.0.0:0", "admin", "password", ).await?; let proxy_addr = tunnel.proxy_addr()?; println!("UDP proxy bound at: {}", proxy_addr); let udp_socket = tunnel.get_ref(); println!("Local UDP address: {:?}", udp_socket.local_addr()); Ok(()) } ``` -------------------------------- ### Rust Error Handling for SOCKS5 Client Connections Source: https://context7.com/dizda/fast-socks5/llms.txt Illustrates error handling in Rust when establishing a SOCKS5 client connection using the Fast Socks5 library. It demonstrates how to match against various `SocksError` variants, including I/O errors, authentication failures, and specific SOCKS reply errors. Requires the 'fast_socks5' crate and 'tokio'. ```rust use fast_socks5::client::{Config, Socks5Stream}; use fast_socks5::{ReplyError, SocksError}; #[tokio::main] async fn main() { let result = Socks5Stream::connect( "127.0.0.1:1080", "example.com".to_string(), 80, Config::default(), ).await; match result { Ok(stream) => println!("Connected successfully"), Err(SocksError::Io(e)) => println!("I/O error: {}", e), Err(SocksError::AuthenticationRejected(msg)) => { println!("Auth failed: {}", msg); } Err(SocksError::ReplyError(reply)) => match reply { ReplyError::ConnectionRefused => println!("Target refused connection"), ReplyError::NetworkUnreachable => println!("Network unreachable"), ReplyError::HostUnreachable => println!("Host unreachable"), ReplyError::ConnectionTimeout => println!("Connection timed out"), ReplyError::CommandNotSupported => println!("Command not supported"), _ => println!("SOCKS error: {}", reply), }, Err(e) => println!("Other error: {}", e), } } ``` -------------------------------- ### Implement UDP Proxying with fast-socks5 Source: https://context7.com/dizda/fast-socks5/llms.txt This snippet demonstrates how to initialize a TCP listener and handle the UDPAssociate command. It uses the run_udp_proxy function to facilitate UDP traffic, requiring a public IP address to be returned to the client in the SOCKS5 reply. ```rust use fast_socks5::server::{ run_tcp_proxy, run_udp_proxy, DnsResolveHelper, Socks5ServerProtocol, }; use fast_socks5::{ReplyError, Result, Socks5Command}; use std::net::IpAddr; use std::time::Duration; use tokio::net::TcpListener; #[tokio::main] async fn main() -> Result<()> { let listener = TcpListener::bind("0.0.0.0:1080").await?; let public_ip: IpAddr = "192.168.1.100".parse().unwrap(); loop { let (socket, _) = listener.accept().await?; let reply_ip = public_ip; tokio::spawn(async move { let proto = Socks5ServerProtocol::accept_no_auth(socket).await?; let (proto, cmd, target_addr) = proto .read_command() .await? .resolve_dns() .await?; match cmd { Socks5Command::TCPConnect => { run_tcp_proxy(proto, &target_addr, Duration::from_secs(10), false).await?; } Socks5Command::UDPAssociate => { run_udp_proxy(proto, &target_addr, None, reply_ip, None).await?; } Socks5Command::TCPBind => { proto.reply_error(&ReplyError::CommandNotSupported).await?; } } Ok::<_, fast_socks5::SocksError>(()) }); } } ``` -------------------------------- ### Create SOCKS5 Server Without Authentication (Rust) Source: https://context7.com/dizda/fast-socks5/llms.txt This snippet shows how to create a SOCKS5 server that accepts connections without any authentication. It utilizes the `Socks5ServerProtocol::accept_no_auth` method and handles TCP connect commands, resolving DNS for target addresses. The typestate pattern ensures protocol correctness at compile time. ```rust use fast_socks5::server::{ run_tcp_proxy, run_udp_proxy, DnsResolveHelper, Socks5ServerProtocol, }; use fast_socks5::{ReplyError, Result, Socks5Command}; use std::time::Duration; use tokio::net::TcpListener; #[tokio::main] async fn main() -> Result<()> { let listener = TcpListener::bind("127.0.0.1:1080").await?; println!("SOCKS5 server listening on 127.0.0.1:1080"); loop { let (socket, client_addr) = listener.accept().await?; println!("New connection from {}", client_addr); tokio::spawn(async move { // Accept connection without authentication let proto = Socks5ServerProtocol::accept_no_auth(socket).await?; // Read command and resolve DNS let (proto, cmd, target_addr) = proto .read_command() .await? .resolve_dns() .await?; match cmd { Socks5Command::TCPConnect => { let request_timeout = Duration::from_secs(10); run_tcp_proxy(proto, &target_addr, request_timeout, false).await?; } _ => { proto.reply_error(&ReplyError::CommandNotSupported).await?; } } Ok::<_, fast_socks5::SocksError>(()) }); } } ``` -------------------------------- ### Implement Custom Token Authentication for Fast Socks5 Server (Rust) Source: https://context7.com/dizda/fast-socks5/llms.txt This Rust code defines a custom token authentication method for the Fast Socks5 server. It includes structs for the authentication states (`TokenAuthStarted`, `TokenAuthSuccess`) and implements the `AuthMethod` and `AuthMethodSuccessState` traits. The `verify_token` function handles reading and validating the token from the client. This method can be combined with other authentication methods using the `auth_method_enums!` macro. ```rust use fast_socks5::server::{ run_tcp_proxy, AuthMethod, AuthMethodSuccessState, DnsResolveHelper, PasswordAuthentication, PasswordAuthenticationStarted, Socks5ServerProtocol, }; use fast_socks5::{auth_method_enums, ReplyError, Result, Socks5Command, SocksError}; use std::time::Duration; use tokio::io::{AsyncRead, AsyncReadExt}; use tokio::net::TcpListener; // Define custom auth method states pub struct TokenAuthStarted(T); pub struct TokenAuthSuccess(T, String); // Store validated token impl TokenAuthStarted { pub async fn verify_token(self) -> Result, SocksError> { let mut socket = self.0; let mut token_len = [0u8; 1]; socket.read_exact(&mut token_len).await?; let mut token = vec![0u8; token_len[0] as usize]; socket.read_exact(&mut token).await?; let token = String::from_utf8_lossy(&token).to_string(); if token.starts_with("valid_") { Ok(TokenAuthSuccess(socket, token)) } else { Err(SocksError::AuthenticationRejected("Invalid token".into())) } } } impl AuthMethodSuccessState for TokenAuthSuccess { fn into_inner(self) -> T { self.0 } } #[derive(Clone, Copy)] pub struct TokenAuthentication; impl AuthMethod for TokenAuthentication { type StartingState = TokenAuthStarted; fn method_id(self) -> u8 { 0x80 } // Private method range fn new(self, inner: T) -> Self::StartingState { TokenAuthStarted(inner) } } // Combine with standard password auth auth_method_enums! { pub enum MyAuth / MyAuthStarted { PasswordAuthentication(PasswordAuthenticationStarted), TokenAuthentication(TokenAuthStarted), } } #[tokio::main] async fn main() -> Result<()> { let listener = TcpListener::bind("127.0.0.1:1080").await?; loop { let (socket, _) = listener.accept().await?; tokio::spawn(async move { let proto = match Socks5ServerProtocol::start(socket) .negotiate_auth(&[ MyAuth::PasswordAuthentication(PasswordAuthentication), MyAuth::TokenAuthentication(TokenAuthentication), ]) .await? { MyAuthStarted::PasswordAuthentication(auth) => { let (user, pass, auth) = auth.read_username_password().await?; if user == "admin" && pass == "password" { auth.accept().await?.finish_auth() } else { auth.reject().await?; return Err(SocksError::AuthenticationRejected("Bad creds".into())); } } MyAuthStarted::TokenAuthentication(auth) => { auth.verify_token().await?.finish_auth() } }; let (proto, cmd, addr) = proto.read_command().await?.resolve_dns().await?; if cmd == Socks5Command::TCPConnect { run_tcp_proxy(proto, &addr, Duration::from_secs(10), false).await?; } Ok::<_, SocksError>(()) }); } } ``` -------------------------------- ### Rust TargetAddr Enum for Connection Targets Source: https://context7.com/dizda/fast-socks5/llms.txt Demonstrates the usage of the TargetAddr enum in Rust for representing connection targets, including IPv4, IPv6, and domain names. It showcases DNS resolution, conversion to string and port, and serialization for the SOCKS5 protocol. Requires the 'fast_socks5' crate and 'tokio' for async operations. ```rust use fast_socks5::util::target_addr::{TargetAddr, ToTargetAddr}; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; #[tokio::main] async fn main() -> Result<(), Box> { // Create from tuple (domain, port) let addr1 = ("example.com", 443).to_target_addr()?; assert!(addr1.is_domain()); // Create from IP address let addr2 = ("192.168.1.1", 8080).to_target_addr()?; assert!(addr2.is_ip()); // Create from SocketAddr let socket_addr: SocketAddr = "10.0.0.1:3000".parse()?; let addr3 = socket_addr.to_target_addr()?; // Create IPv6 target let addr4 = (Ipv6Addr::LOCALHOST, 443).to_target_addr()?; // DNS resolution (async) let domain_addr = TargetAddr::Domain("github.com".to_string(), 443); let resolved = domain_addr.resolve_dns().await?; if let TargetAddr::Ip(socket) = resolved { println!("Resolved to: {}", socket); } // Convert to string and port let addr = TargetAddr::Domain("api.example.com".to_string(), 8443); let (host, port) = addr.into_string_and_port(); println!("Host: {}, Port: {}", host, port); // "api.example.com", 8443 // Serialize to bytes for SOCKS5 protocol let addr = ("proxy.local", 1080).to_target_addr()?; let bytes = addr.to_be_bytes()?; println!("Serialized: {:?}", bytes); Ok(()) } ``` -------------------------------- ### Connect to TCP server via SOCKS5 proxy Source: https://context7.com/dizda/fast-socks5/llms.txt Demonstrates establishing a TCP connection through a SOCKS5 proxy without authentication using the Socks5Stream client. The stream implements AsyncRead and AsyncWrite for standard Tokio I/O operations. ```rust use fast_socks5::client::{Config, Socks5Stream}; use fast_socks5::Result; use tokio::io::{AsyncReadExt, AsyncWriteExt}; #[tokio::main] async fn main() -> Result<()> { let config = Config::default(); let mut stream = Socks5Stream::connect( "127.0.0.1:1080", "example.com".to_string(), 80, config, ).await?; stream.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n").await?; let mut response = vec![0u8; 1024]; let n = stream.read(&mut response).await?; println!("Response: {}", String::from_utf8_lossy(&response[..n])); Ok(()) } ``` -------------------------------- ### Client API - Using Existing Streams Source: https://context7.com/dizda/fast-socks5/llms.txt Use `use_stream` to wrap an existing socket as a SOCKS5 client, enabling advanced scenarios like TLS-wrapped SOCKS5 or custom transport layers. ```APIDOC ## Client API - Using Existing Streams ### Description Use `use_stream` to wrap an existing socket as a SOCKS5 client, enabling advanced scenarios like TLS-wrapped SOCKS5 or custom transport layers. ### Method POST (Implicitly for SOCKS5 handshake and command execution) ### Endpoint N/A (Operates on an existing, established TCP stream) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None (Configuration and authentication are passed as arguments to `use_stream`) ### Request Example ```rust use fast_socks5::client::{Config, Socks5Stream}; use fast_socks5::{AuthenticationMethod, Result, Socks5Command}; use fast_socks5::util::target_addr::ToTargetAddr; use tokio::net::TcpStream; #[tokio::main] async fn main() -> Result<()> { // Create your own TcpStream (could be TLS-wrapped, etc.) let socket = TcpStream::connect("127.0.0.1:1080").await?; // Configure to skip auth for private proxies let mut config = Config::default(); config.set_skip_auth(false); // Provide authentication credentials let auth = Some(AuthenticationMethod::Password { username: "user".to_string(), password: "pass".to_string(), }); // Wrap existing stream as SOCKS5 let mut stream = Socks5Stream::use_stream(socket, auth, config).await?; // Make a SOCKS5 request let target = ("google.com", 80).to_target_addr()?; let bind_addr = stream.request(Socks5Command::TCPConnect, target).await?; println!("Bound address: {}", bind_addr); // Now use stream.get_socket() for I/O Ok(()) } ``` ### Response #### Success Response (200) Returns a `Socks5Stream` instance that wraps the provided socket, ready to execute SOCKS5 commands. The `request` method returns the bound address from the proxy server. #### Response Example ``` Bound address: 192.168.1.100:12345 ``` ``` -------------------------------- ### Establish UDP Association via SOCKS5 Source: https://context7.com/dizda/fast-socks5/llms.txt Demonstrates how to use Socks5Datagram to route UDP traffic through a SOCKS5 proxy. This is useful for protocols like DNS that require datagram-based communication. ```rust use fast_socks5::client::Socks5Datagram; use fast_socks5::Result; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use tokio::net::TcpStream; #[tokio::main] async fn main() -> Result<()> { let backing_socket = TcpStream::connect("127.0.0.1:1080").await?; let client_bind = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); let tunnel = Socks5Datagram::bind(backing_socket, client_bind).await?; let dns_query = [ 0x13, 0x37, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, b'g', b'i', b't', b'h', b'u', b'b', 0x03, b'c', b'o', b'm', 0x00, 0x00, 0x01, 0x00, 0x01 ]; let dns_server: SocketAddr = "8.8.8.8:53".parse().unwrap(); tunnel.send_to(&dns_query, dns_server).await?; let mut buf = [0u8; 512]; let (len, from_addr) = tunnel.recv_from(&mut buf).await?; println!("Received {} bytes from {:?}", len, from_addr); Ok(()) } ``` -------------------------------- ### Client API - UDP with Authentication Source: https://context7.com/dizda/fast-socks5/llms.txt Creates a UDP tunnel through an authenticated SOCKS5 proxy using `bind_with_password`. This is essential when the proxy requires credentials for UDP ASSOCIATE operations. ```APIDOC ## Client API - UDP with Authentication ### Description Creates a UDP tunnel through an authenticated SOCKS5 proxy using `bind_with_password`. This is essential when the proxy requires credentials for UDP ASSOCIATE operations. ### Method POST (Implicitly through UDP ASSOCIATE command with authentication) ### Endpoint N/A (Operates on an established TCP control connection) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None (Authentication is handled during the SOCKS handshake, and data is sent via UDP datagrams after association) ### Request Example ```rust use fast_socks5::client::Socks5Datagram; use fast_socks5::Result; use std::net::SocketAddr; use tokio::net::TcpStream; #[tokio::main] async fn main() -> Result<()> { let socks_server: SocketAddr = "127.0.0.1:1080".parse().unwrap(); let backing_socket = TcpStream::connect(socks_server).await?; // Bind with authentication let tunnel = Socks5Datagram::bind_with_password( backing_socket, "0.0.0.0:0", // Local bind address "admin", // Username "password", // Password ).await?; // Get proxy address for reference let proxy_addr = tunnel.proxy_addr()?; println!("UDP proxy bound at: {}", proxy_addr); // Access underlying socket for advanced configuration let udp_socket = tunnel.get_ref(); println!("Local UDP address: {:?}", udp_socket.local_addr()); Ok(()) } ``` ### Response #### Success Response (200) Returns a `Socks5Datagram` instance bound to a UDP port through the authenticated proxy. The `proxy_addr()` method can be used to retrieve the address assigned by the proxy for UDP communication. #### Response Example ``` UDP proxy bound at: 127.0.0.1:54321 Local UDP address: 127.0.0.1:54321 ``` ``` -------------------------------- ### Client API - UDP Associate Source: https://context7.com/dizda/fast-socks5/llms.txt Enables UDP traffic through a SOCKS5 proxy using the UDP ASSOCIATE command. It wraps a UDP socket that routes all datagrams through the proxy server. ```APIDOC ## Client API - UDP Associate ### Description Enables UDP traffic through a SOCKS5 proxy using the UDP ASSOCIATE command. It wraps a UDP socket that routes all datagrams through the proxy server, useful for protocols like DNS queries. ### Method POST (Implicitly through UDP ASSOCIATE command) ### Endpoint N/A (Operates on an established TCP control connection) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None (Data is sent via UDP datagrams after association) ### Request Example ```rust use fast_socks5::client::Socks5Datagram; use fast_socks5::Result; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use tokio::net::TcpStream; #[tokio::main] async fn main() -> Result<()> { // Create TCP backing socket for SOCKS5 control connection let backing_socket = TcpStream::connect("127.0.0.1:1080").await?; // Bind UDP socket through the proxy let client_bind = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); let tunnel = Socks5Datagram::bind(backing_socket, client_bind).await?; // Send DNS query to 8.8.8.8 let dns_query = [ 0x13, 0x37, // Transaction ID 0x01, 0x00, // Flags: Standard query 0x00, 0x01, // Questions: 1 0x00, 0x00, // Answers: 0 0x00, 0x00, // Authority: 0 0x00, 0x00, // Additional: 0 0x06, b'g', b'i', b't', b'h', b'u', b'b', // "github" 0x03, b'c', b'o', b'm', // "com" 0x00, // Root 0x00, 0x01, // Type: A 0x00, 0x01, // Class: IN ]; let dns_server: SocketAddr = "8.8.8.8:53".parse().unwrap(); tunnel.send_to(&dns_query, dns_server).await?; // Receive DNS response let mut buf = [0u8; 512]; let (len, from_addr) = tunnel.recv_from(&mut buf).await?; println!("Received {} bytes from {:?}", len, from_addr); Ok(()) } ``` ### Response #### Success Response (200) UDP datagrams are sent and received through the established tunnel. The `recv_from` method returns the number of bytes received and the source address. #### Response Example ``` Received 42 bytes from 8.8.8.8:53 ``` ``` -------------------------------- ### Wrap Existing Streams for SOCKS5 Source: https://context7.com/dizda/fast-socks5/llms.txt Utilizes the use_stream method to wrap an existing TcpStream, allowing for custom configurations such as TLS-wrapped connections or specific authentication requirements. ```rust use fast_socks5::client::{Config, Socks5Stream}; use fast_socks5::{AuthenticationMethod, Result, Socks5Command}; use fast_socks5::util::target_addr::ToTargetAddr; use tokio::net::TcpStream; #[tokio::main] async fn main() -> Result<()> { let socket = TcpStream::connect("127.0.0.1:1080").await?; let mut config = Config::default(); config.set_skip_auth(false); let auth = Some(AuthenticationMethod::Password { username: "user".to_string(), password: "pass".to_string(), }); let mut stream = Socks5Stream::use_stream(socket, auth, config).await?; let target = ("google.com", 80).to_target_addr()?; let bind_addr = stream.request(Socks5Command::TCPConnect, target).await?; println!("Bound address: {}", bind_addr); Ok(()) } ``` -------------------------------- ### Implement non-RFC compliant authentication skip Source: https://context7.com/dizda/fast-socks5/llms.txt Shows how to bypass the authentication handshake to reduce latency in trusted environments. This method uses the non-standard skip_auth_this_is_not_rfc_compliant helper. ```rust use fast_socks5::server::{run_tcp_proxy, DnsResolveHelper, Socks5ServerProtocol}; use fast_socks5::{ReplyError, Result, Socks5Command}; use std::time::Duration; use tokio::net::TcpListener; #[tokio::main] async fn main() -> Result<()> { let listener = TcpListener::bind("127.0.0.1:1080").await?; loop { let (socket, _) = listener.accept().await?; tokio::spawn(async move { // Skip auth handshake - client sends command immediately let proto = Socks5ServerProtocol::skip_auth_this_is_not_rfc_compliant(socket); let (proto, cmd, target_addr) = proto .read_command() .await? .resolve_dns() .await?; if cmd == Socks5Command::TCPConnect { run_tcp_proxy(proto, &target_addr, Duration::from_secs(10), false).await?; } else { proto.reply_error(&ReplyError::CommandNotSupported).await?; } Ok::<_, fast_socks5::SocksError>(()) }); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.