| Crates.io | totp-gateway |
| lib.rs | totp-gateway |
| version | 0.1.5 |
| created_at | 2025-11-25 15:18:58.744328+00 |
| updated_at | 2025-11-27 13:23:31.925995+00 |
| description | A high-performance TOTP-based authentication gateway built on Cloudflare's Pingora framework for securing private network access |
| homepage | https://github.com/KBluePurple/totp-gateway |
| repository | https://github.com/KBluePurple/totp-gateway |
| max_upload_size | |
| id | 1949933 |
| size | 278,575 |
TOTP Gateway is a lightweight, high-performance reverse proxy authentication gateway built on Cloudflare's Pingora framework.
It adds a Two-Factor Authentication (TOTP) layer in front of your internal admin panels, private tools, or sensitive API endpoints, effectively blocking unauthorized access. You can enhance security with just a single binary and a configuration file, without setting up complex authentication infrastructure.
protect.config.toml) instantly without downtime.
protect option to choose whether a route is secured by the gateway or proxied directly. Defaults to true for full backward compatibility. See the updated examples above and example_config.toml.cargo install totp-gateway
git clone https://github.com/your-username/totp-gateway.git
cd totp-gateway
cargo build --release
The compiled binary will be located at target/release/totp-gateway (or totp-gateway.exe on Windows).
Generate Config: Run the binary. If no config exists, it will automatically create config.toml from the default template.
./target/release/totp-gateway
Edit Config: Open config.toml and configure bind_addr and totp_secret to match your environment.
Run:
./target/release/totp-gateway --config config.toml
The config.toml file consists of the following sections:
[server])[server]
bind_addr = "0.0.0.0:25000" # Listening address and port
default_upstream = "127.0.0.1:8080" # Default upstream server if no route matches
# Trusted proxy configuration for real IP extraction
# Essential when running behind Cloudflare Tunnel, Nginx, etc.
trusted_proxies = [
["127.0.0.1/32", "CF-Connecting-IP"],
["10.0.0.0/8", "X-Forwarded-For"]
]
[auth])[auth]
# TOTP Secret (Base32 encoded). Register this key in your Authenticator app.
totp_secret = "JBSWY3DPEHPK3PXP"
# Load from file: totp_secret_file = "./secret.txt"
# Load from env: totp_secret_env = "MY_TOTP_SECRET"
# Path to custom login HTML file (optional)
login_page_file = "./login_page.html"
# Session duration in seconds. Default: 1800 (30 mins)
session_duration = 3600
[security])Core settings to defend against Brute-force attacks.
[security]
enabled = true # Enable security features
max_retries = 5 # Max failed attempts before banning
ban_duration = 3600 # IP ban duration (seconds)
ip_limit_duration = 3600 # Time window for tracking failures (seconds)
blacklist_size = 1000 # Max IPs in blacklist
blacklist_strategy = "overwrite" # "overwrite" (remove oldest) or "block" (reject new)
[tls])If this section is present, the server runs in HTTPS mode.
[tls]
cert_file = "./certs/fullchain.pem" # Path to certificate
key_file = "./certs/privkey.pem" # Path to private key
[[routes]])Define multiple routes. Matched in order from top to bottom.
host: glob pattern for hostname (e.g., *.example.com)path: glob pattern for path (e.g., /admin/*)path_prefix: simple prefix match for path (checked before host/path globs)upstream_addr: target host:portprotect (bool, default true): when false, the route bypasses authentication, sessions, blacklist, etc.# 1. Route specific path to a different port (protected by default)
[[routes]]
path_prefix = "/admin"
upstream_addr = "127.0.0.1:9090"
protect = true
# 2. Subdomain matching (unprotected example)
[[routes]]
host = "api.example.com"
upstream_addr = "127.0.0.1:3000"
protect = false # bypass login and security for this route
# 3. Wildcard support
[[routes]]
host = "*.internal.com"
path = "/legacy/*"
upstream_addr = "127.0.0.1:4000"
protect = true
Tip:
server.default_upstream and remains protected (equivalent to protect = true).protect = false.SID).protect=false): The gateway skips authentication and blacklist checks and proxies the request directly.[[routes]] matches) is always protected. To expose a public endpoint, create a specific route and set protect = false.protect = false route that matches /auth unintentionally; doing so would proxy the login endpoint to your upstream instead of handling authentication.protect = false routes.protect field is optional and defaults to true. Existing configs without protect continue to work unchanged.[server]
bind_addr = "0.0.0.0:25000"
default_upstream = "127.0.0.1:8080"
[auth]
totp_secret = "JBSWY3DPEHPK3PXP"
[[routes]]
# Public healthcheck endpoint
path = "/health"
upstream_addr = "127.0.0.1:8080"
protect = false
[[routes]]
# Protected admin area
path = "/admin/*"
upstream_addr = "127.0.0.1:9090"
protect = true
Built on Cloudflare's Pingora framework, TOTP Gateway delivers:
Run the full test suite:
# Run all tests
cargo test
# Run with verbose output
cargo test -- --nocapture
# Run specific test
cargo test test_basic_auth_and_replay_protection
The test suite includes:
protect = true/false) validating bypass and enforcement behaviorBug reports, feature suggestions, and Pull Requests are welcome!
git checkout -b feature/AmazingFeature).git commit -m 'Add some AmazingFeature').git push origin feature/AmazingFeature).Distributed under the MIT License.