2
Files
caddy-opnsense-blocker/README.md

98 lines
3.0 KiB
Markdown

# caddy-opnsense-blocker
`caddy-opnsense-blocker` is a local-first daemon that ingests Caddy access logs in their default JSON format, evaluates suspicious requests, keeps persistent local state in SQLite, provides a lightweight web UI for review, and blocks or unblocks IP addresses through an OPNsense alias.
## Features
- Real-time ingestion of multiple Caddy JSON log files.
- One heuristic profile per log source.
- Persistent local state in SQLite.
- Local-only web UI for reviewing events and IPs.
- Manual block, unblock, and override reset actions.
- OPNsense alias backend with automatic alias creation.
- Concurrent polling across multiple log files.
## Current scope
This first version is intentionally strong on ingestion, persistence, UI, and OPNsense integration.
The decision engine is deliberately simple and deterministic for now:
- suspicious path prefixes
- unexpected `POST` requests
- `.php` path detection
- explicit known-agent allow/deny rules
- excluded CIDR ranges
- manual overrides
This keeps the application usable immediately while leaving room for a more advanced network-intelligence engine later.
## Architecture
- `internal/caddylog`: parses default Caddy JSON access logs
- `internal/engine`: evaluates requests against a profile
- `internal/store`: persists events, IP state, manual decisions, backend actions, and source offsets
- `internal/opnsense`: manages the target OPNsense alias through its API
- `internal/service`: runs concurrent log followers and applies automatic decisions
- `internal/web`: serves the local review UI and JSON API
## Quick start
1. Generate or provision OPNsense API credentials.
2. Copy `config.example.yaml` to `config.yaml` and adapt it.
3. Start the daemon:
```bash
CGO_ENABLED=0 go run ./cmd/caddy-opnsense-blocker -config ./config.yaml
```
4. Open the local UI on the configured address, for example `http://127.0.0.1:9080`.
## Example configuration
See `config.example.yaml`.
Important points:
- Each source points to one Caddy log file.
- Each source references exactly one profile.
- `initial_position: end` means “start following new lines only” on first boot.
- The web UI should stay bound to a local address such as `127.0.0.1:9080`.
## Web UI and API
The web UI is intentionally small and server-rendered.
It refreshes through lightweight JSON polling and exposes these endpoints:
- `GET /healthz`
- `GET /api/overview`
- `GET /api/events`
- `GET /api/ips`
- `GET /api/ips/{ip}`
- `POST /api/ips/{ip}/block`
- `POST /api/ips/{ip}/unblock`
- `POST /api/ips/{ip}/reset`
## Development
Run the test suite:
```bash
CGO_ENABLED=0 go test ./...
```
Build the daemon:
```bash
CGO_ENABLED=0 go build ./cmd/caddy-opnsense-blocker
```
`CGO_ENABLED=0` is useful on systems without a C toolchain. The application itself only relies on pure-Go dependencies.
## Roadmap
- richer decision engine
- asynchronous DNS / RDAP / ASN enrichment
- richer review filters in the UI
- alternative blocking backends besides OPNsense
- direct streaming ingestion targets in addition to file polling