- Add socks5.rs module with SOCKS5 protocol parsing (greeting, auth, CONNECT) - Add /forward HTTPS endpoint on listener for target TCP forwarding - Add SOCKS5 proxy listener on connector side with fail-closed auth gating - Support IPv4 and hostname targets, sequential/concurrent streams - Fail-closed behavior: SOCKS rejected before tunnel authentication - 38 new tests covering protocol parsing, malformed input, and E2E paths Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
136 lines
3.1 KiB
Rust
136 lines
3.1 KiB
Rust
/// Error types for the HTTPS mTLS tunnel.
|
|
///
|
|
/// All errors are designed to be actionable and fail-closed — they never
|
|
/// silently degrade to an insecure path.
|
|
use thiserror::Error;
|
|
|
|
/// Errors that occur when loading or configuring TLS material.
|
|
#[derive(Debug, Error)]
|
|
pub enum TlsError {
|
|
#[error("missing {0}")]
|
|
Missing(&'static str),
|
|
|
|
#[error("invalid {0}: {1}")]
|
|
Invalid(&'static str, String),
|
|
|
|
#[error("certificate identity mismatch: {0}")]
|
|
IdentityMismatch(String),
|
|
|
|
#[error("certificate expired: {0}")]
|
|
#[allow(dead_code)]
|
|
Expired(String),
|
|
|
|
#[error("certificate verification failed: {0}")]
|
|
VerificationFailed(String),
|
|
|
|
#[error("I/O error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
#[error("rustls error: {0}")]
|
|
#[allow(dead_code)]
|
|
Rustls(String),
|
|
}
|
|
|
|
/// Errors that occur during application-level authentication.
|
|
#[derive(Debug, Error)]
|
|
pub enum AuthError {
|
|
#[error("auth token missing")]
|
|
Missing,
|
|
|
|
#[error("auth token invalid")]
|
|
Invalid,
|
|
|
|
#[error("auth token expired")]
|
|
#[allow(dead_code)]
|
|
Expired,
|
|
|
|
#[error("too many auth attempts")]
|
|
#[allow(dead_code)]
|
|
TooManyAttempts,
|
|
}
|
|
|
|
/// Errors that occur during tunnel lifecycle operations.
|
|
#[derive(Debug, Error)]
|
|
pub enum TunnelError {
|
|
#[error("TLS error: {0}")]
|
|
Tls(#[from] TlsError),
|
|
|
|
#[error("auth error: {0}")]
|
|
Auth(#[from] AuthError),
|
|
|
|
#[error("bind error on {0}: {1}")]
|
|
BindError(String, String),
|
|
|
|
#[error("connection refused: {0}")]
|
|
ConnectionRefused(String),
|
|
|
|
#[error("connection closed")]
|
|
#[allow(dead_code)]
|
|
ConnectionClosed,
|
|
|
|
#[error("port {0} already in use")]
|
|
PortInUse(u16),
|
|
|
|
#[error("shutdown requested")]
|
|
#[allow(dead_code)]
|
|
Shutdown,
|
|
|
|
#[error("I/O error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
#[error("protocol error: {0}")]
|
|
Protocol(String),
|
|
|
|
#[error("timeout: {0}")]
|
|
#[allow(dead_code)]
|
|
Timeout(String),
|
|
|
|
#[error("hostname error: {0}")]
|
|
Host(#[from] HostError),
|
|
}
|
|
|
|
/// Errors returned by the connector side.
|
|
#[allow(dead_code)]
|
|
#[derive(Debug, Error)]
|
|
pub enum ConnectorError {
|
|
#[error("TLS handshake failed: {0}")]
|
|
TlsHandshake(String),
|
|
|
|
#[error("server certificate verification failed: {0}")]
|
|
ServerCertVerification(String),
|
|
|
|
#[error("server certificate identity mismatch for {0}: {1}")]
|
|
ServerIdentityMismatch(String, String),
|
|
|
|
#[error("server certificate expired")]
|
|
ServerCertExpired,
|
|
|
|
#[error("auth rejected: {0}")]
|
|
AuthRejected(String),
|
|
|
|
#[error("connection failed: {0}")]
|
|
ConnectionFailed(String),
|
|
|
|
#[error("I/O error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
#[error("protocol error: {0}")]
|
|
Protocol(String),
|
|
|
|
#[error("timeout: {0}")]
|
|
Timeout(String),
|
|
}
|
|
|
|
/// Errors returned during hostname resolution.
|
|
#[derive(Debug, Error)]
|
|
pub enum HostError {
|
|
#[error("DNS resolution failed for '{0}': {1}")]
|
|
DnsResolution(String, String),
|
|
|
|
#[error("hostname '{0}' is empty or invalid")]
|
|
InvalidHostname(String),
|
|
|
|
#[error("no addresses resolved for '{0}'")]
|
|
NoAddresses(String),
|
|
}
|