Stream-based security event multiprocessing engine for any HTTP server — and far beyond
Eight behavioural detectors analyse every HTTP access log in real time and route confirmed attackers to any output — Fail2Ban, Cloudflare WAF, MikroTik RouterOS, or your own exec+JSON sink in any language. Bare-metal, Docker Compose, or Kubernetes DaemonSet.
Six servers supported natively — nginx works without any config. Every other server enables with a single profile line. Works behind any proxy or Cloudflare — always scores the real attacker, never the CDN or load balancer.
nginx combined log format works out of the box — no profile needed.
Standard CLF — no server-side changes required.
Default access log (CLF) — no configuration needed.
Apache CLF by default — no server-side changes required.
Requires xcaddy + transform-encoder plugin for CLF output.
Requires option httplog in haproxy.cfg + rsyslog to write to file.
Each detector adds points to an IP's score. Score decays linearly over the observation window — no false bans from old traffic.
Requests to sensitive paths: /.env, /.git/config, /.aws/credentials, /wp-config.php, /phpinfo.php, admin panels, backup archives and 30+ others. Active reconnaissance attempts trigger immediately on the first request.
More than 100 requests per 60 seconds from a single IP. Catches DDoS probes, aggressive vulnerability scanners, credential stuffing bursts and scraping tools trying to stay under static limits.
Case-insensitive substring match against built-in lists: scanners (Nuclei, sqlmap...), grabbers (Scrapy, HTTrack...) and automation clients (python-requests, curl...). Extend via config easily.
More than 60% of responses are 404 with at least 10 requests. Typical signature of path-enumeration tools (dirbuster, gobuster, ffuf) blindly traversing wordlists. min_requests prevents false positives.
Five or more sequentially numbered URLs in a row — /page/1, /page/2, /article/100... Characteristic of automated content scrapers dumping entire site sections at machine speed.
Loads pages but requests CSS, JS or images on fewer than 10% of hits — with at least 3 page views. Real browsers fetch resources; markup-only scrapers skip static assets entirely.
URLs longer than 2048 characters, or containing known WAF evasion keywords: bypass, shell, cmd, eval, exec... Targets buffer overflows and code injections.
Matches User-Agent (and optionally Referer) against a community-maintained blocklist of ~685 known bad bots — scrapers, SEO crawlers, spam bots, vulnerability probes. Updated daily. Powered by nginx-ultimate-bad-bot-blocker by Mitchell Krog.
The package handles everything: binary, systemd unit, Fail2Ban config, and system user.
# Works on Debian, Ubuntu, Fedora, RHEL, AlmaLinux, Rocky Linux, Arch Linux # Auto-detects your distro and architecture (amd64 / arm64) curl -fsSL https://raw.githubusercontent.com/mr-addams/arxsentinel/main/scripts/get.sh | sudo bash
The script downloads the correct package from GitHub Releases, installs it with your package manager, checks for fail2ban, auto-detects your access.log path, and starts the service.
# Requires Go 1.26+ git clone https://github.com/mr-addams/arxsentinel cd arxsentinel sudo ./scripts/install.sh sudo systemctl enable --now arxsentinel
# Docker — distroless image (~12 MB), runs as uid 65532, amd64 + arm64 docker run -d \ -v /var/log/nginx/access.log:/var/log/nginx/access.log:ro \ -v /var/log/arxsentinel:/var/log/arxsentinel \ -p 127.0.0.1:9117:9117 \ ghcr.io/mr-addams/arxsentinel:latest
Prometheus metrics available at :9117/metrics immediately after start.
For Docker Compose and Kubernetes (Helm DaemonSet) setup — see the full guides:
README.docker.md ·
Kubernetes (Helm) README
/etc/arxsentinel/config.yaml and set your log path. nginx works without any profile. For Apache, Traefik, Caddy, HAProxy or LiteSpeed — set parser.profile to the server name. Config reloads on SIGHUP — no restart needed.
Add threat IPs to a Cloudflare IP List and ban them at the network edge — no iptables, no host firewall. Batch operations, async polling, automatic TTL expiry and cross-instance dedup.
Write banned IPs to a plain blocklist file with TTL auto-expiry and atomic writes. arxsentinel only writes the file; you include it into nginx however suits you. Optional reload command.
Manage a RouterOS firewall address-list over the REST API. TTL-based auto-unban, safe removal of only arxsentinel-owned entries, works on CHR and ARM-based routers.
Not using a built-in profile? Define your own regex with named capture groups, or switch to JSON log parsing — both work without recompilation. Any format that captures IP, timestamp, method, path, status and bytes maps to the full detection pipeline.
Watch multiple log files in one process. Within each stream, define independent pipelines — each with its own detectors, sources, sinks and IP state. Share IP state between pipelines via tracker_group for correlated multi-log analysis.
Ship-ready profiles for popular servers. Override field positions, date formats and delimiter rules per log source without touching core logic.
Deploy alongside any containerised HTTP server via a shared log volume — no changes to your app container. Ready-to-use docker-compose.yml and config in deploy/examples/docker/. Prometheus metrics exposed on :9117 for scraping.
One pod per node reads host access logs via hostPath. Helm chart included with values reference and Prometheus Operator integration. Sidecar topology also supported for managed clusters without host log access.
Run `arxsentinel validate` to check your whole config before deploy. A topology-aware validator models the real data flow and catches broken wiring using static plugin manifests — no live traffic needed.
Buffer executor events through an in-memory, file-based (bbolt) or Redis queue — pick per executor to fit bare-metal, single-host or multi-replica Kubernetes setups.
Route threat events between independent pipelines by name — one pipeline can detect while another enforces, fully decoupled.
Googlebot, Bingbot, Yandex, DuckDuckBot, GPTBot and 6 others are verified via reverse + forward DNS. Legitimate crawlers are never scored. Fakes get a penalty instead. Trusted crawlers can be matched by User-Agent only (`ua_only`, no DNS) and given per-bot detector exemptions (`exempt_detectors`) so legitimate automation is never penalised.
Add your office IPs, VPN subnets (CIDR), monitoring services, SEO tools by User-Agent substring, or URL paths. Changes apply instantly on SIGHUP.
All config changes — whitelist, detector scores, thresholds — apply instantly on SIGHUP. No restart. IP state and DNS cache are preserved.
Detectors always score the real attacker — never Cloudflare or your load balancer. Supports CF-Connecting-IP, X-Forwarded-For chains, and trusted proxy CIDR ranges out of the box.
Read from any log source. Write threats to any destination. Fail2Ban remains the default — now one option among many.
type: file · path: /var/log/nginx/access.log
type: syslog · addr: udp://0.0.0.0:5514 · no shared volume
type: http · protocol: plain|cloudflare|firehose|pubsub|loki|otlp|azure|splunk|ndjson
Push threats to Telegram, Slack and PagerDuty — with built-in deduplication and rate-limiting so a burst never floods your channel.
Push threat IPs directly into AWS WAF IP set rules. Integrates with existing WAF rule groups — no Lambda or custom infrastructure required.