Skip to content

RoMON connection

Daniel Frantík edited this page Sep 25, 2026 · 8 revisions

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.

Connecting

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. Leave Port unset on the target setup — the port that is dialled is the agent's.

Which transports

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.

No IP at all: MAC-Telnet to 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, listen, monitors and Tab-completion

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.

Finding the target's RoMON id

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.

What the routers need

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.

Which route did the connection take?

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.

When it fails

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.

When the relay ends while the connection is open

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.

Security

  • 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 address restriction 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 port secrets and forbidden ports instead.

See also

Start here

API levels

Entities

Transports

Safety & diagnostics

Project

Clone this wiki locally