ezy-shield

module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: AGPL-3.0

README

EzyShield

CI CodeQL

EzyShield

Intrusion blocking for Linux servers — fail2ban, a decade later.

EzyShield watches your server logs, detects attacking IPs, and bans them with escalating penalties: locally via nftables and at the edge via Cloudflare. A deterministic rule engine scores every event offline and always works; AI is consulted only for the ambiguous cases, so decisions stay cheap and the tool runs fully offline if you never configure a provider. It ships as a single static Go binary — no Python, no Java, no runtime to install.

Status: early release (v0.1). Everything described below is implemented, tested in CI, and running today on multiple Linux servers managed by the maintainer. Start in dry-run (the default), watch the decisions, and arm it once you trust them. Interfaces may still change before 1.0 — bug reports via issues are very welcome.


Quickstart

curl -sfL https://get.ezyshield.com | sudo sh    # install (verifies SHA-256)
sudo ezyshield init                              # guided setup — installs & starts the service
ezyshield status                                 # see what it *would* have banned (dry-run)
sudoedit /etc/ezyshield/policy.yaml              # set `armed: true` when you trust it
sudo systemctl restart ezyshield                 # apply the new policy

Before v0.1.0 ships, every release is a release candidate — the install command above detects that and prints instructions instead of installing; see Install for the release-candidate command that works today. No flags will be needed the moment v0.1.0 ships.

That's the whole loop: init leaves the daemon running in dry-run; observe first, arm only once the decisions look right.


Why EzyShield

EzyShield fail2ban CrowdSec SSHGuard
Language / runtime Go, single static binary Python Go C
Setup ezyshield init, dry-run by default jails + regex filters agent + Local API + remediation components (bouncers) small config + firewall backend
Strike escalation built in: 5min → 1h → 24h → 7d → permanent, history kept forever optional (bantime.increment, since 0.11) per-scenario durations via profiles; escalation via custom expressions yes — block time doubles per repeat offense
Edge enforcement (CDN/WAF) built in (Cloudflare) via bundled actions (incl. Cloudflare) yes — remediation components incl. Cloudflare no — local firewall backends only
Shared threat intel no — not built in today report-to actions (AbuseIPDB, DShield); no community blocklist yes — community blocklist + CTI; this is their core strength no
Mandatory telemetry / account none none signal sharing on by default (opt-out); console account optional none
Anti-lockout guarantees automatic — SSH peer + admin CIDRs allowlisted before every rule write manual ignoreip manual whitelists manual whitelisting
AI usage optional, ambiguous cases only; rule engine needs zero AI none none none

fail2ban is battle-tested and great at what it does; CrowdSec's community blocklist is genuinely valuable and something EzyShield simply doesn't have; SSHGuard is admirably small and fast. EzyShield's bet is different: strike escalation, local and edge enforcement, and guardrails that make it hard to ban yourself — out of the box, from a single binary. You can even run EzyShield as the brain and keep fail2ban for enforcement.

Comparison verified against each project's docs as of July 2026 — fail2ban, CrowdSec, SSHGuard. Corrections welcome via issues.


How it works

logs (SSH, Nginx, Apache, Caddy, Traefik)
        │
        ▼
   [ Collector ]   ── tail file / journald
        │
        ▼
    [ Parser ]     ── structured event (IP, method, status, ...)
        │
        ▼
   [ Enricher ]    ── GeoIP / ASN / reputation
        │
        ▼
  [ Rule Engine ]  ── offline scoring (always runs)
        │
        ├──(ambiguous only)──▶ [ AI Analyzer ] ── Anthropic / OpenAI-compatible / Ollama
        │
        ▼
 [ Decision Engine ] ── strikes + TTL escalation + policy
        │
        ├──▶ [ Enforcer ] ── nftables (local) / Cloudflare (edge)
        └──▶ [ Notifier ] ── Telegram / Email / Slack / Discord / webhook

The whole path from parser to decision is side-effect-free and tested against fixture logs. Firewall changes only happen through a small privilege-separated helper (ezyshield-enforcer) that holds CAP_NET_ADMIN and accepts a fixed, minimal verb set — the main daemon can never run arbitrary firewall commands.

