π For the latest documentation, cloud platform access, and support, visit fronthouse.io
FrontHouseClient is a modular, high-performance reverse proxy with smart request filtering, rate limiting, mTLS support, and adaptive behavior based on real-time analytics. Built for privacy-aware routing, resilience to abuse, and observability across distributed environments.
- β‘ HTTP(S) + WebSocket + gRPC reverse proxy
- π Per-IP behavior tracking + learning
- βοΈ Distributed Redis-backed state
- π Self-healing config + cert reload
- π TLS termination and mTLS upstream
- π§ Training/production mode switching
- π¦ Integrated Redis-based rate limiting
- β Training mode (learn-only): observes request outcomes without blocking
- β Production mode (enforce): blocks based on credibility and blacklists
- β URL whitelisting on successful responses (2xx, 3xx)
- β URL blacklisting on repeated client-side failures (4xx)
- β Ignores 5xx responses to avoid poisoning the blacklist
- π Global learning pause if 5xx errors spike (configurable window and threshold)
- π§― Rate-limited learning (per IP and URL) to prevent Redis overuse or DDoS abuse
- π Graceful IP adaptation:
- Allows first 10 requests per new IP
- Tracks request outcome ratio per IP
- Blocks IPs falling below credibility thresholds
- Automatically unblocks well-behaved IPs
- β Global per-IP rate limit (e.g. 100 req/min)
- β Per-IP independent rate limit (separate from routing)
- β Global per-route rate limit (shared across all IPs)
- β
Configurable via
.envandconfig.json - β Efficient fixed-window algorithm using Redis keys
- β Bucket expiration to prevent memory bloat
- β Clear console logging when rate limits are hit
- β
Path-based routing using full regex (
^/api,^/admin, etc.) - π― Multiple upstream targets per route
- βοΈ Round-robin or weighted round-robin strategies
- 𧬠Sticky sessions via:
- IP Hash
- Cookie strategy with custom name
- π Smart circuit breaker per route:
- Opens after N failures within time window
- Auto-close after configured timeout
- Resets on any successful request
- Ignores client errors (4xx)
- Only counts server errors (5xx)
- π Retry policy with configurable delay and attempt count
- β
TLS termination via:
- Base64-encoded certificate in
config.json - Legacy support: cert file path + password from
.env
- Base64-encoded certificate in
- β
mTLS support:
- Each route can specify a client certificate
- Certificates are hot-reloaded on change
- π Header forwarding is clean and controllable (inject or strip as needed)
- π API Authentication:
- Configurable via
config.jsonor.env - Supports API key and token authentication
- Secure storage of credentials
- Configurable via
- β HTTP
- β HTTPS
- β WebSocket pass-through support
- β gRPC with streaming support
- β Chunked and large file uploads/downloads using streamed proxying
- β
Per-target health checks (optional)
- Supports HTTP health endpoints (
/health) - Supports TCP connection checks (e.g., port 443 alive)
- Supports gRPC health checks (
grpc.health.v1.Health/Check)
- Supports HTTP health endpoints (
- β Unhealthy targets are automatically excluded from routing
- π§ Tracks total and blocked requests per IP
- π§ Maintains allow-list flags for trusted IPs
- π§ Stores whitelisted/blacklisted URLs
- π§ Tracks global 5xx patterns for learning suppression
- π§ TTL-based counters (sliding expiration) for IP stats and limits
- β
Configuration priority:
config.jsonvalues take precedence- Falls back to
.envvalues if not found inconfig.json
- β
Credentials in
config.json:- API key and token
- TLS certificate (base64-encoded)
- Certificate password
- β
Legacy
.envsupport:- API credentials
- File-based TLS certificates
- π Hot-reloads
config.jsonon file change - π Hot-reloads mTLS certificates automatically
- β Minimal NuGet dependencies for performance and portability
- πΎ All state shared via Redis β supports horizontal scaling
- π§ Stateless proxy instance β restart-safe
- β Shared circuit breaking, load balancing, blacklisting across nodes
In production mode, the proxy evaluates each request against a set of escalating filters:
-
Training Mode?
- β Allow all traffic (no blocking).
- π Still observe outcomes for learning.
-
New IP?
- If fewer than 10 total requests seen β β Allow.
-
Credibility Score
- Calculated as:
Credibility = 1.0 - (blocked_requests / total_requests) - If
credibility >= BLOCK_THRESHOLDβ β Allow
- Calculated as:
-
URL in Local Whitelist?
- β Allow and log
-
URL in Local Blacklist?
- β Block and log
-
URL in Remote Blacklist?
- β Block and log
-
Credibility < BLOCK_HARD_THRESHOLD?
- If URL not in any list β β Block
-
Final fallback
- β Allow, but log as "borderline credibility"
- Proxy never blocks
- It observes request outcomes:
- β Adds 2xx/3xx URLs to whitelist
- β Adds 4xx URLs to blacklist
- Proxy enforces full blocking rules
- Uses Redis-stored whitelist, blacklist, and IP reputation
Controlled by Redis key:
CLIENT:config:mode
- Values in
config.jsontake precedence - Falls back to
.envvalues if not found inconfig.json
{
"Api": {
"Key": "your-api-key", // API key for remote blacklist URL lookup and Redis prefix
"Token": "your-api-token" // API token for remote API auth
},
"Tls": {
"CertificateBase64": "base64-encoded-cert-data", // Base64 encoded PFX/PKCS#12
"CertificatePassword": "your-cert-password" // Certificate password
},
"Routes": [
{
"PathRegex": "^/api",
"RateLimitPerMinute": 30,
"LoadBalancing": "WeightedRoundRobin",
"PreserveRequestPath": false,
"PreserveQueryString": true,
"StickySession": {
"Enabled": true,
"Strategy": "Cookie",
"CookieName": "STICKY"
},
"RetryPolicy": {
"MaxRetries": 2,
"RetryDelayMs": 200
},
"CircuitBreaker": {
"FailureThreshold": 10,
"OpenPeriodSeconds": 30,
"FailureWindowSeconds": 60
},
"ClientCertificate": {
"CertPath": "certs/client.pfx",
"CertPassword": "secret"
},
"Targets": [
{
"Url": "https://api-backend-1.internal",
"Weight": 3,
"HealthCheck": {
"Type": "http",
"Path": "/health",
"IntervalSeconds": 10
}
}
]
}
]
}| Key | Description | Default |
|---|---|---|
REDIS_CONNECTION |
Redis connection string | (required) |
| Key | Description | Default |
|---|---|---|
KEY |
API key for blacklist lookup and Redis prefix | (falls back to config.json) |
TOKEN |
API token for remote API auth | (falls back to config.json) |
| Key | Description | Default |
|---|---|---|
SSL_CERT_PATH |
Path to TLS certificate file | (falls back to config.json) |
SSL_CERT_PASSWORD |
Password for the certificate | (falls back to config.json) |
| Key | Type | Default | Description |
|---|---|---|---|
BLOCK_THRESHOLD |
double |
0.5 |
If credibility β₯ this, allow IP |
BLOCK_HARD_THRESHOLD |
double |
0.2 |
Below this β block even if URL is clean |
LEARNING_GLOBAL_5XX_THRESHOLD |
int |
20 |
Pause learning if 5xx errors exceed this |
| Key | Type | Default | Description |
|---|---|---|---|
RATE_LIMIT_ENABLED |
bool |
true |
Enable/disable all rate limiting |
RATE_LIMIT_GLOBAL_PER_MINUTE |
int |
100 |
Max requests per IP across all paths |
RATE_LIMIT_PER_IP_PER_MINUTE |
int |
200 |
Max requests per IP (independent of route) |
All Redis keys are prefixed with your API key for isolation and security:
| Redis Key | Purpose |
|---|---|
{api-key}:req:total:{ip} |
All requests from IP |
{api-key}:req:blocked:{ip} |
Blocked requests from IP |
{api-key}:req:allow:{ip} |
IP is trusted even if matching blacklist |
{api-key}:urls:whitelist |
Known good URLs |
{api-key}:urls:blacklist |
Known bad URLs |
{api-key}:config:mode |
Current operational mode |
{api-key}:ratelimit:{ip}:{minute} |
Global rate limit bucket per IP |
{api-key}:ratelimit:ip:{ip}:{minute} |
Per-IP general bucket |
{api-key}:ratelimit:{ip}:{path}:{minute} |
Per-route rate bucket |
Note: The API key from
config.json(or fallback to.envKEY) is used as a prefix for all Redis keys, providing isolation between different instances and improved security.
- β
config.jsonis automatically reloaded when changed - β TLS certificates are hot-reloaded when modified
- β No service restart required for configuration updates
- Use
config.jsonfor all configuration except Redis connection - Store certificates as base64 strings in configuration
- Utilize container secrets management
- Enable horizontal scaling
- Can use
.envfile for all configuration - Support for file-based certificates
- Maintains compatibility with existing setups
REDIS_CONNECTION: Redis connection string (default: redis://localhost:6379)
- β
Full gRPC protocol support:
- Unary calls
- Server streaming
- Client streaming
- Bidirectional streaming
- π§ Configurable settings:
- Maximum message size
- Compression options
- Keep-alive intervals
- π₯ Health checking:
- Native gRPC health protocol support
- Automatic service discovery
- π Protocol handling:
- Automatic HTTP/2 upgrade
- Header forwarding
- Status code mapping
- β‘ Performance optimizations:
- Streaming message handling
- Connection pooling
- Multiple HTTP/2 connections
- π Security:
- TLS 1.2/1.3 support
- Custom certificate validation
- Header sanitization
| Key | Description | Default |
|---|---|---|
REDIS_CONNECTION |
Redis connection string | (required) |
Note: Redis keys are now automatically prefixed with your API key for isolation and security.
All Redis keys are prefixed with your API key:
| Redis Key | Purpose |
|---|---|
{api-key}:req:total:{ip} |
All requests from IP |
{api-key}:req:blocked:{ip} |
Blocked requests from IP |
{api-key}:req:allow:{ip} |
IP is trusted even if matching blacklist |
{api-key}:urls:whitelist |
Known good URLs |
{api-key}:urls:blacklist |
Known bad URLs |
{api-key}:config:mode |
Current operational mode |
{api-key}:ratelimit:{ip}:{minute} |
Global rate limit bucket per IP |
{api-key}:ratelimit:ip:{ip}:{minute} |
Per-IP general bucket |
{api-key}:ratelimit:{ip}:{path}:{minute} |
Per-route rate bucket |