You've already forked caddy-opnsense-blocker
281 lines
4.9 KiB
Markdown
281 lines
4.9 KiB
Markdown
# HTTP API
|
|
|
|
The daemon serves a small JSON API used by the built-in web UI.
|
|
|
|
## General behavior
|
|
|
|
- All endpoints are served from the same address as the web UI.
|
|
- Responses are JSON.
|
|
- Error responses use the shape `{"error":"..."}`.
|
|
- Unsupported HTTP methods return `405 Method Not Allowed`.
|
|
- There is no built-in authentication or TLS.
|
|
|
|
## `GET /healthz`
|
|
|
|
Liveness probe.
|
|
|
|
Example response:
|
|
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"time": "2026-03-12T18:22:11Z"
|
|
}
|
|
```
|
|
|
|
## `GET /api/overview`
|
|
|
|
Returns summary counters plus recent IP and recent event samples.
|
|
|
|
Query parameters:
|
|
|
|
- `limit`
|
|
- optional
|
|
- default: `50`
|
|
- maximum: `1000`
|
|
- `hours`
|
|
- optional
|
|
- default: `24`
|
|
- used for the top activity leaderboards returned in the same payload
|
|
- `show_known_bots`
|
|
- optional
|
|
- default: `true`
|
|
- when `false`, the leaderboards exclude IPs currently identified as known bots
|
|
- `show_allowed`
|
|
- optional
|
|
- default: `true`
|
|
- when `false`, the leaderboards exclude IPs whose current state is `allowed`
|
|
|
|
Main response fields:
|
|
|
|
- `total_events`
|
|
- `total_ips`
|
|
- `blocked_ips`
|
|
- `review_ips`
|
|
- `allowed_ips`
|
|
- `observed_ips`
|
|
- `activity_since`
|
|
- `top_ips_by_events`
|
|
- `top_ips_by_traffic`
|
|
- `top_sources`
|
|
- `top_urls`
|
|
- `recent_ips`
|
|
- `recent_events`
|
|
|
|
## `GET /api/events`
|
|
|
|
Returns recent raw events.
|
|
|
|
Query parameters:
|
|
|
|
- `limit`
|
|
- optional
|
|
- default: `100`
|
|
- maximum: `1000`
|
|
|
|
Each event includes:
|
|
|
|
- source and profile names
|
|
- timestamps
|
|
- remote and client IPs
|
|
- host, method, URI, path, status, and User-Agent
|
|
- decision, primary reason, all reasons, and whether it was enforced
|
|
- raw Caddy JSON
|
|
- current IP state and manual override
|
|
|
|
## `GET /api/ips`
|
|
|
|
Returns current IP state rows.
|
|
|
|
Query parameters:
|
|
|
|
- `limit`
|
|
- optional
|
|
- default: `100`
|
|
- maximum: `1000`
|
|
- `state`
|
|
- optional
|
|
- filter by one state such as `review`, `blocked`, `allowed`, or `observed`
|
|
|
|
Each row includes:
|
|
|
|
- `ip`
|
|
- `first_seen_at`
|
|
- `last_seen_at`
|
|
- `last_source_name`
|
|
- `last_user_agent`
|
|
- `latest_status`
|
|
- `total_events`
|
|
- `state`
|
|
- `state_reason`
|
|
- `manual_override`
|
|
- `last_event_id`
|
|
- `updated_at`
|
|
|
|
## `GET /api/recent-ips`
|
|
|
|
Returns aggregated IP rows over a recent time window.
|
|
|
|
Query parameters:
|
|
|
|
- `hours`
|
|
- optional
|
|
- default: `24`
|
|
- values less than or equal to zero fall back to `24`
|
|
- `limit`
|
|
- optional
|
|
- default: `200`
|
|
- maximum: `1000`
|
|
|
|
Each row includes:
|
|
|
|
- `ip`
|
|
- `source_name`
|
|
- `state`
|
|
- `events`
|
|
- `last_seen_at`
|
|
- `reason`
|
|
- `manual_override`
|
|
- optional `bot`
|
|
- `actions`
|
|
|
|
`actions` contains:
|
|
|
|
- `can_block`
|
|
- `can_unblock`
|
|
- `can_clear_override`
|
|
|
|
## `GET /api/ips/{ip}`
|
|
|
|
Returns the complete details for one IP address.
|
|
|
|
Response fields:
|
|
|
|
- `state`
|
|
- `recent_events`
|
|
- `decisions`
|
|
- `backend_actions`
|
|
- optional `investigation`
|
|
- `opnsense`
|
|
- `actions`
|
|
|
|
The current implementation returns up to:
|
|
|
|
- 100 recent events
|
|
- 100 decision records
|
|
- 100 backend action records
|
|
|
|
## `POST /api/ips/{ip}/investigate`
|
|
|
|
Forces a fresh investigation for the selected IP and returns the updated `IPDetails` payload.
|
|
|
|
This bypasses the cached investigation for that request.
|
|
|
|
No request body is required.
|
|
|
|
## Action endpoints
|
|
|
|
These endpoints accept an optional JSON body:
|
|
|
|
```json
|
|
{
|
|
"actor": "alice@example.net",
|
|
"reason": "short human-readable explanation"
|
|
}
|
|
```
|
|
|
|
If omitted:
|
|
|
|
- `actor` defaults to `web-ui`
|
|
- `reason` defaults to an action-specific fallback
|
|
|
|
All action endpoints return the updated `IPDetails` payload on success.
|
|
|
|
### `POST /api/ips/{ip}/block`
|
|
|
|
- Sets a manual force-block override.
|
|
- Default reason: `manual block`.
|
|
- If OPNsense is enabled, the daemon adds the IP to the configured alias if it is missing.
|
|
|
|
### `POST /api/ips/{ip}/unblock`
|
|
|
|
- Sets a manual force-allow override.
|
|
- Default reason: `manual allow`.
|
|
- If OPNsense is enabled, the daemon removes the IP from the configured alias if it is present.
|
|
|
|
### `POST /api/ips/{ip}/clear-override`
|
|
|
|
- Removes the local manual override.
|
|
- Default reason: `manual override cleared`.
|
|
- Does not directly call OPNsense.
|
|
|
|
### `POST /api/ips/{ip}/reset`
|
|
|
|
Backwards-compatible alias for `clear-override`.
|
|
|
|
## Response model details
|
|
|
|
### `investigation`
|
|
|
|
When present, `investigation` may contain:
|
|
|
|
- `ip`
|
|
- `updated_at`
|
|
- `error`
|
|
- `bot`
|
|
- `reverse_dns`
|
|
- `registration`
|
|
- `reputation`
|
|
|
|
### `bot`
|
|
|
|
- `provider_id`
|
|
- `name`
|
|
- `icon`
|
|
- `method`
|
|
- `verified`
|
|
|
|
### `reverse_dns`
|
|
|
|
- `ptr`
|
|
- `forward_confirmed`
|
|
|
|
### `registration`
|
|
|
|
- `source`
|
|
- `handle`
|
|
- `name`
|
|
- `prefix`
|
|
- `organization`
|
|
- `country`
|
|
- `abuse_email`
|
|
|
|
### `reputation`
|
|
|
|
- `spamhaus_lookup`
|
|
- `spamhaus_listed`
|
|
- optional `spamhaus_codes`
|
|
- optional `error`
|
|
|
|
### `opnsense`
|
|
|
|
- `configured`
|
|
- `present`
|
|
- `checked_at`
|
|
- optional `error`
|
|
|
|
## Example manual block request
|
|
|
|
```bash
|
|
curl -X POST \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"actor":"cli","reason":"confirmed credential stuffing"}' \
|
|
http://127.0.0.1:9080/api/ips/203.0.113.10/block
|
|
```
|
|
|
|
## Example recent IP query
|
|
|
|
```bash
|
|
curl 'http://127.0.0.1:9080/api/recent-ips?hours=24&limit=250'
|
|
```
|