Files
EvoFirewall/docs/agents.md
T
Denozordec 43f5ac2525
Build and Push EvoFirewall Docker Image / build-and-push (push) Successful in 1m43s
Build and Push EvoFirewall Docker Image / create-release (push) Skipped
feat(api, web): implement port ACL and host firewall snapshot features
- Added support for managing desired L4 port ACL rules for Linux agents, allowing for open/close actions on specified ports.
- Introduced a new endpoint for CRUD operations on port rules, enhancing the API's capabilities for agent management.
- Implemented functionality to collect and report host firewall snapshots, capturing observed rules and listeners for better monitoring.
- Updated the agent detail view to include tabs for managing port ACLs and viewing host firewall data, improving user experience.
- Enhanced documentation to reflect the new features and API changes, ensuring clarity for users and developers.

These changes significantly improve the management and visibility of firewall rules and port access control for agents.
2026-08-11 15:08:00 +07:00

8.9 KiB
Raw Blame History

Agents

Short install (рекомендуется)

В UI /agentsДобавить агента:

  1. Создаётся агент со статусом Invited (сразу виден в таблице) + install-ссылка.
  2. Скопируйте one-liner (колонка Install или Sheet):

Linux:

curl -fsSL https://<cp>/agent-install/<id> | bash

MikroTik:

/tool fetch url="https://<cp>/agent-install/<id>" dst-path=evofw-install.rsc; /import file-name=evofw-install.rsc
  1. После enroll статус станет Pending — одобрите агента (Approve).
  2. Approved — агент синхронизирует политику.

Повторный запуск той же install-ссылки на хосте, где агент уже стоит: обновляет sync-скрипт / timer (или MikroTik scheduler) и пересоздаёт nft rules (в т.ч. deny_port_hits), без повторного enroll — CLIENT_ID/token сохраняются. Сбрасывается last_hash, затем сразу force sync. Полный переустановки с новым токеном: EVOFW_INSTALL_FORCE=1 (Linux).

API (auth): POST /api/v1/install-links { "name": "web-01", "platform": "linux" | "mikrotik" }.

Linux (legacy one-liner)

curl -fsSL https://<cp>/v1/agent/install.sh | \
  EVOFW_CP_URL=https://<cp> \
  EVOFW_SEED=<seed> \
  EVOFW_CLIENT_NAME="web-01" \
  bash

Создаёт нового агента со статусом Pending (без Invited).

Файлы: /etc/evofw/agent.conf, /usr/local/sbin/evofw-firewall.sh, timer evofw-firewall.timer (default 1min).

Install сам ставит зависимости через apt/dnf/yum/apk: curl, jq (или python3), nftables/iptables(+ipset). Планировщик: systemd timer если есть /run/systemd/system, иначе ставит cron/cronie и пишет crontab. Значения в agent.conf всегда в single quotes (имена с пробелами безопасны). Sync при статусе pending завершается с exit 0 (pending approval), чтобы systemd timer не был failed.

Если /etc/evofw/agent.conf уже есть — install переходит в update: скачивает свежий sync-script + uninstall.sh, перезаписывает unit/timer, оставляет токен. EVOFW_INSTALL_FORCE=1 — полный re-enroll (новый токен; для уже Approved install-link обычно не сработает).

Uninstall (Linux):

curl -fsSL https://<cp>/v1/agent/uninstall.sh | bash
# или локально после install:
sudo /usr/local/sbin/evofw-uninstall.sh

Backend auto-detect: nft → ipset → iptables.

Whitelist: nft chain policy drop + allow set. Blacklist: policy accept + deny set.

Per-IP blocked stats (Linux)

Linux agent reports optional ip_hits in POST /v1/agent/apply-report:

  • nft: tries set deny_v4 with flags interval; counter;. If the kernel rejects counters on interval sets, falls back to plain interval (aggregate Traffic ↓ still works; per-IP empty).
  • Upgrade path: on install-link re-run, last_hash is cleared once so sets/chain can be recreated (chain deleted before set replace) — обновляет и port-hit правила.
  • ipset: prefers hash:net … counters on create; existing sets without counters are left as-is.
  • Payload: only entries with packets > 0, top 200 by packets.
  • Control plane: agent_ip_block_stats, accumulates deltas of absolute kernel counters (как Traffic ↓). После flush set/chain (policy apply) CP сбрасывает per-IP baseline (last_reported), иначе вторая эпоха счётчиков теряется (Traffic растёт, Blocked IPs — нет).
  • GET /api/v1/agents/:id/blocked-ips, reset via POST …/stats/reset.
  • UI: agent detail → Blocked IPs. Sum of Blocked IPs ≈ Traffic ↓ для deny (при default accept); default-drop / allow в Traffic считаются отдельно.

