Skip to content

Releases: davlgd/wisegate

v0.12.0

Choose a tag to compare

@davlgd davlgd released this 13 May 15:09

Security

  • X-Real-IP spoofing: Strip any client-supplied X-Real-IP header before processing so the upstream only ever sees the value wisegate computed.
  • Authorization leakage: When wisegate has performed authentication, the Authorization header is now stripped before forwarding. Opt back in with CC_FORWARD_AUTH_HEADER=true (or AuthenticationProvider::forward_authorization_header() in the library) when the upstream genuinely needs the credentials.
  • IPv6 rate-limit bypass: Extracted IPs are canonicalised (RFC 5952), so 2001:0db8::1 and 2001:db8::1 now key the same rate-limit bucket. Blocked/allowed IP lists are also matched on canonical form, so non-canonical IPv6 spellings in config still apply.

Added

  • wisegate_core::DefaultConfig: ready-to-use struct implementing every configuration trait with the same defaults as the CLI, so library users can drop wisegate-core in without trait boilerplate.
  • Startup warnings: warn when CC_REVERSE_PROXY_IPS contains the bind sentinel 0.0.0.0, and when wisegate listens on 0.0.0.0 with no auth and no IP blocklist (a common open-proxy misconfiguration).
  • Full env-var reference in --help: every recognised variable is now listed, grouped by purpose (proxy security / filtering / rate limiting / authentication / proxy behaviour).
  • CC_FORWARD_AUTH_HEADER env var to opt into upstream Authorization forwarding.

Changed

  • Library example: README and wisegate-core crate docs now showcase the DefaultConfig path instead of the 5-trait implementation snippet.
  • ConnectionTracker::track(): returns impl Drop instead of the concrete ConnectionGuard; binary callers only ever depended on the drop side anyway.
  • Doc: request_handler::handle_request rustdoc now spells out the Tokio runtime requirement, the permissive-mode header-trust caveat, and that strict mode requires both X-Forwarded-For and Forwarded headers (the by= field is what gets matched against the proxy allowlist).

Refactored

  • ip_filter: deduplicated the canonical-IP equality path into a private ips_match helper and dropped the dead is_valid_ip_format wrapper.

Full Changelog: v0.11.0...v0.12.0

v0.11.0

Choose a tag to compare

@davlgd davlgd released this 13 May 11:32

Added

  • Sliding window log algorithm: True sliding window rate limiting replacing the fixed window approach

Fixed

  • Content-Length pre-check: Check body size before buffering to prevent memory exhaustion
  • Hop-by-hop header filtering: Filter on request path per RFC 7230
  • URL pattern bypass: Case-insensitive URL pattern blocking to prevent bypass
  • Bearer token prefix: Case-insensitive Bearer prefix per RFC 6750
  • WWW-Authenticate header: Sanitize realm value to prevent header injection
  • Credential masking: Mask auth credentials and tokens in verbose log output

Performance

  • Zero-copy body forwarding: Pass Bytes directly to reqwest body instead of to_vec()
  • Hop-by-hop comparison: Case-insensitive comparison without allocation
  • Method/pattern filtering: Reduce allocations in method and URL pattern filtering
  • url_decode: Byte-based iteration avoiding String allocation per hex pair
  • Blocked patterns: Pre-normalize to lowercase at config load time
  • forward_host: Use Arc<str> to avoid per-connection String::clone

Refactored

  • RateLimiter: Unified state into single Mutex, encapsulated internals, moved cleanup state per-instance
  • Client IP: Replace sentinel string with Option<String>
  • ConnectionGuard: RAII guard with saturating decrement
  • Config caching: Replace once_cell::Lazy with std::sync::LazyLock
  • ConfigProvider: Use trait consistently instead of standalone getters
  • Header constants: Use constants instead of magic strings in IP filter and request handler
  • Test infrastructure: Merge AuthTestEnvironment into TestEnvironment with builder pattern
  • Error types: Remove unused error variants
  • Defaults: Remove redundant constant aliases, use defaults module directly
  • Method matching: Simplify HTTP method matching in request forwarding
  • Rate limiter locking: Eliminate nested locking in cleanup path
  • Dead code cleanup: Remove unused Result type alias, builder methods, and consolidate redundant tests
  • Clippy warnings: Fix collapsible_if, expect_fun_call, and manual_contains in integration tests

Documentation

  • Fix request flow order in README to match implementation
  • Fix library examples, document TRUSTED_PROXY_IPS_VAR whitelist
  • Remove unsupported CIDR notation from proxy IPs example

Full Changelog: v0.10.0...v0.11.0

v0.10.0

Choose a tag to compare

@davlgd davlgd released this 17 Jan 01:34

What's Changed

Added

  • Authentication integration tests: 9 new tests covering Basic Auth, Bearer Token, and combined authentication scenarios
  • defaults module: Centralized default configuration values in wisegate-core/src/defaults.rs (DRY principle)

Changed

  • request_handler: Now uses WiseGateError for consistent error handling throughout the pipeline
  • test_utils: Uses centralized defaults module for configuration values

Full Changelog: v0.9.0...v0.10.0

v0.9.0

Choose a tag to compare

@davlgd davlgd released this 17 Jan 01:33

