Traefik plugin · Edge reporter
Correlate your site's incoming traffic against the BoarNet threat-intelligence network. Your production edge becomes a contributing sensor — without adding request latency or blocking legitimate traffic.
Overview
The BoarNet Traefik plugin is observational middleware that runs inside your Traefik instance. For every incoming request it asynchronously matches the visitor IP against BoarNet's public threat-intel API (/api/v1/lookup). When an IP is already known to us, the plugin reports the sighting — your edge contributes a fresh observation that feeds back into the mesh.
It does not block traffic. If you also want blocking, run a bouncer like CrowdSec alongside it; they are fully compatible.
How it works
The middleware hook does one thingon the request path: a non-blocking send to a buffered in-memory channel (~200 ns). It immediately calls the next handler. The request lifecycle never touches the network for BoarNet purposes.
A background goroutine owns every HTTP round-trip:
- Dequeues events from the channel.
- Checks a per-IP TTL cache (default 60s, matches our
Cache-Controlheader). - On cache miss, calls
/api/v1/lookup?ip=<ip>and stores the verdict. - If
seen: true, queues the sighting for batched submission (default 30s flush).
If BoarNet is unreachable, the plugin fails silent: no sighting is recorded, the next request is served normally, your users never see it. Under sustained burst traffic the channel drops oldest enqueues rather than blocking — we'd rather miss a sighting than add latency.
Install
Declare the plugin in your Traefik static configuration:
experimental:
plugins:
boarnet:
moduleName: github.com/Bino97/boarnet-traefik
version: v0.1.0Declare the middleware in your dynamic configuration:
http:
middlewares:
boarnet-reporter:
plugin:
boarnet:
ingestURL: "https://www.boarnet.io/api/v1"
token: "bn_REPLACE_ME"
edgeID: "REPLACE-ME-WITH-A-UUID"Attach it to your router(s):
http:
routers:
my-app:
rule: Host(`example.com`)
service: my-app
middlewares:
- boarnet-reporterMinting a token
Sign in to /dashboard/sensors and mint a new token. The same token family is used for honeypot sensors and edge reporters — both are legitimate sources of telemetry. Label it something you'll recognize (edge-prod-web-01, edge-staging, etc.) and paste the bn_…value into the plugin's token field.
Picking an edge ID
The edgeID is the opaque identifier BoarNet uses to group sightings from this install. It is not your server's hostname or IP — pick a random UUID at install time. A shell one-liner:
python -c 'import uuid; print(uuid.uuid4())'
Configuration
| Key | Default | Meaning |
|---|---|---|
ingestURL | https://www.boarnet.io/api/v1 | Base of BoarNet's v1 API. |
token | required | Bearer token minted at /dashboard/sensors. |
edgeID | required | Opaque install identifier — pick a UUID, not a hostname. |
flushIntervalSeconds | 30 | How often queued sightings are POSTed. |
cacheTTLSeconds | 60 | LRU verdict-cache freshness. |
cacheSize | 100000 | Max entries in the verdict cache. |
queueSize | 10000 | Buffered channel capacity before the worker. Excess drops silently. |
trustedProxiesHeader | X-Forwarded-For | Header carrying the real client IP. Empty = use RemoteAddr directly. |
Privacy
Your visitors' IPs doleave your network — that's the product. BoarNet needs them to correlate sightings across the mesh.
Your server's own IP does notget stored or correlated. The ingest endpoint deliberately skips GeoIP on the submitter's IP and does not write a sensor row tied to the submitter's address. Submissions are identified only by your bearer token and the opaque edgeID you chose.
The one trace we can't avoid is the TCP-layer source of the submit request, which our CDN (Vercel) sees transiently as part of normal request handling. If that still matters to you, route the plugin's outbound through your corporate egress or a VPN.
Full details in the Privacy Policy.
Pairing with CrowdSec
CrowdSec's bouncer is blocking — it decides whether to serve each request. This plugin is observational — it never blocks or delays. They run in the same Traefik instance without conflict.
http:
routers:
my-app:
middlewares:
- crowdsec-bouncer # blocks known-bad
- boarnet-reporter # observes + contributesOrder matters only if you care about whether blocked requests should still generate sightings — put the bouncer first if they should not, or the reporter first if they should.
Troubleshooting
Plugin running but no sightings on the dashboard
Most likely your traffic is too low or too clean for known-bad IPs to hit. The plugin is a pure pass-through for visitors we don't already know about — it only reports when our /lookup returns seen: true. Expected match rate depends heavily on the site's exposure: public- facing login pages see matches within hours; a private intranet might see none for weeks.
Lookup returns 401 / 429
401: the token is invalid or revoked. Mint a new one at /dashboard/sensors. 429: you've exceeded your tier's rate limit. Authenticated Participant and above get 1000+ lookups/hr; if you're running a Traefik on observer tier traffic volume, upgrade or deploy a sensor to unlock Participant.
Traefik start-up error about Yaegi
The plugin is pure standard-library Go — it should run under any recent Traefik. If you see an interpreter error, pin version: v0.1.0 exactly (not latest) and open an issue at github.com/Bino97/boarnet-traefik.