IPv6 skipped.

Destination ports (Linux nft)

На nft агент ведёт dynamic set deny_port_hits (ipv4_addr . inet_proto . inet_service, timeout 1h, counter):

  • Deny rule для tcp/udp: update @deny_port_hits { ip saddr . meta l4proto . th dport } + drop; прочие протоколы — plain drop.
  • В apply-report: optional port_hits top 500 { ip, port, protocol, packets }.
  • CP: agent_port_block_stats (absolute deltas). Set не flush’ится на каждый policy apply (элементы живут по timeout) — baseline не сбрасывается при Traffic flush.
  • GET /api/v1/agents/:id/blocked-ports — aggregate top 50 портов; в blocked-ips у каждого IP — ports top 5.
  • UI: Top ports + колонка Ports в Blocked IPs (только platform=linux).
  • ipset/iptables: port_hits: []. MikroTik — без port hits.
  • Чтобы подтянуть правила на уже установленном агенте: re-run install one-liner (см. выше).

IPv6 skipped.

Host firewall snapshot + Port ACL (Linux)

Observed (Host firewall)

Каждый sync агент собирает best-effort снимок и шлёт в apply-report.host_firewall:

  • nft list ruleset, iptables-save, optional ufw / firewall-cmd, ss -lntu
  • Каждое правило: ownership: evofw | foreign (метка по имени table/chain/comment evofw)
  • CP: agent_host_firewall_snapshots; GET /api/v1/agents/:id/host-firewall
  • UI agent detail → tab Host firewall (Rules / Listeners)

Foreign правила только отображаются — с CP не редактируются.

Desired (Port ACL)

Per-agent таблица agent_port_rules: open|close, tcp|udp|both, port range, src_kind: all|cidr|list.

  • API: CRUD /api/v1/agents/:id/port-rules, import /port-rules/import (from list или policy set sources)
  • Policy apply_version: 3port_rules[] с expanded src_cidrs
  • nft apply: после L3 allow — close drop, затем open accept (comment "evofw-port-<id>")
  • UI: tab Port ACL (DataGrid + Sheet create/edit + Import)
  • ipset / MikroTik: без L4 apply; секции скрыты для non-linux

Мутация Port ACL бампит policy_generation → agent re-apply.

MikroTik (RouterOS 7.21+)

В UI /agentsДобавить агента → platform MikroTik. Скопируйте one-liner:

/tool fetch url="https://<cp>/agent-install/<id>" dst-path=evofw-install.rsc; /import file-name=evofw-install.rsc

Или короткий slug: https://<cp>/<slug>.

Install RSC:

  1. Enroll (с install_link_id → агент Invited → Pending).
  2. Создаёт filter-правила evofw-* в начале цепочек input/forward (place-before) и address-list EVOFW_DENY / EVOFW_ALLOW / dynamic EVOFW_HITS.
  3. Scheduler evofw-sync каждую минуту: GET /v1/agent/policy (JSON) → rebuild deny/allow + report (+ ip_hits из HITS). Не использует /import огромного .rsc.

Лог: /log print where message~"evofw". Ручной sync: /system script run evofw-sync. Traffic ↓/↑ в UI — сумма packets с evofw-deny-drop-* / evofw-allow-* / evofw-default-drop-* (накопительно, пока правила не пересозданы re-install).

Per-IP / Blocked IPs (MikroTik)

Цепочка deny: hit → drop (семантика drop/allow/default как раньше):

  1. evofw-deny-hit-input/forwardadd-src-to-address-listEVOFW_HITS, address-list-timeout=1h (passthrough).
  2. evofw-deny-drop-input/forwarddrop по EVOFW_DENY.

В EVOFW_HITS попадают реальные src /32. Policy rebuild не чистит HITS (только DENY/ALLOW). Sync шлёт top-200 в ip_hits; CP mode presence: last_seen обновляется, пока IP в HITS; packets (Hits) увеличивается только при первом появлении или повторном входе после исчезновения из списка (~>2.5 мин без report), а не на каждый sync.

UI: agent detail → Blocked IPs (колонка Hits).

Default action задаётся на агенте (default_action: accept | drop):

  • accept — пакет вне deny/allow пропускается
  • drop — пакет вне deny/allow отбрасывается (forward)

Цепочка: deny-hit → deny-drop → allow-accept → default. Наборы несут только правила deny/allow, без exclusive mode.

Force sync

sudo rm -f /var/lib/evofw/last_hash
sudo /usr/local/sbin/evofw-firewall.sh