Added

  • HTTP Basic Authentication (RFC 7617): Protect your endpoints with username/password
    • Support for multiple password formats: plain text, bcrypt, APR1 MD5, SHA1
    • Constant-time comparison to prevent timing attacks
    • Multiple users via CC_HTTP_BASIC_AUTH_N environment variables
    • Configurable realm via CC_HTTP_BASIC_AUTH_REALM
  • Bearer Token Authentication (RFC 6750): API key authentication
    • Simple token-based authentication via CC_BEARER_TOKEN
    • Constant-time comparison to prevent timing attacks
    • Can be used alone or combined with Basic Auth (either method accepted)
  • auth module: New wisegate-core/src/auth/ module with:
    • Credentials struct for credential storage
    • hash::verify() for multi-format password verification
    • hash::constant_time_eq() for secure comparison
    • check_basic_auth() for request authentication
    • check_bearer_token() for bearer token verification
  • AuthenticationProvider trait: Configuration trait for authentication settings
    • bearer_token() method for bearer token access
    • is_basic_auth_enabled() and is_bearer_auth_enabled() helpers
  • New environment variables: CC_HTTP_BASIC_AUTH, CC_HTTP_BASIC_AUTH_N, CC_HTTP_BASIC_AUTH_REALM, CC_BEARER_TOKEN
  • New error types: AuthenticationRequired, InvalidCredentials
  • New headers: AUTHORIZATION, WWW_AUTHENTICATE constants
  • 51 new tests: Comprehensive coverage for auth module

Changed

  • Request pipeline now includes authentication check after method blocking, before rate limiting
  • ConfigProvider trait now requires AuthenticationProvider implementation
  • Startup info displays authentication status (Basic Auth and Bearer Token)

Full Changelog: v0.8.0...v0.9.0

v0.8.0

Choose a tag to compare

@davlgd davlgd released this 16 Jan 23:36

What's Changed

Added

  • wisegate-core crate: Extracted reusable library for embedding in other projects
  • ConfigProvider trait: Dependency injection for configuration, enabling library reuse
  • EnvVarConfig: Default implementation reading from environment variables
  • WiseGateError: Custom error type with HTTP status mapping and user-friendly messages
  • HTTP header constants: Centralized in headers.rs with is_hop_by_hop() helper
  • ConnectionTracker: Track active connections for graceful shutdown
  • ConnectionLimiter: Semaphore-based connection limiting with permit management
  • Shared TestConfig: Centralized test configuration in test_utils.rs module
  • Comprehensive unit tests: 220 tests covering all modules

Refactored

  • Workspace structure: Split into wisegate (CLI) and wisegate-core (library)
  • ip_filter: Accepts ConfigProvider instead of global config
  • rate_limiter: Accepts ConfigProvider instead of global config
  • request_handler: Accepts ConfigProvider and HTTP client, uses centralized headers::is_hop_by_hop()
  • main.rs: Uses ConnectionTracker and ConnectionLimiter for cleaner connection management

Removed

  • test-local.py: Removed redundant Python test script (replaced by Rust integration tests)
  • Duplicated TestConfig: Consolidated into shared test_utils.rs module
  • Duplicated is_hop_by_hop: Now uses centralized function from headers.rs

Full Changelog: v0.7.2...v0.8.0

v0.7.2

Choose a tag to compare

@davlgd davlgd released this 16 Jan 23:35

Added

  • ConfigProvider trait: Dependency injection for configuration, enabling library reuse
  • EnvVarConfig: Default implementation reading from environment variables

Refactored

  • ip_filter: Accepts ConfigProvider instead of global config
  • rate_limiter: Accepts ConfigProvider instead of global config
  • request_handler: Accepts ConfigProvider instead of global config
  • main: Uses EnvVarConfig for dependency injection

Full Changelog: v0.7.1...v0.7.2

v0.7.1

Choose a tag to compare

@davlgd davlgd released this 16 Jan 23:35

Refactored

  • NewType RateLimiter: Replaced type alias with proper struct for better encapsulation
  • RateLimitEntry struct: Named fields instead of tuple for clearer code
  • StartupConfig: Decoupled server.rs from CLI Args struct
  • IP validation: validate() now returns parsed IpAddr to avoid double parsing

Full Changelog: v0.7.0...v0.7.1

v0.7.0

Choose a tag to compare

@davlgd davlgd released this 16 Jan 20:27

What's Changed

Added

  • Structured logging: tracing with JSON support (--json-logs)
  • Graceful shutdown: SIGINT/SIGTERM handling with 30s connection drain
  • Connection limiting: MAX_CONNECTIONS env var with semaphore-based limiting
  • HTTP connection pooling: Reusable client with 32 connections per host
  • Configuration caching: once_cell::Lazy for zero-overhead config access
  • Library structure: Extracted lib.rs for better testability and reuse
  • Complete rustdoc: All public functions documented with examples

Enhanced

  • Performance: opt-level = 3 (2x faster than "z", +0.8MB)
  • Dependencies: Updated to latest versions (tokio 1.49, reqwest 0.13, clap 4.5.54)
  • Documentation: Simplified README

Full Changelog: v0.6.1...v0.7.0

v0.6.1

Choose a tag to compare

@davlgd davlgd released this 03 Aug 14:24

🔧 Enhanced:

  • Docs: updated texts
  • Testing: Added scripts & tools

Full Changelog: v0.6.0...v0.6.1

v0.6.0

Choose a tag to compare

@davlgd davlgd released this 03 Aug 10:05

✨ New Features

  • CLI Short Flags: -l, -f, -v, -q for better UX
  • Quiet Mode: --quiet for production deployments (minimal output)
  • Verbose Mode: --verbose shows full config + environment variables
  • Enhanced Help: Comprehensive CLI help with environment variable docs

🔧 Enhanced Functionality

  • Better Error Handling: Replaced panics with graceful error handling
  • Improved Validation: Configuration validation with fallback to defaults
  • Security Enhancements: Better hop-by-hop header filtering

🧹 Code Quality

  • Simplified Architecture: Removed experimental streaming modes
  • Better Organization: Centralized defaults and cleaner separation
  • Type Safety: Enhanced validation and error propagation

Full Changelog: v0.5.0...v0.6.0