Strike escalation (configurable)
Strike Ban duration
1 5 minutes
2 1 hour
3 24 hours
4 7 days
5 permanent

Strike history is kept forever in SQLite, so a repeat offender from last month still escalates today.


Features (today)

  • Escalating bans — short first ban, permanent after repeated offences
  • Local enforcement — nftables, via a privilege-separated enforcer helper
  • Edge enforcement — push IP bans to a Cloudflare list
  • SSH, Nginx, Apache, Caddy & Traefik parsers with fuzz-tested, panic-safe parsing of hostile input
  • Deterministic rule engine — thresholds + scanner signatures; works with zero AI configured
  • AI-assisted decisions (optional) — Anthropic, any OpenAI-compatible endpoint, or local Ollama, with provider failover, a token budget, and verdict caching
  • Prompt-injection defense — log lines are treated as data, never instructions; AI output is schema-validated and clamped by policy (it can only suggest within limits)
  • Anti-lockout — active SSH peer + admin CIDRs auto-allowlisted before any rule write; allowlist always wins
  • Dry-run by default — nothing is enforced until you set armed: true
  • Ban rate limitmax_bans_per_minute (default 30) so a bad rule or poisoned feed can't ban the internet
  • Notifications — Telegram, Email (SMTP), Slack, Discord, generic webhook
  • Audit trail — every action recorded in SQLite; JSON output for scripting
  • Localhost-only dashboard — small web UI over 127.0.0.1 with status, active bans, allowlist, event log, live WebSocket updates and a strike timeline; CSRF-protected manual ban/unban/allow; access remotely via SSH tunnel or Cloudflare Tunnel (see docs and the remote-access guide)
  • Scriptable--json on commands; unix-socket control, no TCP port ever

Your data is yours

No telemetry, no phone-home, no account, no data sharing required for any feature. The rule engine scores everything offline; the only outbound connections are the ones you configure (edge enforcement, notifiers, AI providers) or run yourself (ezyshield update). AI is opt-in, and when enabled the provider never sees your logs: it receives only aggregated counters per IP — event kinds, counts, and GeoIP/ASN metadata if you've configured the MaxMind databases — never raw log lines. CI gates enforce that secrets and hostile log content can't reach the request (prompt-injection and secret-leak tests). The complete map — every outbound connection, its trigger and payload, and the exact zero-outbound configuration — is in the data-flow reference.

Our pledge

The local agent will never lose features to a paywall. The code is and stays open under AGPL-3.0. If a paid offering ever exists, it will be about coordination at scale — fleets, identity, compliance, support — never about the protection itself. If EzyShield defends one server well, that part stays free, forever. — Evert


Install

Package manager (apt / dnf)
# Debian / Ubuntu
curl -fsSL https://packages.ezyshield.com/ezyshield.asc | sudo gpg --dearmor -o /usr/share/keyrings/ezyshield.gpg
echo "deb [signed-by=/usr/share/keyrings/ezyshield.gpg] https://packages.ezyshield.com/apt testing main" | sudo tee /etc/apt/sources.list.d/ezyshield.list
sudo apt update && sudo apt install ezyshield

GPG-signed repositories with .deb and .rpm for amd64/arm64 — dnf setup and details in the install guide. Every release today is a release candidate, so this uses the testing suite; switch to stable once v0.1.0 ships. See the supported platforms matrix for the distros and architectures exercised by the end-to-end install test.

Specific version (including release candidates)
curl -sfL https://get.ezyshield.com | sudo EZYSHIELD_VERSION=v0.1.0-rc.N sh

Check the releases page for the current tag. This is the install-script method that works today, before v0.1.0 ships.

Install script
curl -sfL https://get.ezyshield.com | sudo sh

Fetches the latest release binaries (ezyshield and ezyshield-enforcer) and verifies their SHA-256 checksums. Before v0.1.0 ships (every release today is a release candidate), this prints install instructions instead — see "Specific version" above.

See the install guide for all options (air-gapped mirrors, from source, upgrading).

