Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2.5 KiB
Patterns and conventions
Error handling
The project uses a layered error strategy:
thiserrorenums for domain-specific errors (TlsError,AuthError,TunnelError,HostError,Socks5Error,FrameError). These live insrc/errors.rsandsrc/socks5.rs/src/framing.rs.anyhowfor application-level propagation. CLI commands returnanyhow::Resultandmainexits withprocess::exit(exit_code).- All errors are designed to be actionable and fail-closed. There are no silent degradation paths to insecure modes.
Secret handling
- The
Redactedwrapper insrc/redact.rsmust be used before logging any secret. Redacted::inner()andinto_inner()are marked#[allow(dead_code)]to discourage use, but available for file writes.is_sensitive()detects PEM private key blocks.is_auth_token()detects long alphanumeric strings.is_connection_key()detects strings starting withrtun1..
Async patterns
- Tokio's multi-threaded runtime is used on both listener and connector sides.
tokio::spawnis used for per-connection and per-stream tasks.tokio::select!withbiased;prioritizes shutdown signals over new connections.watch::channelis used for publishing the activeStreamMuxto the SOCKS5 proxy (supports reconnect).mpsc::channelandoneshot::channelare used for stream data and CONNECT_REPLY coordination.
Constant-time comparison
Auth token comparison in src/tunnel.rs uses a manual constant-time XOR loop to prevent timing attacks:
fn constant_time_compare(a: &str, b: &str) -> bool {
let a_bytes = a.as_bytes();
let b_bytes = b.as_bytes();
if a_bytes.len() != b_bytes.len() {
return false;
}
let mut result: u8 = 0;
for (x, y) in a_bytes.iter().zip(b_bytes.iter()) {
result |= x ^ y;
}
result == 0
}
Frame reader partial read discipline
FrameReader in src/framing.rs never consumes bytes from the buffer until a complete frame (header + payload) is available. This prevents corruption when TCP segments arrive in arbitrary chunks.
TLS material as enum
Both ServerTlsMaterial and ClientTlsMaterial are enums with Paths and Pem variants. This lets the listener and connector accept either file paths (from CLI args) or embedded PEM strings (from connection keys).
Insecure mode
--insecure-skip-tls-verify exists for DPI/intercepted environments only. When enabled, the listener skips client certificate verification and the connector skips server certificate verification. This is logged at warn level.