Network monitoring, security analytics, and device management for MikroTik RouterOS networks.
Built in Rust with a React frontend.
Ion Drift connects to your MikroTik router's REST API, monitors your network in real time, learns what's normal, and alerts you when something changes. It tracks every connection, fingerprints every device, maps your topology, and gives you Sankey flow diagrams to investigate traffic patterns.
See FEATURES.md for the full feature list.
- DNS Policy Deviation Detection — Detects devices using unauthorized DNS servers by cross-referencing connection tracking with the infrastructure policy map. Enriched with MITRE ATT&CK technique context. Resolve actions build Drift's own authorization policies organically from observed traffic.
- NTP Policy Deviation Detection — Detects devices using unauthorized NTP servers. ATT&CK technique T1124 (System Time Discovery). Policies auto-synced from DHCP option 42.
- Policy Editor — Define network policies directly in Drift. Policies live in Drift and describe what it treats as authorized for deviation detection — Drift never pushes, writes, or enforces them on the router. Admin-created policies survive Drift's router-config sync; policies synced in from the router's config are read-only (lock icon).
Findings is where Drift's vulnerability intelligence comes together: the RouterOS vulnerability feed, service-exposure and exploitation findings, confusable-domain detection, and anything your registered modules publish — all in one triage surface with a consistent lifecycle, filterable by status, severity, module, and category. (Behavior anomalies and policy deviations keep their own dedicated pages.)
- Vulnerability feed (NVD + CISA KEV). Drift pulls RouterOS advisories daily. Every managed device whose firmware falls inside a published affected range gets a finding; CVEs CISA lists as actively exploited are raised to Critical. Findings state plainly that Drift checked the version — not whether the affected feature happens to be enabled — so a real exposure is never hidden behind a false "not applicable."
- Service exposure, early. When a service tied to a known advisory is enabled (for example
api/api-ssl), Drift raises an early-warning finding before anyone attacks it — High when the service is reachable from anywhere, Low when you have restricted it by address. - Exploitation signals & confusable domains. Sustained credential-failure patterns and UTS #39 look-alike domains (the
rnicrosoft.com-style homoglyph tricks) surface here too, with the evidence that triggered them.
You decide before anything leaves your network. The vulnerability feed stays off until an administrator confirms it — no outbound request is made until then. Turn it off later and Drift keeps checking against the data it already downloaded; it simply stops learning about newly published CVEs.
A lifecycle that respects your judgment. Acknowledge a finding and it stays acknowledged — until the risk genuinely changes: an acknowledged vulnerability reopens, with a note naming the old and new severity, the day CISA marks it exploited; an exposure finding reopens if you remove the address restriction that kept it Low. Resolve a vulnerability or exposure finding by hand and it stays resolved — Drift reopens those only when it resolved them itself (after an upgrade, if the version regresses; after you disable a service, if it is re-enabled). Exploitation findings are the exception: they reopen if the attack signal resumes, keeping your manual resolution as evidence.
Resilient when the router blips. If the router is briefly unreachable, Findings — along with Connections, Logs, ARP, firewall, and the network map — keeps serving the last data it had behind a clear "showing last-known data" banner instead of failing the page.
Findings is where much of the near-term roadmap converges (the full path to 1.0 lives in ROADMAP.md):
- Suppression, done right — a suppression-rule editor with scope preview, so you can silence noise without hiding signal.
- Findings that reach you — routing findings to the channels you actually watch: email, webhook, ntfy, Discord, and Matrix, each with a per-rule test that sends a synthetic event end to end.
- Deeper evidence — a collapsible evidence-chain view for investigations, plus a verdict feedback loop that learns from your corrections.
- New classes of finding — HTTP/TLS hygiene (TLS 1.0/1.1, self-signed and wildcard misuse inside the trust zone) and SMB/LDAP egress, plus router config-drift detection when a device diverges from its last approved snapshot.
- On the horizon — opt-in, load-guarded data-plane fingerprinting (JA3/JA4, mDNS/SSDP, DHCP fingerprints) to surface signals the REST control plane cannot see.
Auto-discovered network topology driven by a resolved infrastructure snapshot from the correlation engine. VLAN grouping, device classification, and switch-level attachment inference with unified LLDP device resolution (6-step precedence) and evidence chains. Endpoints progress visually from hexagons (learning/unknown) to device icons once baselined and typed.
Multi-level drill-down: network overview, per-VLAN device flows, per-device protocol/destination breakdown, and conversation detail.
GeoIP-enriched connection visualization with country and city summaries, flagged region monitoring, and arc overlays.
Inter-VLAN traffic volumes with real-time activity tracking.
Live interface status with traffic rates, MTU, MAC addresses, and link state.
Firewall rule viewer with drop statistics and geo-enriched drop country attribution.
Detects devices using unauthorized DNS and NTP servers by cross-referencing connection tracking with your router's DHCP and DNS configuration. Every deviation is enriched with MITRE ATT&CK technique context. Resolve actions — Authorize, Acknowledge, Flag All, Dismiss — build Drift's own authorization policies organically from observed traffic. Custom policies can be defined via the built-in policy editor. These policies live inside Drift for deviation detection; none are pushed to the router.
On our own production network, the deviation detector flagged our authoritative DNS server for performing recursive resolution directly to root servers — bypassing our AdGuard ad-filtering pipeline entirely. A misconfiguration we'd missed for months, found and fixed in 20 minutes. If it catches that on a network run by the developers, it'll catch IoT devices hardcoding 8.8.8.8 on yours.
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU | 2+ vCPU |
| RAM | 512 MB | 1 GB |
| Disk | 500 MB | 2 GB (grows with connection history) |
| Docker | 20.10+ | Latest stable |
Compiling Rust in release mode is resource-intensive. Do not attempt to build on low-spec VMs.
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 4 vCPU | 8+ vCPU |
| RAM | 8 GB | 8 GB+ |
| Disk | 10 GB free | 20 GB free |
| Rust | 1.85+ (via rustup) | Latest stable |
| Node.js | 20+ | 22 LTS |
The release build can take 10-30 minutes depending on hardware. With less than 8GB of RAM, the Rust compiler will likely be killed by the OOM killer.
Before you start, have these ready:
- Your MikroTik router's hostname or IP address
- A dedicated RouterOS API user with
read,api,rest-apipolicies (see Router User Setup below) - The router must have HTTPS enabled on port 443 with a TLS certificate
Step 1: Set up the config
cp docker-compose.example.yml docker-compose.yml
mkdir -p config
cp config/production.example.toml config/production.tomlEdit config/production.toml — fill in the [router] section for your environment:
[router]
host = "your-router.example.com" # hostname or IP — must match TLS certificate
port = 443
tls = true
ca_cert_path = "" # set to "/app/certs/root_ca.crt" for private CA
username = "ion-drift"
wan_interface = "ether1" # your router's WAN-facing interface nameThen uncomment the config mount in docker-compose.yml:
volumes:
- ./config/production.toml:/app/config/server.toml:roIf your router uses a private CA (Smallstep, EJBCA, self-signed), set ca_cert_path and mount the CA cert. See docs/configuration.md for details. If your router uses Let's Encrypt or another public CA, leave ca_cert_path empty.
Step 2: Start and set up
docker compose up -dOpen http://your-host:3000 in your browser. The setup wizard guides you through initial configuration:
- Create admin account — choose a username and strong password (min 12 characters). This is your Ion Drift login, not your router password.
- Log in — after the wizard completes, click "Access Ion Drift" and log in with the credentials you just created.
- Add your router — go to Settings → Devices. Enter your router credentials (username and password). Ion Drift begins monitoring immediately.
No environment variables or build tools needed. Credentials are stored encrypted — never put passwords in config files or Docker environment variables.
Pre-built images are published to ghcr.io/cyber-hive-security/ion-drift on every release.
Create a dedicated read-only user on your MikroTik router — do not use the admin account:
/user group add name=ion-drift policy=api,read,!write,!ftp,!local,!telnet,!ssh,!reboot,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon,rest-api
/user add name=ion-drift group=ion-drift password=YourStrongPasswordHere
Ion Drift uses the REST API on port 443 (HTTPS). Do not use port 8728 or 8729 — those are the RouterOS proprietary API (Winbox/API), a completely different protocol.
Ion Drift can monitor managed switches via SNMP (v2c or v3) alongside your MikroTik router. Add switches through Settings → Devices with device type "SNMP Switch."
Vendor profiles control how Ion Drift interprets each switch's SNMP data — interface naming, port classification, hidden index filtering, and counter support. Without a profile, the generic fallback works but interface names and port groupings may render incorrectly.
| Vendor | Status |
|---|---|
| Netgear (ProSafe) | Supported — dedicated profile |
| HPE/Aruba (2540 series) | Supported — dedicated profile |
| Cisco Small Business (SG550X, SG350X, SG250X) | Supported — dedicated profile |
| All others | Generic fallback — functional but may have display quirks |
To help us build a profile for your switch, see docs/snmp-profiles.md.
Ion Drift works with any OpenID Connect provider (Keycloak, Authentik, Authelia). To enable SSO, add an [oidc] section to your config file. See docs/configuration.md for provider-specific setup guides.
ion-drift/
├── crates/
│ ├── mikrotik-core/ # RouterOS REST + SNMP + SwOS client library
│ ├── ion-drift-module-api/ # Stable module trait/type contract (semver)
│ ├── ion-drift-module-host/ # Module runtime host (registry, event bus, storage)
│ ├── ion-drift-storage/ # SQLite stores (behavior, switch, metrics, traffic)
│ ├── ion-drift-cli/ # CLI binary (clap)
│ └── ion-drift-web/ # Axum web server + background tasks
├── web/ # React frontend (Vite + TypeScript + TanStack)
├── config/ # Configuration templates (TOML)
└── docs/ # Technical documentation and engine whitepapers
Tech stack: Rust (Axum, Tokio, SQLite), React 19 (Vite, TypeScript, TanStack Router + Query, Recharts, D3.js, Tailwind CSS 4)
Uses the RouterOS v7 REST API over HTTPS. Switch management supports RouterOS, SwOS, and SNMP v2c/v3.
cp docker-compose.example.yml docker-compose.yml
docker compose up -dOptional bind-mounts (uncomment in docker-compose.yml as needed):
config/server.toml→/app/config/server.toml(custom config — setup wizard handles first-run without it)certs/root_ca.crt→/app/certs/root_ca.crt(only if your router or OIDC provider uses a private CA)ion-drift-datavolume →/app/data(SQLite databases, GeoIP data, encryption keys)
If you need to build from source instead of using the pre-built image:
# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
# Install Node.js 22 (if not already installed)
# See https://nodejs.org/ or use your package manager
# Clone and build
git clone https://github.com/Cyber-Hive-Security/ion-drift.git
cd ion-drift
# Build the Rust backend (release mode — requires 8GB+ RAM)
cargo build --release --bin ion-drift-web
# Build the frontend
cd web
npm ci
npm run build
cd ..
# Run
./target/release/ion-drift-web --config config/server.tomlTo build as a Docker image from source:
# Requires 4+ vCPU and 8+ GB RAM available to Docker
docker compose -f docker-compose.build.yml up -dNote: If building fails or the process is killed, your host likely doesn't have enough resources. Use the pre-built image instead — just run
docker compose up -d. See Quick Start.
Ion Drift includes a stable plugin contract for extending the core with custom modules. Modules are self-contained Rust crates that plug into Drift via a single trait, run inside the Drift process, and can register HTTP routes, spawn supervised background tasks, read core state through narrow trait objects, publish and subscribe to events on the per-kind event bus, and own isolated SQLite storage.
The contract crate is ion-drift-module-api (currently 1.1.0, path-only). Modules depend only on the API crate; the runtime host (ion-drift-module-host) can evolve without forcing module recompiles.
Highlights:
- Capability-scoped runtime gating — modules declare what they need; the host gives them exactly that. Undeclared state reads, secrets, and event subscriptions are absent from the context handle, not just guarded at call time.
- Isolated storage per module — each module gets its own SQLite file at
${data_dir}/modules/<name>.dbwith module-owned schema and migrations. No cross-module joins, no schema collisions, no risk of corrupting Drift core state. - Per-kind event channels —
tokio::sync::broadcastperEventKind, so a high-rate topic cannot lag a low-rate subscriber. Modules see a single unifiedEventReceiver::recv()API. - Host-stamped event provenance —
DriftEvent::ModuleCustomevents have theirsourcefield populated by the host from the publishing module's actual name. Modules cannot spoof origin. - Namespace-scoped secrets — modules declare named secrets that must start with
MODULE_<UPPER_NAME>_*. The host rejects modules attempting to declare names outside their prefix at registration, preventing exfiltration of Drift core secrets. - Panic-isolated lifecycle —
Module::initandModule::shutdownare wrapped incatch_unwind. Module HTTP handlers are wrapped in a tower panic guard. A misbehaving module is markedDisabledand Drift continues running. - Test harness in the API crate —
MockContextBuilderplus full mocks for every read trait. Module authors can unit-test in isolation without spinning up a real Drift instance. - Vendor-neutral by design — the OSS Drift repo contains no references to any specific module, vendor, or commercial product. The default module list is empty. Composing additional modules into a Drift build is done by replacing a single stub file at build time.
For a complete walkthrough including a hello-world example, capability declarations, event handling, testing, and a list of v1.0 known limitations, see the Module Developer Guide.
Configuration is optional for getting started. The setup wizard handles initial setup.
For advanced configuration (OIDC, syslog, CertWarden, custom bind address), see docs/configuration.md.
- FEATURES.md — Complete feature list
- CHANGELOG.md — Release history
- SECURITY.md — Vulnerability reporting policy
- docs/troubleshooting.md — Common issues and solutions
- docs/configuration.md — Configuration reference with OIDC provider guides
- docs/auth.md — Authentication architecture
- docs/behavior-engine-whitepaper.md — Anomaly detection engine
- docs/topology-engine-whitepaper.md — Network topology inference
- docs/investigation-engine-whitepaper.md — Automated investigation engine
- docs/correlation-engine-whitepaper.md — Identity correlation engine
- docs/connection-store-whitepaper.md — Connection tracking and GeoIP
- docs/policy-editor.md — Policy editor and deviation detection guide
- docs/deviation-limitations.md — Detection visibility boundaries and evasion techniques
- docs/router-setup.md — MNDP configuration, API user setup, and provisioning overview
- docs/module-developer-guide.md — Module API developer guide (Module trait, capabilities, events, storage, testing, hello-world example)
- ROADMAP.md — Product roadmap and milestones to v1.0
- Secrets encrypted at rest (AES-256-GCM)
- Local auth with argon2id password hashing, or OIDC with any provider
- HMAC-SHA256 signed sessions with HttpOnly/Secure cookies
- CSRF protection, rate limiting, security headers
- No telemetry, no phone-home — runs fully air-gapped with the vulnerability feed off (see Outbound connections)
See SECURITY.md for reporting vulnerabilities.
Ion Drift was built entirely by AI coding agents under the direction and architectural guidance of Scott Baird, founder of Cyber Hive Security LLC.
100% of the source code — backend, frontend, CLI, database schemas, authentication system, behavioral analytics engines, topology inference, and all supporting infrastructure — was written by Claude Code (Anthropic) and Codex (OpenAI). This includes:
- All Rust backend code (Axum web server, RouterOS/SNMP/SwOS clients, SQLite storage, AES-256-GCM encryption, OIDC and local auth)
- All React/TypeScript frontend code (dashboard, topology map, Sankey diagrams, settings UI)
- Security reviews, code audits, and vulnerability remediation
- Refactoring, performance optimization, and architectural decisions
- Documentation, engine whitepapers, and configuration guides
- Licensing system, setup wizard, and deployment infrastructure
- Docker packaging and CI/CD configuration
No line of code was written by a human. Human contribution was limited to product vision, architecture direction, feature prioritization, acceptance testing, and deployment into the production homelab environment where Ion Drift runs today.
This project demonstrates that AI coding agents can produce production-grade, security-conscious software when guided by a knowledgeable operator who understands the problem domain.
Ion Drift is self-hosted and sends no telemetry. It talks to the devices you configure and to services an administrator configures (for example an OIDC provider, MaxMind GeoIP downloads, alert webhooks, or CertWarden). The vulnerability feed is the only outbound connection Ion Drift makes on its own.
The vulnerability feed downloads public RouterOS vulnerability data once a day from:
services.nvd.nist.gov— NIST National Vulnerability Databasewww.cisa.gov— CISA Known Exploited Vulnerabilities catalog
These are plain HTTPS downloads; nothing about your installation, network, or devices is sent. The feed is on by default, but no request is made until an administrator confirms it in the dialog shown at first login. It can be turned off at any time in Settings → Security. With it off, Ion Drift stops downloading vulnerability data: checks continue against the data it last downloaded (if any) and the advisories bundled with the installed release, but newly published or newly exploited RouterOS vulnerabilities are not learned.
PolyForm Shield License 1.0.0 with the Cyber Hive Security Use Agreement.
Personal home use is free. Commercial use requires a license from Cyber Hive Security.
Copyright (c) 2026 Cyber Hive Security LLC









