ezy-shield

module
v0.1.0-rc.19 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 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: pre-alpha. The pipeline, rule engine, nftables + Cloudflare enforcement, AI providers, and notifiers work today. Run in dry-run (the default) and please report bugs via issues. Interfaces may still change before 1.0.


Why EzyShield

fail2ban EzyShield
Bans local firewall, per-jail bantime strike-based escalation + local and edge (Cloudflare)
Detection regex filters rule engine + signatures, optional AI for ambiguous traffic
Lockout safety manual ignoreip anti-lockout: your SSH session + admin CIDRs auto-allowlisted before every rule write
Default behavior enforces immediately dry-run by default — observe before you arm it
Runtime Python single static binary, no dependencies

fail2ban is battle-tested and great at what it does — EzyShield aims one layer higher: escalation, edge enforcement, AI-assisted scoring, and guardrails that make it hard to ban yourself. You can even run EzyShield as the brain and keep fail2ban for enforcement.


How it works

logs (SSH, Nginx)
        │
        ▼
   [ 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 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
  • Service & port discoveryezyshield scan inventories what's actually listening on the host
  • Audit trail — every action recorded in SQLite; export to JSON/CSV
  • 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

Install

From a release (when available)
curl -sfL https://get.ezyshield.com | sudo sh

The installer fetches the latest signed binaries (ezyshield and ezyshield-enforcer) and verifies checksums.

Specific version (including release candidates)

To install a specific version or release candidate, set EZYSHIELD_VERSION:

curl -sfL https://get.ezyshield.com | sudo EZYSHIELD_VERSION=v0.3.0-rc.1 sh

See docs/content/en/guides/install.md for complete installation options.

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.24+ 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

# Run the pipeline (dry-run until you set armed: true in policy.yaml)
sudo ezyshield run

# 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

# See what's listening on this host
sudo ezyshield scan

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.yaml Detection rules

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. The full setup walkthrough — collectors, AI, notifications, custom rules — is in docs/content/en/getting-started/index.md.


Roadmap

Built today: SSH/Nginx detection, rule engine, nftables bans, Cloudflare edge (IP lists), Anthropic/OpenAI/Ollama providers, Telegram/Email/Slack/Discord/ webhook notifications, dry-run, anti-lockout, audit log.

Planned (not yet shipped — see issues):

  • More edge backends: Bunny, AWS WAF; ASN- and country-level blocking
  • More local backends: iptables, ufw, firewalld
  • More log sources: Apache, Caddy, Traefik, container logs
  • Localhost-only dashboard (SSH-tunneled, like kubectl proxy)
  • Community module/plugin system
  • Host sensor: reverse-shell and egress-anomaly detection
  • Reputation feeds, more notifiers (ntfy, Pushover, WhatsApp/SMS)

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 plan, 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.
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.
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