> For the complete documentation index, see [llms.txt](https://docs.openalgo.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openalgo.in/developers/design-documentation/23-ip-security.md).

# 23 - IP Security

## Request Boundary

`SecurityMiddleware` checks the resolved client IP against `logs.db` before Flask handles the request. An active ban returns plain-text HTTP 403 and removes the scoped logs session on both blocked and allowed paths.

Client-IP resolution is deliberately gated by `TRUST_PROXY_HEADERS`:

* Default `FALSE`: use only the immediate peer (`REMOTE_ADDR` / `request.remote_addr`).
* `TRUE`: accept `CF-Connecting-IP`, `True-Client-IP`, `X-Real-IP`, the first `X-Forwarded-For` value, then `X-Client-IP`.

Enable forwarded headers only when a controlled reverse proxy is the sole route to Gunicorn/Flask. Otherwise a direct client can spoof those headers and evade per-IP controls.

## Stored Security State

`database/traffic_db.py` stores three IP-related domains in `logs.db`:

| Table                     | Purpose                                                                    |
| ------------------------- | -------------------------------------------------------------------------- |
| `ip_bans`                 | Active temporary or permanent bans, reason, count, creator                 |
| `error_404_tracker`       | Per-IP 404 count and up to 50 distinct attempted paths in a 24-hour window |
| `invalid_api_key_tracker` | Per-IP invalid-key count and up to 20 key hashes in a 24-hour window       |

Raw API keys are not stored by the invalid-key tracker.

Ban lookups use a short TTL cache. Manual ban/unban and automatic changes invalidate the affected cache entry.

## Automatic Bans

Automatic bans are controlled by the persisted Security settings, not environment variables. Current defaults are:

| Setting                               |             Default |
| ------------------------------------- | ------------------: |
| Automatic banning                     |                 Off |
| 404 threshold in 24 hours             |                 100 |
| 404 ban duration                      | 0 hours (permanent) |
| Invalid API-key threshold in 24 hours |                 100 |
| Invalid API-key ban duration          | 0 hours (permanent) |
| Repeat-offender limit                 |              2 bans |

The authenticated Security dashboard can change the 404 threshold from 1 to 1,000, the invalid API-key threshold from 1 to 100, durations from 0 to 8,760 hours, and repeat limit from 1 to 10. A duration of zero means permanent.

When automatic banning is enabled and a tracker reaches its threshold, localhost addresses are never banned. The tracker resets after its 24-hour window. Existing ban records increment `ban_count`; reaching the configured repeat limit makes the ban permanent. Durations are not automatically doubled.

## Dashboard And Routes

The React Security page is `/logs/security`. Session-authenticated routes are registered under `/security`:

| Route                                     | Purpose                                                          |
| ----------------------------------------- | ---------------------------------------------------------------- |
| `POST /security/ban`                      | Ban one validated IPv4/IPv6 address                              |
| `POST /security/unban`                    | Remove one ban                                                   |
| `POST /security/ban-host`                 | Resolve recent traffic for a validated host and ban matching IPs |
| `POST /security/clear-404`                | Clear one 404 tracker                                            |
| `GET /security/api/data`                  | Read ban/tracker/settings data                                   |
| `GET /security/stats`                     | Read security totals                                             |
| `POST /security/settings`                 | Update automatic-ban settings                                    |
| `GET /security/api/login-activity`        | Read login audit data                                            |
| `POST /security/api/login-activity/clear` | Clear login audit data                                           |
| `GET /security/api/active-sessions`       | Read active application sessions                                 |

There is no CIDR whitelist feature in the current middleware. Rate limiting and IP bans are separate controls.

## Key Files

| File                                                  | Responsibility                         |
| ----------------------------------------------------- | -------------------------------------- |
| `utils/security_middleware.py`                        | Pre-Flask ban enforcement              |
| `utils/ip_helper.py`                                  | Trusted client-IP resolution           |
| `database/traffic_db.py`                              | Ban and attempt persistence            |
| `database/settings_db.py`                             | Persisted thresholds and defaults      |
| `blueprints/security.py`                              | Authenticated controls and data routes |
| `frontend/src/pages/monitoring/SecurityDashboard.tsx` | Current dashboard                      |
