Zedmos
ENTWICKLER · API

Steuern Sie Zedmos von überall.

Jede Zedmos-Funktion der Konsolen-UI ist ein REST-Endpunkt. Dieser Leitfaden zeigt die zwei sicheren Wege, sie aus der Ferne zu erreichen — ein direkter API-Key oder der zedmos-console WebSocket-Proxy — samt vollständiger, kategorisierter Endpunkt-Referenz.

OPNsense 26.1REST + WSSIm Labor verifiziert
ZWEI WEGE HINEIN

Direkte API oder der WebSocket-Proxy

Beide Wege erreichen letztlich dieselben /api/zedmos/*-Controller — nur Transport und Zugangsdaten unterscheiden sich. Wählen Sie einen pro Integration.

ADirekte REST-API
Bereitsteller
Die OPNsense-Firewall selbst (ihr Webserver).
Transport
HTTPS direkt zur Management-Schnittstelle der Firewall.
Zugangsdaten
OPNsense-API-Key + Secret (HTTP-Basic-Auth).
Begrenzung
Eine einzige OPNsense-ACL — page-services-zedmos — schützt jeden Endpunkt (Lesen UND Schreiben). Kein eingebauter Nur-Lese-Bereich.
Geeignet für
Ein Partner in einem vertrauenswürdigen Segment / Site-to-Site-VPN oder per IP einschränkbar.
https://<firewall>/api/zedmos/...
BWebSocket-Proxy (zedmos-console)
Bereitsteller
Der Zedmos-Cloud-Hub (zedmos-backend). Die Firewall wählt sich nach außen ein.
Transport
Firewall öffnet einen ausgehenden wss://-Tunnel zum Hub; der Partner ruft die REST-API des Hubs auf.
Zugangsdaten
Hub-Konsolen-Sitzungstoken (Bearer). Firewall ist mit tenant_id + node_id + agent_secret (HMAC) registriert.
Begrenzung
Pfad-Allowlist-Preset am Agenten, PLUS lokale API-Key-ACL, PLUS Mandanten-Isolation des Hubs.
Geeignet für
SaaS / Multi-Tenant-Verwaltung, Firewalls hinter NAT oder alles, was nicht eingehend exponiert werden darf.
POST https://<hub>/api/agent/proxy/http → { url: "/api/zedmos/..." }
AUTHENTIFIZIERUNG

Schnellstart

Die direkte API nutzt einen OPNsense-API-Key + Secret über HTTP-Basic. Nicht authentifizierte Aufrufe erhalten HTTP 302 (Weiterleitung zum Login), nicht 401. API-Key-Aufrufe sind von CSRF ausgenommen.

Direkte REST-API — curlbash
# 1) Create an API key in OPNsense: System > Access > Users > API keys
#    The user must hold the "Services: Zedmos" privilege (page-services-zedmos).
KEY='....'      # OPNsense API key
SECRET='....'   # OPNsense API secret

# Read — list policy groups
curl -s -u "$KEY:$SECRET" \
  https://fw.example.com/api/zedmos/policies/groups
# -> {"groups":[{"name":"Default","status":true}, ...]}

# Write — block a domain globally (POST, JSON body)
curl -s -u "$KEY:$SECRET" -H 'Content-Type: application/json' \
  -d '{"type":"host","value":"badsite.com","global":true}' \
  https://fw.example.com/api/zedmos/policies/block
# -> {"status":"ok"}
Direkte REST-API — Node.jsts
const base = "https://fw.example.com";
const auth =
  "Basic " + Buffer.from(`${process.env.ZED_KEY}:${process.env.ZED_SECRET}`).toString("base64");

async function zed(path, { method = "GET", body } = {}) {
  const r = await fetch(`${base}/api/zedmos${path}`, {
    method,
    headers: { Authorization: auth, ...(body ? { "Content-Type": "application/json" } : {}) },
    body: body ? JSON.stringify(body) : undefined,
  });
  if (r.status === 302) throw new Error("auth failed (redirect to login)");
  return r.json();
}

const groups = await zed("/policies/groups");
await zed("/policies/block", {
  method: "POST",
  body: { type: "category", value: "AdultContent", group: "Strict" },
});
Über den Hub-WebSocket-Proxy — curlbash
# The partner never talks to the firewall directly — it calls the hub,
# which routes the call down the firewall's outbound socket.
curl -s -X POST https://www.zedmos.com/api/agent/proxy/http \
  -H "Authorization: Bearer $CONSOLE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
        "tenant_id": "69fb...",
        "node_id":   "6a0d...",
        "method":    "GET",
        "url":       "/api/zedmos/policies/groups"
      }'
# -> {"status":"ok","response":{"status":200,"body":"{\"groups\":[...]}","error":null}}
SICHERHEIT

Der sicherste Weg, dies bereitzustellen

Für ein externes Unternehmen, das Sie nicht vollständig kontrollieren, bevorzugen Sie den WebSocket-Proxy: kein eingehender Port, Pfad-Allowlist, Mandanten-Isolation, zentraler Widerruf. Die direkte API nur in einem vertrauenswürdigen Segment / VPN und stets gehärtet.

Eine ACL schützt alles

page-services-zedmos deckt jeden /api/zedmos/*-Endpunkt ab, lesend und schreibend. Es gibt kein endpunktbezogenes oder reines Lese-Recht. Schränken Sie einen Partner stattdessen per Netzwerkregeln oder WS-Proxy-Allowlist ein.

API-Keys umgehen CSRF

API-Key-Aufrufe sind vom Anti-CSRF-Token ausgenommen (nur Browser-Sitzungen brauchen es bei Nicht-GET). Manche Endpunkte verändern Zustand sogar per GET ohne Methoden-Guard — für Keys unkritisch, aber begrenzen Sie Methoden an einem Reverse-Proxy, wenn Sie sie exponieren.

Immer HTTPS, immer IP-beschränkt

Die API lauscht auf allen Schnittstellen (*:80 im Labor). Für den Fernzugriff stellen Sie die WebGUI auf HTTPS mit gültigem Zertifikat um und beschränken den Management-Port per Firewall-Regel auf die Quell-IPs des Partners.

Für Dritte den WS-Proxy bevorzugen

Er öffnet keinen eingehenden Port, beschränkt exakt die aufrufbaren Pfade (Allowlist), isoliert Mandanten und ist zentral widerrufbar (signierte Tombstone). Der empfohlene Kanal für nicht vertrauenswürdige Integratoren.

Empfehlung

WS-Proxy für nicht vertrauenswürdige Dritte. Direkte API nur hinter HTTPS + einer Firewall-Regel für den Management-Port, beschränkt auf die Quell-IPs des Partners, mit einem dedizierten Service-Benutzer, der nur page-services-zedmos besitzt.

POLICIES.JSON · FELDER

Das policies.json-Schema

Jeder Schlüssel, den der Partner über /policies/get lesen und über /policies/groupsave bzw. /policies/save schreiben kann. Schema 1.1.0. Erlaubte Werte und Defaults stammen aus der eingebauten Doku des Dokuments.

Dokumentstruktur

Feld
Typ
Werte / Default
Beschreibung
schema_version
string
1.x | 2.x= 1.1.0
Document schema version. Engine rejects an unsupported major; bump only after the engine understands it.
updated_at
string
ISO-8601 timestamp of the last write (set by the API/UI).
source
string
Origin tag of the document (e.g. ui, console, import).
eval
object
Global evaluation controls — group ordering & match strategy (see eval section).
globals
object
Global defaults, catalogs, engine knob registry, schedules, exclusions (see globals).
groups
object[]
Ordered list of policy groups. THE core — almost every key you'll set lives inside a group.

eval — Auswertungsreihenfolge

eval
Feld
Typ
Werte / Default
Beschreibung
group_order
string[]
Names of groups in evaluation order. A flow is matched against groups in this order.
default_group
string
= Default
Fallthrough group when no other group's selectors match.
match_mode
string
first_match | priority= first_match
first_match keeps configured order; priority sorts rules by their `priority` ascending.
use_effective_tags
bool
= true
Use device/identity effective tags (inherited from categories/groups) during selector matching.

groups[] — das Policy-Gruppen-Objekt

Identity

groups[]
Feld
Typ
Werte / Default
Beschreibung
name
string
Unique group name. Referenced from eval.group_order and overrides.schedule.
status
bool
= true
Enable/disable the whole group without deleting it.
description
string
Free-text label.

Selectors — who the group applies to

groups[].selectors

A flow joins this group when its selectors match. Empty arrays = no constraint on that axis.

Feld
Typ
Werte / Default
Beschreibung
interfaces
string[]
Interface names this group binds to (e.g. ["vtnet1"]).
vlans
int[]
VLAN IDs to scope to.
direction
string
any | in | out= any
Traffic direction.
devices
string[]
Device identifiers — use uppercase MACs (AA:BB:CC:DD:EE:FF) as stable IDs.
device_tags
string[]
Match devices carrying any of these tags.
device_categories
string[]
Match devices in these categories.
src_cidrs
string[]
Source CIDRs.
dst_cidrs
string[]
Destination CIDRs.
users
string[]
AD/identity usernames.
groups
string[]
AD/identity group names.

Overrides

groups[].overrides
Feld
Typ
Werte / Default
Beschreibung
block_all
bool
= false
Hard early-drop ALL traffic for this group (pair with a schedule for time-bound allow).
block_untrusted
bool
= false
Drop traffic from devices not marked trusted.
schedule
string
Name of a globals.schedules[] entry. Outside its window the engine SKIPS the group (falls through to the next).
security_block_maskdeprecated
int
DEPRECATED / not parsed. Use the per-catalog booleans under `security` instead.

Exclusions

groups[].exclusions

Allow-list overrides that exempt matching traffic from this group's blocks.

Feld
Typ
Werte / Default
Beschreibung
devices
string[]
Devices (MACs) exempt from this group.
macs
string[]
MAC exemptions.
src_cidrs
string[]
Source CIDR exemptions.
dst_cidrs
string[]
Destination CIDR exemptions.
domains
string[]
Domain suffix exemptions.
users
string[]
User exemptions.

Security catalogs (threat categories)

groups[].security

Each boolean enables blocking of one threat-intel catalog. basic_mode/advanced_mode are convenience presets; the `essential{}` and `advanced{}` objects mirror the flat booleans.

Feld
Typ
Werte / Default
Beschreibung
basic_mode
string
off | low | medium | high= high
Preset that toggles the essential catalogs as a group.
advanced_mode
string
off | low | medium | high= high
Preset for the advanced catalogs.
custom_ti
bool
Also evaluate the operator's custom IOC feed for this group.
malware_virus / phishing / hacking / spam / parked / first_seen / potentially_dangerous / turkish_usom
bool
Essential catalogs — one boolean each.
botnet_cc / compromised / spyware_adware / ransomware / cryptominer / exploit_kit / banking_trojan / info_stealer / iot_botnet / ddos_amplifier / scanner / anonymizer / bulletproof_hosting / dynamic_dns / newly_registered / adult_nsfw / yara_rules / ja3 / ja4 …
bool
Advanced catalogs (under security.advanced{}) — one boolean each.

Application control (L7 app-ID)

groups[].apps
Feld
Typ
Werte / Default
Beschreibung
categories_block
string[]
nDPI category slugs to block, e.g. ["adultcontent"]. See /api/zedmos/policies/appcategories.
block
string[]
Specific application names to block (see /api/zedmos/policies/appcatalog).
custom
object[]
Custom app definitions {name, category, domains[], ports[]} so flows nDPI can't classify become matchable. domains are SNI/Host suffix-matched; ports[] is forward-compatible.

Encrypted-transport control

groups[].transport

First-install default: all 'allow'. Switch to 'block' to enforce.

Feld
Typ
Werte / Default
Beschreibung
quic_strategy
string
allow | block= allow
QUIC (HTTP/3) handling.
doh_strategy
string
allow | block= allow
DNS-over-HTTPS handling.
dot_strategy
string
allow | block= allow
DNS-over-TLS handling.
doq_strategy
string
allow | block= allow
DNS-over-QUIC handling.
starttls
object
Force STARTTLS inspection per protocol: {smtp, imap, pop3, xmpp} booleans.

TLS inspection (MITM)

groups[].tls
Feld
Typ
Werte / Default
Beschreibung
enable_inspection
bool
= false
Turn on TLS bumping for this group.
bump_mode
string
auto | force | off= force
How aggressively to bump TLS sessions.
min_version
string
off | 1.0 | 1.1 | 1.2 | 1.3= off
Minimum TLS version to allow; below it is blocked.
fail_open
bool
= true
On bump failure, allow (true) or drop (false).
ech_block
bool
= false
Block Encrypted ClientHello. Engine drops only when outer SNI is empty (avoids GREASE-ECH false positives).
ja3_block
string[]
JA3 client fingerprints to block.
ja4_block_sha256
string[]
JA4 fingerprint SHA-256s to block.
alpn_block
string[]
ALPN protocols to block.
weak_ciphers_block
string[]
Cipher suites to block.
sni_bump_sfx
string[]
SNI suffixes to force-bump.
sni_bypass_sfx
string[]
SNI suffixes to NEVER bump (cert-pinned hosts; ~33 sane defaults shipped).
pinned_hosts
string[]
Hosts known to pin certs — relayed raw.
tls_app_bypass / tls_cat_bypass
string[]
Apps / categories to exempt from bumping.

Network (L3/L4) blocks

groups[].network

Hard early-drops via fast-reject before rules[] runs. Use a rule with is_exception+action:allow to punch a hole.

Feld
Typ
Werte / Default
Beschreibung
proto_block
string[]
IP protocols to drop.
port_block
int[]
Destination ports to drop.
macs
string[]
MAC addresses to drop.
src_ip_block / dst_ip_block
string[]
IPv4 source/destination addresses to drop.
src_cidr_block / dst_cidr_block
string[]
IPv4 source/destination CIDRs to drop.
src_ip6_block / dst_ip6_block / src_cidr6_block / dst_cidr6_block
string[]
IPv6 equivalents.

Web filtering

groups[].web
Feld
Typ
Werte / Default
Beschreibung
url_allow / url_block
string[]
URL allow / block lists.
http_host_block / http_uri_block / http_method_block / http_status_block
string[]
Block by HTTP host / URI / method / response status.
doh_endpoints_block
string[]
Known DoH endpoint hosts to block.
safe_search
object
{enable:bool} — force SafeSearch on supported engines.
dlp
object
Data-loss-prevention block (see web.dlp).

DLP & AI Gateway

groups[].web.dlp

Per-group only — globals.web.dlp is a TEMPLATE the engine ignores. First-install default: OFF.

Feld
Typ
Werte / Default
Beschreibung
enable
bool
= false
Master DLP switch for the group.
mode
string
off | regex_only | ai_gateway | llm_all= off
regex_only = Hyperscan presets only; ai_gateway = regex + LLM verdict on matching AI routes; llm_all = LLM verdict on every matching body.
action
string
log | block | quarantine= log
What to do on a DLP hit.
presets
string[]
Hyperscan preset names (CC/IBAN/national-ID/PII) from the DLP preset library (/api/zedmos/policies/dlppresets).
patterns
string[]
Additional preset/regex names to match.
body_inspection
object
{enable, methods[], max_mb, skip_mime[]} — which request bodies to inspect (POST/PUT/PATCH; skips images/video/binary).
llm
object
LLM verdict config: {enable, provider(ollama|claude|openai|vllm|lmstudio), endpoint, api_key, model, system_prompt, max_tokens, timeout_ms, async, multimodal{}}.
ai_gateway
object
{rules[]} — each {name, paths[], domains[], apps[], categories[], llm_override{}} routes a subset of requests to the LLM. Only consulted when mode=ai_gateway.

File / AV scanning

groups[].file.scan
Feld
Typ
Werte / Default
Beschreibung
mode
string
off | detect | block= off
off = no scan; detect = scan+log; block = scan+drop infected.
action
string
log | block | quarantine= block
Action on an infected file.
fail_close
bool
= false
If the scanner is unavailable, block (true) or pass (false).
max_mb
int
Max file size to scan (MB).
engines
string[]
Scan engines to use, e.g. ["clamav"].
mime_allow / mime_deny
string[]
MIME allow / deny lists.
prefilter
bool
Cheap pre-filter before full scan.
protocols
object
Per-protocol toggles {tls_http, smtp, ftp, smb, imap, pop3, mqtt, nfs, tftp, modbus} — inherit/on/off.

DNS control

groups[].dns
Feld
Typ
Werte / Default
Beschreibung
block_domains / allow_domains
string[]
Domain block / allow lists (suffix match).
rcode_block
string[]
DNS response codes to block.
rewrite
object[]
DNS rewrite rules.
edns_client_subnet
string
EDNS Client Subnet handling.
tunnel
string
off | log | block= block
DNS-tunneling heuristic action.
malformed
string
off | log | block= block
Malformed-DNS action.
dga
string
off | log | block= block
DGA (domain-generation-algorithm) heuristic action.
poison
string
off | log | block= block
DNS-poisoning heuristic action.

ETA · Identity · Geo · Risk · TI · IDS

groups[].{eta,identity,geo,risk,ti,ids}
Feld
Typ
Werte / Default
Beschreibung
eta
object
Encrypted Traffic Analysis: {enabled, log_threshold, block_threshold}.
identity
object
{user_block[], group_block[], device_block[]} — block by AD identity.
geo
object
{country_block[]} — block by GeoIP country code.
risk
object
{labels_block[], tags_block[]} — block by risk label / device tag (works with mark_suspicious).
ti
object
{enable:bool, domain_block[], sni_block[], domain_allow[], sni_allow[]} — per-group threat-intel gate against globals.ti feeds.
ids
object
{mode: off|detect|prevent, enable, alert_max_priority(1-4), block_max_priority(1-3), wan_only}.

Action handlers

groups[].actions

Configured at group level; a rule references them via its `action`. Most fire only on a DROP-class decision (pair with action:drop). Placeholders $src, $dst, $rule_id.

Feld
Typ
Werte / Default
Beschreibung
shape
object
{pps:int} — rate-limit matched flows.
redirect
object
{ip, port} — redirect the connection.
quarantine
object
{enable:bool} — quarantine the device.
tarpit
object
{enable:bool} — tarpit the connection.
rewrite_url
object
{to:string} — rewrite the request URL.
execute_script
object
{path, args, timeout_ms, env} — fork+exec via writerd after an action_event.
call_api
object
{url, method, headers, body, timeout_ms, capture_response, max_body_kb} — webhook/API call.
mark_suspicious
object
{tag, severity, ttl_sec, scope: device|flow} — inline tag for risk.tags_block on the same/next eval.

SD-WAN routing

groups[].routing
Feld
Typ
Werte / Default
Beschreibung
enabled
bool
Enable policy-based routing for this group.
default_target
string
Default route target (gateway/iface/tunnel).
routes
object[]
Each route {name, match_type, match_values[], target, fallback}. fallback used when target SLA is DOWN.

Rules (ordered, fine-grained)

groups[].rules[]

Optional per-group ordered rule list evaluated after early-drops. Each rule matches on fields and fires one action.

Feld
Typ
Werte / Default
Beschreibung
action
string
allow | log | drop | reset | shape | redirect | quarantine | tarpit | scan_content | rewrite_url | execute_script | call_api | mark_suspicious | escalate | route
What the rule does. 'alert' is NOT valid here (IDS-only) — use 'log' for non-drop observation.
mode
string
all | any= all
all = AND across listed match fields; any = OR.
is_exception
bool
= false
Exception rules evaluate BEFORE all hard early-drops — use to selectively allow traffic a coarse block list would catch.
priority
int
Used when the group/eval match_mode is 'priority' (ascending).
time
object
{start:"HH:MM", end:"HH:MM", days:["mon".."sun"]} — restrict activation window (wraps past midnight).
<match fields>
varies
src/dst/port/proto/domain/app/category/user/… matchers combined per `mode`.
example · groupsave bodyjson
// POST /api/zedmos/policies/groupsave  — Content-Type: application/json
// Upsert one group (only the keys you send are changed; rest is preserved).
{
  "name": "Strict",
  "status": true,
  "description": "Locked-down VLAN",
  "selectors": { "vlans": [30], "direction": "any" },
  "overrides": { "block_all": false, "block_untrusted": true, "schedule": "work-hours" },
  "security": { "basic_mode": "high", "malware_virus": true, "phishing": true },
  "apps":     { "categories_block": ["adultcontent", "gaming"] },
  "transport":{ "quic_strategy": "block", "doh_strategy": "block" },
  "tls":      { "enable_inspection": true, "bump_mode": "force", "min_version": "1.2" },
  "dns":      { "block_domains": ["coin-hive.com"], "dga": "block", "tunnel": "block" },
  "web":      { "dlp": { "enable": true, "mode": "regex_only", "action": "block",
                         "presets": ["cc_luhn","iban","email_pii"] } },
  "file":     { "scan": { "mode": "block", "action": "block", "engines": ["clamav"] } },
  "ids":      { "mode": "prevent", "block_max_priority": 2 },
  "rules": [
    { "is_exception": true, "action": "allow", "mode": "any",
      "dst_domain": ["intranet.corp"], "comment": "always allow intranet" }
  ]
}

globals — Defaults, Kataloge, Engine-Knobs

Engine knob registry

globals.engine

Operator-tunable hot-path knobs. Precedence: value here > env DG_* > hardcoded default. Atomic publish on policy reload.

Feld
Typ
Werte / Default
Beschreibung
tls
object
{ech_block_strict, decision_notify}.
ids_proxy
object
{enable, block, block_max_priority, alert_max_priority, wan_only} — IDS over decrypted HTTPS bodies.
dlp
object
{decomp_max_mb}.
flow_agg
object
{emit} — flow aggregation/telemetry.
quarantine
object
{ttl_sec, severity}.
block_page_url
string
Override block-page URL.

Global catalogs & defaults

globals.{security,ti,quarantine,schedules,exclusions}
Feld
Typ
Werte / Default
Beschreibung
security
object
{catalog[], catalog_ips[], sources[]} — the threat-intel catalog feeds the per-group security booleans draw from.
ti
object
Feed paths + block lists {ttl_seconds, domains_path, ips_path, ip_block[], domain_block[], sni_block[], ja3_block[], ja4_block[]}. Note: globals.ti.enable is DEPRECATED — use groups[].ti.enable.
quarantine
object
{persist, auto_drop, sources[], devices[]}.
schedules
object[]
Named time windows {name, start:"HH:MM", end:"HH:MM", days[]} referenced by groups[].overrides.schedule.
exclusions
object
Global allow-list {devices, macs, src_cidrs, dst_cidrs, domains}.
transport / tls / web / dns / apps / identity / geo / network / actions
object
Global default templates mirroring the group sections. NOTE: globals.web.dlp.* is TEMPLATE-ONLY — the engine ignores it; DLP enforces from groups[].web.dlp.*.
example · globals bodyjson
// POST /api/zedmos/policies/globals  — set global blacklists / actions
{
  "exclusions": { "domains": ["windowsupdate.com"], "src_cidrs": ["10.0.0.0/8"] },
  "ti": { "domain_block": ["evil.example"], "ip_block": ["203.0.113.7"] },
  "schedules": [
    { "name": "work-hours", "start": "08:00", "end": "18:00",
      "days": ["Mon","Tue","Wed","Thu","Fri"] }
  ]
}
ENDPUNKT-REFERENZ

Jede Kategorie

Gruppiert genau wie die Konsole: zuerst Policies, dann Settings, Notifications, Reports, Live und der Rest. Pfade sind relativ zur jeweiligen Kategorie-Basis.

GET lesenPOST schreiben (POST)GET+POST lesen + schreibenGET* verändert bei GET (kein Methoden-Guard) zustandsverändernd
Policies/api/zedmos/policies

Die zentrale Schnittstelle. Steuert policies.json — Gruppen, Globals, Security-Katalog, App-Kategorien, DLP-Presets und Threat-Intel.

GET
/get
Full policies.json document (sample-merged).
GET+POST
/groups
List groups, or create one.create=1&name=&description=&status=
GET
/groupget
One group's full object.name
POST
/groupsave
Universal write path — upsert a group or the global blacklist.full group JSON | {global_blacklist}
DELETE
/groupdel
Delete a group (refuses "Default").name
GET+POST
/globals
Global exclusions, actions, quarantine, eval flags, schedules.domains, actions, quarantine, eval, schedules…
GET+POST
/block
Add a block entry to globals and/or named groups.type(host/sni/ip/category/app), value, global, group(s)
GET+POST
/securitycatalog
Security feed catalog.catalog, sources
GET+POST
/customiocs
Manual TI feed (writes ti_domains.txt / ti_ips.set).ips[], domains[]
GET*
/securitypull
Fetch all configured security feeds now.
GET
/appcategories
nDPI category catalog with per-category counts.
GET
/appcatalog
nDPI protocol → category map.
GET
/dlppresets
DLP preset library (CC/IBAN/national-ID/PII regex).
GET
/ti
Per-group threat-intel state (POST rejected — TI is per-group).
GET
/routehealth
SD-WAN route SLA health (route_health.json).
GET
/whois
whois lookup (truncated 64 KB).value
POST
/validate
SD-WAN dry-run validator; never writes.raw policies doc (optional)
POST
/save
Replace full policies.json (deep-merge guard).raw JSON full doc; ?strict=1
POST
/consolesave
Console-facing variant of save (tolerant of double-encoding).raw/nested JSON
GET+POST
/geoipupdate
Trigger GeoIP DB update.
Settings/api/zedmos/settings

Die größte Schnittstelle (~62 Aktionen): TLS/CA, Interfaces & Worker, IDS/ETA/TI, writerd & Storage, AD/Identität, Cloud-Konsole, Geräteerkennung und Traffic-Control.

GET
/get
TLS + LDAP + TI snapshot (secrets blanked).
GET+POST
/interfaces
Interface / worker / deployment config; reloads engine.deployment_mode, zones, *_workers, bridge_pairs
GET
/policiesInterfaces
Routing-aware interface list for policy scoping.
GET+POST
/tls
TLS-proxy config block.tls_root_ca_path, proxy_port, quic_proxy_port…
GET
/tlsstatus
Live TLS proxy status (listening, pf anchor, rdr, quic).
GET+POST
/tlscreateca
Create the MITM CA.DN fields
GET
/tlsexportca
Download CA.format(pem/der/p12)
GET
/tlsmobileconfig
Apple .mobileconfig CA profile.
GET+POST
/ids
IDS/IPS config.mode(off/detect/prevent), block_max_priority, wan_only
GET+POST
/eta
Encrypted Traffic Analysis.enabled, log_threshold, block_threshold
GET+POST
/ti
Threat-intel feed CRUD.action(save_feed/delete_feed/toggle_feed/save_output)
GET
/tistatus
TI feed download status.
GET+POST
/adsettings
Directory integration (secrets blanked on GET).full AD/Azure/SCIM config
GET*
/adsync
Run LDAP/Azure/SCIM sync now.
GET+POST
/devicerecognition
Device-ID config.os_detection, arp, dhcp, mdns, nbns…
GET+POST
/consoleconfig
Cloud Console config.console_url, console_node_name, console_owner_email, console_enabled
POST
/console_register
Create service user + API key, register firewall with the hub.email, node_name, console_url
GET+POST
/engine
Allowlisted zedmos-ctl engine proxy.op(status/metrics/health/reload_policy/…)
GET+POST
/writerdconfig
SIEM writer config (file/sqlite/elasticsearch/syslog).full sink config
GET+POST
/retention
DB retention window.days, months
GET
/storagedashboard
Storage KPIs (disk, growth, retention, backends, alerts).
GET+POST
/privacy
Privacy redaction flags.pii_redact, audit_extended
POST
/restartEngine
Template reload + engine restart.
POST
/uninstall
Stop services, optional data wipe, remove package.mode(pkg_only/full)
Notifications/api/zedmos/notifications

Alarm-Feed + Dispatcher. Der einzige Controller mit eigenem Autorisierungs-Gate (canModify: Sitzungsbenutzer oder Loopback/gleicher Host). Konfig in notifications.json.

GET
/list
Notifications feed.window_sec, since, type, severity, limit≤1000, page, q, sort, dir
GET
/total
{total} count.
GET+POST
/ack
Mark acknowledged.ids[] | csv
GET+POST
/clear
Delete old rows.older_than_sec
GET+POST
/delete
Delete rows.ids[]
GET
/taxonomy
Channel-type / severity enums.
GET
/settingsGet
Dispatcher settings.
POST
/settingsSave
Save dispatcher config + start/stop notifyd.enabled, poll_interval_sec, retry…, quiet_hours, digest_*
GET
/channelsList
Channels (secrets masked).
POST
/channelSave
Create/update a channel (email/webhook/…).{id,name,type,enabled,params}
POST
/channelDelete
Delete a channel.{id}
GET+POST
/channelTest
Send a test through a channel.id
GET
/routesList
Routing rules.
POST
/routeSave
Create/update a routing rule.{id,name,match,channel_ids,rate_limit,quiet_hours}
GET
/deliveries
Delivery log.limit≤1000, notify_id
GET
/dispatchStatus
Dispatcher status.
POST
/emitTest
Emit a synthetic notification row.{type,severity,title,message}
POST
/dispatchControl
Control the dispatcher.op(start/stop/restart/reload/once)
Reports/api/zedmos/reports

Reine Lese-Chart-Endpunkte über die Flow-DB. Alle erzwingen POST in dispatch(), damit die UI sie per XHR-GET nutzen kann; mit API-Key beide Methoden möglich. Übliche Parameter: hours(1-168), since/until(ms), mode(session/packet/volume). Meist {labels, values}.

GET+POST
/connectionsTopGeoCountries
Top remote destination countries.
GET+POST
/connectionsTopThreats
Top threats by reason.
GET+POST
/connectionsTopThreatDevices
Top threat source devices.
GET+POST
/connectionsTopBlocks
Top policy blocks by reason.
GET+POST
/connectionsTopBlockedHosts
Top blocked hosts.
GET+POST
/connectionsApps
Top applications.mode, traffic_type
GET+POST
/connectionsTopDevices
Top source devices.mode, traffic_type
GET+POST
/connectionsTopSni
Top TLS SNI.
GET+POST
/connectionsTopTlsAlpn
Top TLS ALPN.
GET+POST
/connectionsTopDnsQueries
Top DNS queries.
GET+POST
/overviewThreatsTimeline
Time-bucketed threats vs blocks.
GET+POST
/overviewIdsTopSids
Top IDS signatures.topn(5-50)
GET+POST
/overviewTiBreakdown
Threat-intel feed-hit breakdown.
POST
/bulk
Batch — run a whitelist of chart actions in one request → {results}.actions(JSON/csv) + per-action params
Live/api/zedmos/live

Nahezu-Echtzeit-Feeds. Mit since-Cursor pollen (die UI nutzt Polling — kein WebSocket/SSE auf der Box). Übliche Parameter: hours(6), since(ms), limit(1000, 10-2000), plus Smart-Filter (filters_<ep>, sf_*).

GET+POST
/connections
Live connections ({rows}).
GET+POST
/threats
Security flows + IDS alerts + portscans.
GET+POST
/blocks
Policy blocks.
GET+POST
/web
HTTP flows.
GET+POST
/dns
DNS transactions.
GET+POST
/tls
TLS flows (SNI, ALPN, cipher, JA3/JA4).
GET+POST
/files
File-transfer flows.
GET+POST
/whois
whois lookup.query, type(ip/host)
GET+POST
/export
CSV export {filename, content}.type(connections/threats/blocks/web/dns/tls)
GET+POST
/suspiciousCreate
Mark a host suspicious.ip, mac, tag, scope, severity, ttl_sec
GET+POST
/quarantineCreate
Quarantine a host.ip, mac, iface, group, reason
Dashboard/api/zedmos/dashboard

Aggregierte KPIs, System-Telemetrie (CPU/Temp/Disk), Feature-Status sowie Dienst- / Update-Steuerung.

GET
/summary
{engine, traffic, files, ml, database} today aggregate (30s cache).
GET
/featurestatus
Per-feature enabled map (tls_proxy, threat_intel, eta, policies, ids_ips, file_scan, backup, siem, console, device_id, license).
GET
/aggregatestatus
Combined engine + writerd + agent status.
GET
/cpu
System + per-process CPU/mem.
GET
/disk
Disk usage of /var/log/zedmos.
POST
/enable
Set autostart (zedmos_enable).enabled
GET*
/restart
Engine restart.
GET+POST
/agent
Control the zedmos-console (Cloud Agent).op(status/start/stop/restart)
GET
/checkupdate
Check for a new package (300s cache).force
POST
/installversion
Install a specific version.version
GET
/snapshot
Bundle multiple sub-actions in one call.sections(csv)
Device/api/zedmos/device

Geräte-Inventar + Lebenszyklus. Nutzt positionsbasierte Pfad-Argumente für <id>-Aktionen, z. B. /device/trust/42.

GET
/list
Device inventory {rows, total}.filter, category, q, sort, dir, limit, page
GET
/stats
Counters (total/online/trusted/hidden/quarantined…).
GET
/categories
Device categories.
GET
/detail/<id>
Device + ips + stats + events.
GET
/history
Flow history.ip, mac, limit, offset
GET+POST
/setcategory/<id>
Set device category.name
GET*
/trust/<id>
Trust toggle.flag(0/1)
GET*
/hide/<id>
Hide toggle.flag(0/1)
POST
/purge/<id>
Hard-delete across tables + policies.json.ip, mac
GET+POST
/tagadd/<id>
Add a tag.tag
GET
/export
devices.csv.
More controllers/api/zedmos

Weitere Controller, zusammengefasst. Jeder folgt der gleichen Konvention /api/zedmos/<slug>/<command> und der gleichen Authentifizierung.

GET+POST
/anomaly/settings | /advanced
ML anomaly modes + training params; mlStart/mlStop/mlRestart, summary, recent.
GET*
/av/updatedb | /start | /stop
ClamAV DB + daemon lifecycle (dbstatus, status are GET).
POST
/block_page/save | /preview | /uploadlogo
Block-page designer (get, castatus, cadownload, logoinfo, removelogo).
GET*
/cti/categories
Proxies the TiHub CTI categories (cached).
GET
/routing/validate | /targets | /health | /wgpeers
SD-WAN routing validation + health.
POST
/ssh/save | /hasshadd | /hasshremove
SSH deep-inspect config + HASSH blocklist (settings, status, hasshlist, groupsettings).
GET
/support/context
HMAC-signed support-portal redirect.
GET+POST
/waf/config | /feeds | /enable
Reverse-proxy WAF config (multiplexed by action), feeds, status, forceupdate.
POST
/wizard/apply | /consoleRegister | /tihubEnroll
First-run wizard: sysinfo, db*, mode*, sub*, *Es, engine, writerd.
GET+POST
/agent/settings | /control
Cloud-agent config + control (status).
POST
/zedmoswg/provisionInstance | /addPeer | /writeIdentityFiles
WireGuard instance/peer management (getInstance, instanceHealth, listInstances, getIdentityUsers…).
WEBSOCKET-PROXY

Weg B im Detail

Die Firewall wählt sich zum Hub ein; der Partner ruft die REST-API des Hubs auf, die den Aufruf über den Socket weiterreicht. Der Agent erzwingt vor dem lokalen API-Zugriff eine Allowlist pro Anfrage.

Hub-REST-API — was der Partner aufruft

POST
/api/agent/proxy/http
Leitet einen API-Aufruf an eine benannte Firewall weiter. url muss relativ sein und mit /api/ beginnen (SSRF-Schutz); Methode ∈ GET/POST/PUT/PATCH/DELETE; url ≤2048B, body ≤256KB. Fehler: 503 nicht verbunden, 504 Timeout, 429 zu viele offen.auth: console Bearer oder x-admin-token
GET
/api/agent/proxy/status
Verbundene Agenten in den Mandanten des Aufrufers.auth: console Bearer
GET
/api/agent/proxy/metrics
Prometheus-Metriken.auth:
POST
/api/agent/enroll
Install-Token tauschen → tenant_id, node_id, agent_secret, jwt, refresh_token.auth: Einmal-Install-Token

Allowlist-Presets (die Grenze pro Anfrage)

core-read-only~364 reine Lese-GET-Endpunkte über 24 Module. Sicherer Standard.
firewall-adminVoll firewall/* + nur-lesend core/diag/interfaces.
network-adminVoll interfaces/*, routes/*, routing/* + nur-lesend core/diag.
vpn-adminVoll ipsec/*, openvpn/*, wireguard/* (auf Platte; via custom wählbar).
ids-monitorVoll ids/* + nur-lesend core/diag (auf Platte; via custom wählbar).
full-adminAlles, jedes Modul. "Entspricht Bypass." Nicht an Partner ausliefern.

Keines der ausgelieferten Presets enthält /api/zedmos/*. Für eine Policies-Integration nutzen Sie eine eigene Allowlist:

custom allowlist · config.json patternsini
# Custom allowlist for a policies integration (config.json patterns / preset=custom)
/api/zedmos/policies/*
/api/zedmos/settings/*
# optional read-only telemetry
/api/zedmos/dashboard/*
/api/zedmos/live/*
/api/zedmos/reports/*

Nachrichtenprotokoll (Referenz)

ws framesyaml
Hub → Agent: {"type":"http","requestId","method","url","body","timeoutMs"}
Agent → Hub: {"type":"httpResponse","requestId","status","body","error"}
Handshake: Hub sendet eine Challenge-Nonce; Agent antwortet mit HMAC-SHA256(agent_secret, "tenant|node|ts|nonce"); Hub antwortet hello_ack. Widerruf per signierter Tombstone.

Vollständige Referenz mit jedem Endpunkt und Parameter: docs/ZEDMOS_API_REFERENCE.md im Repository.