-
Notifications
You must be signed in to change notification settings - Fork 97
RoMON connection
🆕 New in 5.0. Reach a router that has no usable IP connectivity — or none from where you are — through a neighbouring MikroTik, over RoMON.
RoMON (Router Management Overlay Network) is MikroTik's own Layer-2 overlay: every RoMON-enabled router forwards for its neighbours, so a router stays reachable over several hops as long as a chain of RoMON-enabled MikroTiks connects it — whatever its IP configuration. No PC speaks RoMON, WinBox included; you log in to a RoMON-enabled router you can reach — the agent — and let it relay to the one you want — the target.
tik4net does it the same way. The connection logs in to the agent, then runs /tool romon ssh on the agent's
shell and continues inside it. From then on, every command — reads, CRUD, monitors, the O/R mapper — runs on the
target, unchanged.
using tik4net;
using tik4net.Objects;
using tik4net.Objects.System;
var agentSetup = new TikRomonAgentSetup("192.168.88.1", "admin", "agent-password");
var targetSetup = new TikConnectionSetup(TikRouterAddress.FromRomonId("AA:BB:CC:DD:EE:FF"), "admin", "target-password")
{
RomonAgentSetup = agentSetup,
};
using ITikConnection connection = targetSetup.Create(TikConnectionType.Ssh); // or Telnet, MacTelnet
Console.WriteLine(connection.LoadSingle<SystemIdentity>().Name); // the target's identity- The target setup describes the target: its RoMON id, its user and password, and every session option (timeouts, encoding, paging).
-
The agent setup says only where the agent is and who logs in to it: address, user, password, and
optionally
Port. That is all it can hold, so nothing set there is silently ignored. LeavePortunset on the target setup — the port that is dialled is the agent's.
Telnet, SSH and MAC-Telnet to the agent. TikConnectionSetup.SupportsRomon(type) tells you at runtime. Every
other transport is refused when the connection is created — it throws before anything connects, rather than
quietly running your commands on the agent.
Over MAC-Telnet the agent needs no IP address, and neither does the target — the MAC layer reaches the agent, RoMON reaches everything beyond it:
using tik4net;
var agentSetup = new TikRomonAgentSetup(TikRouterAddress.FromMac("AA:BB:CC:00:00:01"), "admin", "agent-password");
var targetSetup = new TikConnectionSetup(TikRouterAddress.FromRomonId("AA:BB:CC:DD:EE:FF"), "admin", "target-password")
{
RomonAgentSetup = agentSetup,
};
using ITikConnection connection = targetSetup.Create(TikConnectionType.MacTelnet);The agent's MAC belongs in the agent setup; RouterMac on the target setup is refused, like Port. Given a host
instead of a MAC, MAC-Telnet looks the agent's MAC up by MNDP, as it does for a direct connection.
Safe Mode works through the relay and is held on the target: SafeModeTake, SafeModeRelease
and SafeModeUnroll act on the target, never on the agent, and closing the connection while Safe Mode is held
rolls the change back on the target.
Listen (LoadListenWithCallback) and monitors (LoadWithCallback, or a bounded monitor such as ping count=2
read with LoadList) work as on a direct CLI connection: they are polled, and every poll goes to the target.
Tab-completion (ITikCliCompletion) lists the target's menus, and leaves the relay on the target.
A RoMON id looks like a MAC address, but it is not necessarily any of the router's MACs: it is its
/tool romon current-id. Ask the agent which ids it can reach:
using tik4net;
using tik4net.Objects;
using tik4net.Objects.Tool.Romon;
using (ITikConnection agent = new TikConnectionSetup(HOST, USER, PASS).Create(TikConnectionType.Api))
{
foreach (ToolRomonDiscover neighbour in agent.RomonDiscover(3))
Console.WriteLine($"{neighbour.Address} {neighbour.Identity} hops={neighbour.Hops}");
}Discovery works over any transport — see Entity helpers. A bare string is never read as
a RoMON id (it would be a MAC); TikRouterAddress.FromRomonId is the only way to say it.
| Router | Needs |
|---|---|
| Agent | RoMON enabled (/tool romon set enabled=yes); the transport you use to reach it (Telnet, SSH, or MAC-Telnet through /tool mac-server) |
| Target | RoMON enabled and reachable from the agent; a user whose group has the ssh policy
|
The target's IP ssh service is not used — it can be disabled. The ssh policy of the user is.
A target user with an empty password works too: RouterOS then asks for no password and shows its change-password prompt instead, which tik4net declines — the account's password is never changed.
using tik4net;
TikRomonConnectionInfo? info = connection.GetRomonConnectionInfo(); // null on a direct connection
if (info != null)
Console.WriteLine($"{info.Target.RomonId} via {info.Agent.Address} ({info.Agent.ConnectionType}), " +
$"agent RoMON id {info.Agent.RomonId}");info.Agent.RomonId is what the target records as by-romon in /user/active — the way to find this
session in the target's own records. The info never carries a password.
A failed login to the agent is a TikConnectionLoginException whose message starts with
RoMON agent <address> refused the login. An agent that is not reached at all — its port refuses the
connection, or the connect times out — is the SocketException itself, as on a direct connection. Anything after that is a TikRomonRelayException (also a
TikConnectionLoginException, so existing catch blocks keep working) with a Reason:
Reason |
Meaning |
|---|---|
TargetUnreachable |
The agent cannot reach that RoMON id — check RomonDiscover on the agent |
RomonNotEnabledOnAgent |
RoMON is off on the agent |
TargetRefusedLogin |
Wrong password, or the user's group lacks the ssh policy — the router answers both the same way |
TargetDidNotRespond |
The target never reached its shell prompt |
NotTheTarget |
A prompt came back but it is not the target's (for example the relay fell back to the agent) |
TransportFailed |
The connection to the agent broke while relaying — see InnerException
|
tik4net confirms it reached the right router: once the target's prompt is up, the target must report the RoMON
id you asked for. Two factory-default routers show the same prompt ([admin@MikroTik] >), so a prompt alone
proves nothing.
On a refused login tik4net sends the target exactly one password and then backs out — every further attempt would be another failed-login entry in the target's log.
If the target logs the session out, reboots, or drops out of the RoMON overlay, the relay ends — and the agent
would hand its own prompt back. tik4net never lets a command run there: the agent's session is ended with the
relay, and the command raises TikRomonRelayEndedException. The connection is closed; open a new one to go on.
CommandMayHaveRun tells the two cases apart. true: the relay ended while the command was running, so it may
have taken effect on the target (a /system reboot ends the relay exactly so). false: it had already ended and
the command was never sent.
Over MAC-Telnet, RouterOS logs a console out after about 30 s of idle. tik4net reconnects as it does for a direct MAC-Telnet connection, and relays to the target again before it resends the command.
- RoMON itself is not encrypted — its secrets authenticate messages, they do not hide them. The overlay hop here is SSH, so it is encrypted.
- The agent sees everything. It runs the SSH client, so the whole session — and the target's password — is in clear on the agent. Use an agent you trust as much as the target.
- The leg to the agent is as private as the transport you choose. Over Telnet and MAC-Telnet, the target's password crosses the network in cleartext. Prefer SSH to the agent where there is IP.
-
A user's IP
addressrestriction does not limit RoMON logins. The target sees the agent's RoMON id as the source, not an IP. Anyone who can use RoMON on a neighbouring router can reach that account — restrict RoMON with/tool romon portsecrets and forbidden ports instead.
Start here
- Getting started — first project
- Which API level?
- One task, every transport & level — 29 runnable programs
- CRUD examples, all levels
- Upgrading from 3.x · with an AI agent
- Upgrading from 4.x to 5.0 · with an AI agent — unreleased
API levels
-
High-level — O/R mapper
- Reading data
- CRUD · async CRUD
- Advanced — streaming, ordering
- Change tracking
- List merging
- ADO.NET-like — commands, parameters
- Low-level — raw sentences
- VB.NET example
Entities
- Entity reference — all 171 menus
- How the mapping works
- TikValue — what a loaded property holds, and why
- Custom entities
- Value types · helpers
- Scaffolding tools
Transports
- Types & capabilities — the matrix
- Threading & concurrency — sharing one connection
- API-SSL · login versions
- REST
- Telnet · SSH
- MAC-Telnet
- RoMON — through a neighbouring router
- WinBox CLI · over MAC
- WinBox native · over MAC
- Command translation
- MNDP discovery
- Writing your own transport
Safety & diagnostics
- Safe Mode — rollback protection
- Exception handling
- Communication debugging
- Testing without a router
Project
- RouterOS versions — what is tested, and how versions differ
- MCP server
- History / changelog