Welcome to Hodor
Relevant source files
The following files were used as context for generating this wiki page:
Hodor is a lightweight reverse proxy written in Rust that gates access to any web application behind a single shared password. It eliminates the need for user databases, OAuth configurations, or complex identity providers by using a simple login form and signed session cookies.
The system operates as a sidecar container, streaming traffic to an upstream service while enforcing authentication and brute-force protection at the edge. It supports WebSocket proxying, custom templates, and path-based or network-based authentication bypasses.
Sources: README.md:3-8, AGENTS.md:3-6, src/proxy.rs:180-185
System Architecture
Hodor utilizes a single-binary architecture built on the axum and hyper frameworks. It maintains a stateless core with in-memory guards for rate limiting and session validation.
Core Components
- Config Loader: Loads settings from defaults,
hodor.toml, and environment variables using thefigmentlibrary. - AppState: Holds the shared runtime state, including the HTTP client, template sources, and the
LoginGuard. - Authentication Engine: Validates passwords using constant-time comparisons and manages HMAC-SHA256 signed session tokens.
- Reverse Proxy: Streams request and response bodies between the client and the upstream server without buffering.
Sources: AGENTS.md:12-25, src/state.rs:19-45, src/config.rs:86-95
Component Relationship
The following diagram illustrates the relationship between the main internal modules:
The diagram shows how configuration data initializes the global state, which the proxy and session modules then utilize to process requests.
Sources: src/state.rs:19-45, src/config.rs:10-35, src/proxy.rs:59-75
Request Lifecycle
Every incoming request passes through a series of filters to determine if it requires authentication or if it should be proxied immediately.
Request Flow Logic
- Health Check: If the path is
/_gate/health, Hodor returns200 OKimmediately. - Public Paths: If the path matches an entry in
BYPASS_PATHS, the proxy forwards the request withX-Hodor-Auth: public. - Active Session: If a valid HMAC-signed cookie exists, the proxy forwards the request with
X-Hodor-Auth: password. - Network Bypass: If the client IP matches
BYPASS_CIDRS, the proxy forwards the request withX-Hodor-Auth: bypass. - Authentication Gate: If none of the above conditions apply, Hodor serves the login page.
Sources: README.md:113-122, src/proxy.rs:59-75, AGENTS.md:16-19
This flowchart details the decision tree Hodor follows for every request.
Sources: README.md:113-122, src/proxy.rs:77-89
Authentication and Security
Hodor focuses on security through simplicity and robust brute-force mitigation.
Session Management
Hodor uses a specific token format for session cookies: <unix_expiry>|<hmac_sha256(expiry)>. This format allows the proxy to inspect the expiration time while preventing client-side tampering through the HMAC signature. If the SECRET is not provided in the configuration, Hodor generates an ephemeral 32-byte key at startup.
Sources: src/auth/session.rs:57-65, src/auth/session.rs:88-97
Brute-Force Protection
The LoginGuard manages login attempts per client IP in memory. It enforces the following constraints:
- Rate Limiting: Limits attempts to 5 per 60 seconds per IP.
- Escalating Lockouts: After 10 failures, it doubles the lockout duration starting from 60 seconds (capped at 1 hour).
- Failure Delay: Introduces a 500ms delay for every failed attempt to slow automated guessing.
- Request Timing: Requires login form bodies to arrive within 10 seconds.
Sources: README.md:124-133, AGENTS.md:27-32
Forwarded Authentication Headers
Hodor injects the X-Hodor-Auth header into all proxied requests. This allows the upstream application to identify the authentication method used. Hodor strips any client-supplied X-Hodor-* headers before adding its own to prevent spoofing.
| Header Value | Description |
|---|---|
password | The user presented a valid session cookie. |
bypass | The request originated from a trusted CIDR. |
public | The request matched a configured public path. |
Sources: README.md:166-175, src/proxy.rs:25-45, src/proxy.rs:163-175
Configuration
Hodor supports layered configuration where environment variables override hodor.toml files, which in turn override default values.
Core Configuration Options
| Environment Variable | Required | Default | Description |
|---|---|---|---|
PASSWORD | Yes | - | The shared password for the login gate. |
UPSTREAM | Yes | - | The URL of the backend service (HTTP only). |
SECRET | No | Random | The key used to sign session cookies. |
SESSION_TTL | No | 86400 | Session duration in seconds (default 24h). |
TRUST_PROXY | No | false | Enables processing of X-Forwarded-For headers. |
BYPASS_PATHS | No | - | Comma-separated paths that skip authentication. |
Sources: README.md:46-70, src/config.rs:10-35
Upstream Header Injection
You can configure a static header to be sent to the upstream using UPSTREAM_HEADER. This is useful for passing shared secrets or internal API keys. Hodor validates this header at startup to ensure it does not conflict with reserved headers like Host or Content-Length.
Sources: README.md:86-95, src/config.rs:231-255
Proxy Behavior
The proxy module is responsible for the bidirectional transfer of data. It performs several key actions:
- Header Cleaning: It strips hop-by-hop headers (e.g.,
Connection,Keep-Alive) to maintain proxy integrity. - Host Modification: By default, it replaces the
Hostheader with the upstream authority unlessPRESERVE_HOSTis set totrue. - Forwarding Headers: It appends the client's IP to
X-Forwarded-Forand sets theX-Forwarded-Protoheader. - WebSocket Tunneling: If a request includes a
Upgrade: websocketheader, Hodor establishes a bidirectional tunnel.
Sources: README.md:195-201, src/proxy.rs:125-155, src/proxy.rs:180-195
Sequence of Proxying
The following diagram shows the interaction between Hodor and the Upstream during a typical proxied request:
This diagram demonstrates how Hodor acts as an intermediary, adding security headers while maintaining a streaming connection.
Sources: src/proxy.rs:91-124, AGENTS.md:11-14
Summary
Hodor provides a secure, zero-dependency authentication gate for internal tools and previews. By centralizing authentication at the proxy level, it allows developers to protect upstream services without modifying their codebases. The combination of signed sessions, CIDR bypasses, and brute-force protection ensures that the single-password model remains resilient against common web attacks.