From source (works today)
git clone https://github.com/evertramos/ezy-shield.git
cd ezy-shield
go build -o ezyshield ./cmd/ezyshield
go build -o ezyshield-enforcer ./cmd/ezyshield-enforcer
sudo mv ezyshield ezyshield-enforcer /usr/local/bin/

Requires Go 1.26+ and Linux with nftables for local enforcement.

Then:

sudo ezyshield init      # create config under /etc/ezyshield
sudo ezyshield doctor    # validate config, permissions, and dependencies

Naming: the binary is ezyshield and behaves exactly as ezy shield would in the wider ezy tool family — ezyshield initezy shield init.


Basic usage

# The daemon runs as a systemd service (installed and started by `init`)
sudo systemctl status ezyshield

# Inspect the running daemon
ezyshield status

# Manual ban / unban
sudo ezyshield ban 203.0.113.42
sudo ezyshield unban 203.0.113.42

# Permanently allow an IP or CIDR
sudo ezyshield allow 198.51.100.0/24

# See active bans / allowlist / recent events
ezyshield list

# Test a notification channel without waiting for a real event
sudo ezyshield test notifier telegram

Configuration

File Purpose
/etc/ezyshield/config.yaml Log sources, enforcement backends, AI providers, notifications
/etc/ezyshield/policy.yaml Score thresholds, strike table, allowlists, rate limits
/etc/ezyshield/rules.d/*.yaml Optional drop-in rule customizations — the built-in detection rules ship embedded in the binary and update with it; files here merge over them by name. (rules_path, whole-file replacement, is deprecated.)

Secrets (API tokens, SMTP passwords) are never stored in YAML — reference them as env:VARNAME or via systemd LoadCredential=. Inline secret values are rejected when the config loads, and ezyshield doctor warns on bad file permissions.

Minimal config.yaml:

data_dir: /var/lib/ezyshield

collectors:
  - kind: journald
    unit: sshd
  - kind: file
    path: /var/log/nginx/access.log

enforce:
  nftables:
    table: inet ezyshield
    set: blocked

notify:
  telegram:
    bot_token: env:EZYSHIELD_TELEGRAM_BOT_TOKEN
    chat_ids: ["-1001234567890"]

Start in dry-run (armed: false in policy.yaml), watch what it would block, then arm it and restart the daemon (sudo systemctl restart ezyshield — policy changes are read at startup). The full setup walkthrough — collectors, AI, notifications, custom rules — is in docs/content/en/getting-started/index.md.


Roadmap

Everything listed under Features is implemented, tested, and shipping in the current release. We are preparing the roadmap for the next versions — it will be published here. Ideas and requests are welcome in the issues.


Security

EzyShield is a root-capable security daemon and is built accordingly: privilege separation for firewall writes, unix-socket control (no listening TCP port), a localhost-only dashboard, anti-lockout, action rate limiting, and secrets kept out of config and logs. Every change goes through a mandatory security review.

Found a vulnerability? Please follow SECURITY.md — do not open a public issue for security reports.


Contributing

Contributions are welcome. Read CONTRIBUTING.md first; a CLA is required. Every PR ships code + tests + doc updates together, and CI (lint, tests, CodeQL, fuzz, security gates) must be green to merge.


❤️ Sponsors

EzyShield is free and open source, and always will be (AGPL-3.0). If it keeps your servers safer, consider sponsoring — it funds focused time to build this in the open, independently.

→ Become a sponsor


License

EzyShield is released under AGPL-3.0 — see LICENSE.

Directories

Path Synopsis
cmd
ezyshield command
Command ezyshield is the EzyShield CLI and daemon.
Command ezyshield is the EzyShield CLI and daemon.
ezyshield-enforcer command
ezyshield-enforcer is the privileged helper that applies nftables rules on behalf of the main ezyshield daemon.
ezyshield-enforcer is the privileged helper that applies nftables rules on behalf of the main ezyshield daemon.
Package configs provides embedded example configuration files for ezyshield init.
Package configs provides embedded example configuration files for ezyshield init.
internal
aggregate
Package aggregate provides per-IP sliding-window event aggregation.
Package aggregate provides per-IP sliding-window event aggregation.
ai
Package ai implements AI providers for EzyShield's threat analysis pipeline.
Package ai implements AI providers for EzyShield's threat analysis pipeline.
cdndetect
Package cdndetect resolves domain names and classifies the resulting IP addresses against a compile-time embedded table of CDN edge ranges.
Package cdndetect resolves domain names and classifies the resulting IP addresses against a compile-time embedded table of CDN edge ranges.
collector
Package collector provides log collectors that implement sdk.Collector.
Package collector provides log collectors that implement sdk.Collector.
config
Package config provides YAML loading and strict validation for ezyshield configuration files.
Package config provides YAML loading and strict validation for ezyshield configuration files.
daemon
Package daemon wires all EzyShield subsystems into the long-running watch daemon and exposes a unix-socket control API.
Package daemon wires all EzyShield subsystems into the long-running watch daemon and exposes a unix-socket control API.
dashboard
Package dashboard implements the localhost-only web UI for EzyShield.
Package dashboard implements the localhost-only web UI for EzyShield.
decision
Package decision is the safety-critical policy engine that converts Verdicts into enforceable Actions.
Package decision is the safety-critical policy engine that converts Verdicts into enforceable Actions.
enforce
Package enforce implements sdk.Enforcer backed by nftables.
Package enforce implements sdk.Enforcer backed by nftables.
enrich
Package enrich provides O(1) GeoIP/ASN lookups via MaxMind MMDB files.
Package enrich provides O(1) GeoIP/ASN lookups via MaxMind MMDB files.
nftnames
Package nftnames is the single source of truth for the nftables table and set names EzyShield enforces into (issue #268).
Package nftnames is the single source of truth for the nftables table and set names EzyShield enforces into (issue #268).
notify
Package notify fans-out alert messages to configured notification channels (Telegram, email, ...) with per-channel rate limiting and a global dedup window.
Package notify fans-out alert messages to configured notification channels (Telegram, email, ...) with per-channel rate limiting and a global dedup window.
ownership
Package ownership centralizes the EzyShield daemon's unix group and the socket group-ownership logic shared by the daemon and the privileged enforcer.
Package ownership centralizes the EzyShield daemon's unix group and the socket group-ownership logic shared by the daemon and the privileged enforcer.
parser
Package parser provides log parsers that convert raw log lines into structured Events.
Package parser provides log parsers that convert raw log lines into structured Events.
rules
Package rules provides the always-available rule-based verdict engine.
Package rules provides the always-available rule-based verdict engine.
scan
Package scan discovers listening TCP sockets via /proc/net/tcp[6], maps each to its owning process / systemd unit / container, and resolves a log source.
Package scan discovers listening TCP sockets via /proc/net/tcp[6], maps each to its owning process / systemd unit / container, and resolves a log source.
siem
Package siem renders EzyShield audit events into the wire formats that security information and event management systems (Wazuh, Splunk, generic syslog collectors) ingest natively: JSON, ArcSight CEF, and RFC 5424 structured-data syslog.
Package siem renders EzyShield audit events into the wire formats that security information and event management systems (Wazuh, Splunk, generic syslog collectors) ingest natively: JSON, ArcSight CEF, and RFC 5424 structured-data syslog.
store
Package store provides the SQLite persistence layer for EzyShield.
Package store provides the SQLite persistence layer for EzyShield.
update
Package update implements EzyShield's self-update logic: fetching releases from GitHub, verifying SHA256 checksums against checksums.txt, and atomically replacing the on-disk binaries.
Package update implements EzyShield's self-update logic: fetching releases from GitHub, verifying SHA256 checksums against checksums.txt, and atomically replacing the on-disk binaries.
vhostdetect
Package vhostdetect enumerates virtual-host domains served by local reverse-proxy setups so the init wizard can offer to configure the matching edge enforcer.
Package vhostdetect enumerates virtual-host domains served by local reverse-proxy setups so the init wizard can offer to configure the matching edge enforcer.
pkg
sdk
Package sdk is the public API surface for EzyShield native modules.
Package sdk is the public API surface for EzyShield native modules.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL