tik4net is the most complete .NET library for talking to MikroTik RouterOS devices. Every way into a
router is available — the binary API, REST, Telnet, SSH, MAC-Telnet and the WinBox channel, over IP or
straight over the MAC layer — and they all sit behind one ITikConnection interface. You work with
whatever the router already has enabled instead of reconfiguring it first, and switching transport is one
enum value; the rest of your code does not change.
Work at whichever level suits the task — raw sentences, an ADO.NET-shaped command API, or a fully typed O/R mapper — on the same connection, mixing them freely. Response parsing, terminal and paging quirks, both API login handshakes and correlating replies to their caller are handled for you; what a transport genuinely cannot do, it tells you through its capabilities instead of quietly doing the wrong thing. The surface is large, and the first working program is five lines.
Tested and debugged against RouterOS 7.24.5 — every transport verified against a live router — and also tested on RouterOS 7.21.5 and 6.49.13 (RouterOS versions).
5.0 — in development on master, not released yet:
- RoMON — reach a router you have no IP route to, through a neighbouring router, over Telnet, SSH or MAC-Telnet; RoMON discover and ping included
- One codebase from RouterOS 6.49 to 7.24 — the same entities read and write correctly on each version, tested on 7.24.5, 7.21.5 and 6.49.13 (RouterOS versions)
- TikField — a property knows whether the router printed the field; it never invents a default, and a value from a newer RouterOS does not break the read
- Ask the router what a menu takes —
DescribeMenulists a menu's sub-menus and commands, the arguments each command takes, the fields it reads and can clear, the words an argument accepts and the router's description of each, from the router's own grammar - Connection string —
TikConnectionSetup.FromConnectionString: the router, the credentials and the transport come from config, not code - Negated matchers —
src-address=!10.0.0.0/8reads as a negated10.0.0.0/8, not as a string starting with! - Value lists — a field of several values
(
dst-port=22,8291,connection-state,tcp-flags=syn,!ack, DNS servers) is a typed, immutable list, each item with its own!where the router takes one - Compile-time checks for
TikFieldcomparisons — warning TIK001 flagsobject.Equals("x", rule.Comment)and its kin, which are never equal, and TIK002Assert.IsNull(rule.Comment), which is never null; both with a fix to.Value - SSH private-key login —
SshPrivateKeylogs in with a key instead of a password - List sync with the fewest moves — merge and
SaveListDifferencesreorder firewall rules with minimal moves, sync and async - Filtered CLI reads run on the router — the filter goes into the command instead of the whole table coming back
- Upgrade with an AI agent — a ready-to-paste prompt that does the 4.x → 5.0 migration
4.0 — the current release:
- Eleven ways into the router, one contract — API and API-SSL, REST, Telnet, SSH, MAC-Telnet and WinBox (terminal or native); switching transport is one enum value
- Manage a router that has no IP address — MAC-Telnet and WinBox over the MAC layer, found by MNDP discovery; the only .NET library that speaks MAC-Telnet and the WinBox protocols
- Safe Mode — take, release, unroll, and automatic rollback when the connection drops
- MCP server — an AI assistant drives a router over any transport, with a raw protocol trace
- Change tracking —
Savesends only the fields you changed; a save with no changes sends nothing - Fail-closed capabilities and typed per-transport interfaces — a transport's limits are compile errors or clear refusals, never quiet wrong behaviour
- Streaming and async —
IAsyncEnumerablereads and parallel commands such as torch, with in-flight cancellation TikConnectionSetup, one entry point — fornetstandard2.0andnet8.0, with nullable annotations- Upgrade with an AI agent — a ready-to-paste prompt that does the 3.x → 4.0 migration
Every change, version by version: History.
| Package | NuGet | Description |
|---|---|---|
| tik4net | Everything you normally need: the low-level ADO.NET-like API (sync and async R/W access) and the high-level O/R mapper (strongly typed entities, full CRUD) | |
| tik4net.testing | Unit-testing support — TikFakeConnection lets you write tests without a live router |
|
| tik4net.ssh | The SSH transport (TCP 22) — a separate package because of its SSH.NET (Renci.SshNet) dependency |
⚠️ Upgrading from 3.x? The O/R mapper is now part oftik4netitself — remove anyPackageReferencetotik4net.objectsor you will get an assembly conflict. Your source code does not change. See Upgrading from 3.x to 4.0.
- Easy to use with the O/R mapper high-level API — strongly typed entities, full CRUD
- Low-level API when you need to send the transport's own language unchanged
- One connection contract over every transport, including the MAC-layer ones that reach a router with no IP address
- Broad range of .NET runtimes supported (including .NET Framework, Xamarin and Unity)
- Both API login handshakes, old and v6.43+, negotiated automatically
- MNDP discovery helper — find routers on the segment with no connection at all
- Safe Mode —
SafeModeTake()/SafeModeRelease()/SafeModeUnroll()with automatic rollback-on-disconnect (lockout protection) - Change tracking —
Savesends only the fields you changed; no-op saves skip the API call - Connection capability model —
connection.Supports(TikConnectionCapability.Listen); unsupported features fail closed - Unit testing without a router via
tik4net.testing(TikFakeConnection) - Uniform exception tree across all transports
- Entity scaffolding from a live router, and an MCP server that lets an AI assistant drive a router over any tik4net transport
- Easy to understand and well documented code
All transports share the same ITikConnection API and O/R mapper — pick one via TikConnectionType. See
Connection types and capabilities
for what each capability means in practice, and for the per-transport detail behind this table.
| Transport | Port | What it is | Capabilities |
|---|---|---|---|
| Api / ApiSsl | TCP 8728 / 8729 | native MikroTik API protocol — the default and fastest; TLS variant needs a certificate on the router | every one but the two WinBox-native ones: Crud, Listen, Streaming, Tagging, SafeMode, RawCommand, AsyncCommands, CancelInFlight, MenuSchema |
| Rest / RestSsl | TCP 80 / 443 | REST API, RouterOS 7.1+ | Crud, Listen, AsyncCommands, CancelInFlight, MenuSchema — stateless HTTP, so no streaming and no Safe Mode |
| Telnet | TCP 23 | RouterOS CLI over plain-text Telnet | Crud, Listen, SafeMode, RawCommand, AsyncCommands, MenuSchema |
| Ssh | TCP 22 | RouterOS CLI over an SSH shell (separate tik4net.ssh package) |
Crud, Listen, SafeMode, RawCommand, AsyncCommands, MenuSchema |
| MacTelnet | UDP 20561 | CLI over MAC-Telnet — reaches a router with no IP route, or no IP address at all | Crud, Listen, SafeMode, RawCommand, AsyncCommands, MenuSchema |
| WinboxCli / WinboxCliMac | TCP 8291 / UDP 20561 | CLI over the encrypted WinBox channel (EC-SRP5 + AES, no certificates) | Crud, Listen, SafeMode, RawCommand, AsyncCommands, MenuSchema |
| WinboxNative / WinboxNativeMac | TCP 8291 / UDP 20561 | structured WinBox M2 CRUD, no terminal — experimental: fields are addressed by number, and the API-name ↔ M2 mapping is reconstructed rather than published | Crud, Listen, SafeMode, AsyncCommands, CancelInFlight, FieldLabels, MenuSchema, StructuredWrites |
What the table does not say, in one line each — the capabilities page has the rest:
Listenis server push on the binary API and emulated by polling everywhere else;Streaming(a blocking multi-row read) is binary-API only.RawCommandsends a command in the transport's own language, unchanged — API words on the API, real CLI text on the terminal transports. REST and WinBox native have a request shape rather than a language, so they do not offer it.AsyncCommandsis theTask-based surface with aCancellationToken;CancelInFlightadds that a cancel after dispatch really stops the wait and leaves the connection usable — on the CLI transports a cancel is correct but no faster than the command itself.StructuredWritesmeans a field is written as structured data rather than as the router's textset. It matters for one field so far: a textsetoftcp-flagsreplaces only the half it names (plain or negated members), so over the API, REST and the CLI a change that leaves one half empty is refused before sending, while WinBox native writes it exactly.- Connections are reusable on every transport. Concurrent commands on one connection work on
Api/ApiSsl,Rest/RestSsland both WinBox-native transports; the CLI family drives a single terminal and serializes by design.
Install via NuGet — see the package table above, or:
dotnet add package tik4net # low-level API + O/R mapper — start here
dotnet add package tik4net.testing # unit-testing support
dotnet add package tik4net.ssh # SSH (TCP 22) transport
Runtimes: the packages target netstandard2.0;net8.0 — usable from .NET Framework 4.6.1+, .NET Core
2.0+, .NET 5 and newer, Xamarin and Unity, with no runtime dependencies. The net8.0 build additionally
carries the async streaming API (see
ADO.NET-like API).
See release notes / version history for what's new.
A complete first program — connect, read a typed list, create a rule:
using tik4net;
using tik4net.Objects;
using tik4net.Objects.Ip.Firewall;
// TikConnectionSetup is the entry point: it carries every option and opens the transport you name.
// TikConnectionType.Api works for both the old and the new (v6.43+) login.
var setup = new TikConnectionSetup(HOST, USER, PASS);
using (ITikConnection connection = setup.Create(TikConnectionType.Api))
{
ITikCommand cmd = connection.CreateCommand("/system/identity/print");
Console.WriteLine("Identity: " + cmd.ExecuteScalar());
foreach (Log log in connection.LoadList<Log>())
Console.WriteLine("{0}[{1}]: {2}", log.Time, log.Topics, log.Message);
connection.Save(new FirewallFilter()
{
Chain = FirewallFilter.ChainType.Forward,
Action = FirewallFilter.ActionType.Accept,
});
}Project wiki:
- Getting started — step-by-step first project (NuGet → connect → CRUD)
- wiki root
- How to use tik4net — picking the right API level
- CRUD examples for all APIs
- Connection types and capabilities — pick a transport and see what it supports
- Exception handling — the full exception tree
- Safe Mode · Change tracking — the flagship 4.0 features
- Communication debugging — protocol words and raw wire bytes
- Unit testing without a router —
TikFakeConnection, tests with no hardware - History
Examples and help:
- example project — including asynchronous commands such as
/tool/torch - VisualBasic example
- support forum
MikroTik's own protocol documentation:
- ARCHITECTURE.md — how the codebase is laid out: the transport family, the capability model, the O/R mapper internals, and where the risky code lives. Read this before any non-trivial change.
- AGENTS.md — working rules and the documentation map. Written for AI coding agents, but it is the shortest accurate description of how this project is worked on, so it is worth reading either way.
- Docs/ — protocol ground truth: what the router actually does on the wire, established by live probing. Docs/HISTORY.md holds the project's superseded diagnoses and dated incidents.
- Each project directory has its own
README.mddescribing what it is and what belongs in it. - Tests: tik4net.unittests runs in CI on every pull request; tik4net.integrationtests needs a live router. If a test does not need hardware, it belongs in the former.
- I am looking for collaborators. If you are interested in helping maintain this project, please reach out — open an issue or contact me directly.
- create highlevel classes for all mikrotik entities (you can still generate your own classes)
- create tiklink project - easy use-to wrapper over mikrotik router with fluent API
- convert examples to separate unittests (in progress)
- tiktop — a MikroTik traffic monitor inspired by Linux
iftop(currently in alpha, available on NuGet/GitHub)
- Apache 2.0.