Aller au contenu

MikroTik RouterOS

This page covers administrative access to a MikroTik router over RADIUS. It is the device-side counterpart to RADIUS.

PlatformSoftwareWhat was verified
MikroTik CHR (x86_64)RouterOS 7.5 (stable)RADIUS administrative login over SSH with MS-CHAPv2, for both local and Active Directory accounts; user-group assignment via Mikrotik-Group; login accounting; 802.1X and MAC authentication with VLAN assignment; CoA Disconnect

This is the first thing to know, because it decides whether anything works at all.

RouterOS does not send the password as PAP. Every Access-Request it produces for an administrative login carries MS-CHAP-Challenge and MS-CHAP2-Response:

sending Access-Request with id 30 to 10.0.0.20:1812
Service-Type = 1
User-Name = "ad_user1"
MS-CHAP-Challenge = 0x62c0175b3701c8cfbe5fb74390bf59df
MS-CHAP2-Response = 0x0000d8fca3d1cec9412f03e395aed10a…
Calling-Station-Id = "10.6.0.110"
NAS-Identifier = "MT-DEMO"
NAS-IP-Address = 10.0.0.11

and a successful reply carries MS-CHAP2-Success:

received Access-Accept with id 30 from 10.0.0.20:1812
MS-CHAP2-Success = 0x00533d38393136423546344342423845…
Service-Type = 1
Session-Timeout = 3600
Idle-Timeout = 600

What follows from that:

Your identity source has to be able to answer MS-CHAPv2. Unlike PAP, MS-CHAPv2 is a challenge–response exchange that cannot be satisfied by a plain directory bind. For directory-backed accounts the branch is chosen by the user’s own directory, and that directory has to be one that can serve MS-CHAPv2: either the Active Directory the node has joined — of which there is at most one — or a directory that publishes a readable NT hash, such as FreeIPA’s ipaNTHash. The two are not alternatives: a node may hold a domain join and any number of hash-readable directories at the same time. See MS-CHAPv2 for directory accounts.

Every successful login is preceded by a rejected one

Section titled “Every successful login is preceded by a rejected one”

RouterOS probes the SSH none authentication method before it prompts the human, and it does so by sending a complete MS-CHAPv2 Access-Request whose response proves the empty password. That request is neither optional nor a misconfiguration: exactly one arrives before every interactive login, including the ones that succeed.

Taranac rejects it — it has to — and records it under its own reason, empty_password_probe, shown in the authentication log as Empty password (device probe). That reason is excluded from everything that counts failures:

  • it does not feed the brute-force guard, which would otherwise halve the configured threshold for exactly the devices that need MS-CHAPv2;
  • it is left out of the authentication-failure rate and out of the dashboard’s top failed authentications widget, which on a MikroTik-heavy installation was topped by the customer’s own administrators, one entry per successful login.

The row itself stays in the log on purpose — a packet that really arrived is not hidden. So a healthy RouterOS login is two rows for the same username: a rejected probe, then an accepted login. Only the second one is a login.

MS-CHAPv2 decides what is possible here, and the answer is narrow: push is the only workable second factor on this platform. This is not a gap waiting to be closed — two of the three MFA modes cannot work over MS-CHAPv2 even in principle.

One-time passwords appended to the password do not work, and cannot be made to. MS-CHAPv2 never carries the password. It carries a response derived from the NT hash of exactly the string the user typed. Append an OTP and the router hashes password+OTP, which will never match the stored password — and the server cannot separate the two halves back out, because it never receives either one in the clear.

Challenge mode does not work either, for a separate and more mundane reason: RouterOS runs no second round for an administrative login, so an Access-Challenge has nowhere to go.

Push works normally. The password is verified by MS-CHAPv2 as usual, and the second factor happens out of band — the server holds the exchange open while the user approves on their phone. Verified on this platform with the Telegram and Email push providers.

The behaviour is fail-closed, and Taranac distinguishes two rejection reasons so you can tell the cases apart:

Reject reasonMeaning
mfa_provider_unsupportedThe user’s MFA provider cannot work over MS-CHAPv2 — typically a TOTP/OTP factor. Move that user to a push provider.
mfa_not_configuredPolicy requires MFA and the user has no factor enrolled at all.

Both surface as a plain Access-Reject to the router, which shows the user nothing but a failed login — so the distinction lives in Taranac’s authentication log, and that is where to look when someone says “my password works everywhere else”.

Everything above applies to any platform that authenticates over MS-CHAPv2, not just MikroTik. And note the interaction with the RADIUS timeout below: push is the one mode that works here, and it is also the one that needs the timeout raised.

/radius
add address=10.0.0.20 secret="<RADIUS_SECRET>" service=login timeout=3s comment="Taranac device-admin"

service=login is what scopes this server entry to administrative login. RouterOS uses the same /radius list for every RADIUS-consuming subsystem, so a router that also does 802.1X carries a second entry with service=dot1x pointed at the NAC ports:

add address=10.0.0.20 secret="<RADIUS_SECRET>" service=dot1x authentication-port=1814 accounting-port=1815 timeout=3s comment="Taranac NAC"

Both entries point at the same server and therefore carry the same secret: it is the radius_secret on this router’s device entry in Taranac, and it must match byte for byte. See Network devices for the device → device group → global chain.

Leaving the ports off the first entry uses the RADIUS defaults, 1812/1813, which is what a standard Taranac deployment listens on for device administration. The NAC service listens on 1814/1815 and must be named explicitly. Getting these the wrong way round produces a server that answers with the wrong policy engine rather than an error.

/user aaa
set use-radius=yes accounting=yes default-group=read

use-radius=yes is the master switch. accounting=yes is what produces the Accounting-Request pairs that create login records in Taranac — a router without it authenticates perfectly and reports nothing.

interim-update controls periodic updates during a session; the tested router leaves it at 0s, which sends start and stop only.

The attribute Taranac must return is Mikrotik-Group (vendor 14988, VSA type 3), carrying the name of a RouterOS user group. The built-ins are full, write and read; custom groups work too, and the name has to match exactly.

/user group print detail
0 name="read" policy=local,telnet,ssh,reboot,read,test,winbox,password,web,sniff,…
1 name="write" policy=local,telnet,ssh,reboot,read,write,test,winbox,…
2 name="full" policy=local,telnet,ssh,ftp,reboot,read,write,policy,test,winbox,…

For this to work, the Taranac policy rule serving this device must return a profile built on the MikroTik RouterOS RADIUS template. A profile built on some other vendor’s template will authenticate the user perfectly and send an attribute the router does not understand — see below, because this failure is invisible unless you know its signature.

/ip service print

RADIUS login applies to the management services RouterOS exposes — ssh, winbox, www, api and others. Disable what you do not use; each enabled service is another path where an authorization mistake has consequences. SSH was the method verified here.

Turn on RADIUS logging first — RouterOS logs nothing about RADIUS by default:

/system logging
add topics=radius
add topics=radius,debug

The radius,debug topic prints every attribute of every packet, which is what makes this platform pleasant to diagnose. Turn it off again when you are done; it is noisy.

/radius monitor 0 gives the counter summary for the first server entry:

/radius monitor 0
pending: 0
requests: 32
accepts: 12
rejects: 20
resends: 0
timeouts: 0
bad-replies: 0
last-request-rtt: 10ms

timeouts and bad-replies at zero mean the server is reachable and the shared secret is right. resends climbing points at latency or loss. rejects are policy decisions, not transport problems.

/user active print detail shows who is connected and, crucially, how they authenticated:

/user active print detail
Flags: R - radius; M - by-romon
0 when=aug/02/2026 08:49:55 name="admin" via=console group=full
1 R when=aug/06/2026 08:32:21 name="ad_user1" address=10.6.0.110 via=ssh group=read

The R flag is the one to read: that session was authenticated by RADIUS. A session without it came from the local user database. The group= column shows which RouterOS group was actually applied — compare it against what your policy intended.

This pair of lines is the whole verification in one view. R proves Taranac authenticated the session; group=read proves the group assignment arrived and was applied, because a session that fell through to default-group would show that group instead.

received Access-Accept with id 40 from 10.0.0.20:1812
MS-CHAP2-Success = 0x00533d35303334364244304435433937…
Service-Type = 1
Session-Timeout = 3600
Idle-Timeout = 600
MT-Group = "read"

MT-Group present, named, and carrying a group that exists on the router. That is the line to look for.

If Taranac returns an authorization profile built on another vendor’s template, RouterOS accepts the login and logs the attribute it cannot use:

received Access-Accept with id 30 from 10.0.0.20:1812
Service-Type = 1
Session-Timeout = 3600
Idle-Timeout = 600
Unknown-Attribute(vendor=Cisco, type=1) = 0x7368656c6c3a707269762d6c766c3d3135

That hex decodes to shell:priv-lvl=15 — a Cisco AV-pair, sent to a MikroTik. RouterOS does not understand it, ignores it, and falls back to default-group.

Login accounting works and needs no configuration beyond accounting=yes. A session produces a start and a stop:

sending Accounting-Request with id 19 to 10.0.0.20:1813
User-Name = "ad_user1"
Acct-Status-Type = 1 ← start
Acct-Session-Id = "84000004"
NAS-Identifier = "MT-DEMO"
NAS-IP-Address = 10.0.0.11
…
sending Accounting-Request with id 20 to 10.0.0.20:1813
Acct-Status-Type = 2 ← stop
Acct-Session-Time = 8
Acct-Terminate-Cause = 1

For administrative login, Taranac matches the address the packets come from against the registered device; the NAS-IP-Address RouterOS writes into them plays no part (see How a request finds its device). RouterOS sends from the interface it uses to reach the server, so on a router with several routed interfaces check the device entry against the source address of these requests rather than against the address you think of as its management IP. The src-address property of the /radius entry pins it. See Network devices.

RouterOS can also act as an authenticator for endpoints, using the second /radius entry:

/interface dot1x server
add interface=ether4 auth-types=dot1x,mac-auth mac-auth-mode=mac-as-username-and-password accounting=yes

auth-types=dot1x,mac-auth enables 802.1X with MAC authentication as the fallback — RouterOS’s equivalent of MAB. mac-auth-mode=mac-as-username-and-password sends the endpoint’s MAC address as both username and password, which is the convention Taranac’s MAB matching expects.

VLAN assignment: wired and wireless read different attributes

Section titled “VLAN assignment: wired and wireless read different attributes”

RouterOS reads the assigned VLAN from two different attributes, depending on what authenticated the endpoint:

AuthenticatorAttribute RouterOS acts on
/interface dot1x server on a bridge port (wired)The RFC 3580 tunnel attributes: Tunnel-Type, Tunnel-Medium-Type, Tunnel-Private-Group-ID
Wireless (the access point’s RADIUS authentication)Mikrotik-Wireless-VLANID, with Mikrotik-Wireless-VLANIDtype = 0 (802.1Q)

Wireless ignores the tunnel attributes: it logs them, then places the station in no assigned VLAN — with vlan-mode=use-tag the station falls back to the interface’s own vlan-id, associates, and never gets an address.

Taranac’s mikrotik vendor dictionary entry therefore sends both for a profile’s VLAN — the MikroTik attribute first, the tunnel triplet after it — so one authorization profile is meant to serve a MikroTik switch port and a MikroTik access point alike. For VLAN 40 the Access-Accept carries, in this order:

AttributeValue
Mikrotik-Wireless-VLANID40
Mikrotik-Wireless-VLANIDtype0
Tunnel-TypeVLAN (13)
Tunnel-Medium-TypeIEEE-802 (6)
Tunnel-Private-Group-ID40

RouterOS prints its own attributes with an MT- prefix in the debug log. The wired assignment below was verified with the tunnel attributes; the wireless one follows from where RouterOS wireless takes the VLAN, measured separately.

For this entry to be used, pin it: set Vendor Dictionary (CoA) on the device to Mikrotik RouterOS (see Network devices). Otherwise the vendor is detected from the request or the device’s Vendor field, and an access point that is not recognised gets the generic entry — tunnel attributes only.

A NAC session records the VLAN Taranac assigned and the VLAN the device reported as two separate values, so accounting never overwrites the assignment and a disagreement between the two is visible instead of being averaged away. The port needs no decoding on this platform: RouterOS puts a readable interface name in NAS-Port-Id (ether2), which is what the NAS Port column shows as it arrives.

/radius incoming
set accept=yes port=3799

This opens the listener for change-of-authorization requests. Without it Taranac’s disconnects go nowhere and every session stays up until it ends on its own — with no error on either side.

port= is where the two sides have to agree, and it is worth being explicit about it. Taranac resolves the destination port for every CoA through device → device group → pinned vendor dictionary → nac.coa_port; the mikrotik entry declares 3799, which matches /radius incoming above. If the router listens on one port and Taranac sends to another, the CoA fails as a silent timeout: no NAK, nothing in the router’s log, and an operator staring at a disconnect that reports failure with no reason. The device’s Details card shows the resolved port and which level decided it.

The device card’s CoA test is not offered for RouterOS: the mikrotik entry declares no safe probe, so a CoA here is checked with a real Disconnect on a live session.

Confirmed working on the tested router:

received Disconnect-Request with id 63 from 10.0.0.20:52608
Acct-Session-Id = "0f000086"
User-Name = "00:50:79:66:68:06"
…
sending Disconnect-ACK with id 63 to 10.0.0.20:52608

Note what happens in between: the router tears the session down and sends its own Accounting-Stop with final counters before acknowledging the disconnect. That ordering is why a disconnected session closes cleanly in Taranac with real byte and packet totals.

The rest of the mikrotik entry in Taranac’s NAC vendor dictionary, for completeness:

WhatHow Taranac encodes it
VLANMikrotik-Wireless-VLANID + Mikrotik-Wireless-VLANIDtype = 0, then Tunnel-Type / Tunnel-Medium-Type / Tunnel-Private-Group-ID
Named ACLFilter-Id
Session timeoutSession-Timeout + Termination-Action = RADIUS-Request
Re-authenticationA Disconnect. MikroTik declares no native CoA reauth, so the endpoint reconnects rather than re-authenticating in place
VLAN changeA real CoA-Request carrying the same five attributes
Port bounce · port disableUnsupported
Downloadable ACL · URL redirectNot declared. URL redirect is declared by Cisco IOS / IOS-XE alone

The Disconnect is the row verified on the tested router. Everything else in that table is what the dictionary declares from vendor documentation and has not been exercised here.

  • Local fallback. Whether local RouterOS accounts still work when Taranac is unreachable, and whether an explicit Access-Reject behaves differently from a timeout, has not been established. Keep a local account and verify it before relying on use-radius=yes.
  • Winbox, WebFig and API logins. Only SSH was verified.
  • Push providers other than Telegram and Email. Those two were verified; the remaining providers are expected to behave the same way, since the push path is shared, but have not been exercised over MS-CHAPv2.
SymptomLikely cause
Every RADIUS user gets full rightsdefault-group=full combined with a missing or unusable Mikrotik-Group. Check for Unknown-Attribute in the debug log.
Every RADIUS user gets full rights, and MT-Group = "full" is in the replyThe profile leaves Mikrotik-Group unset, so the template’s own default — full — is what gets sent.
Every successful login also logs a rejected empty_password_probeNormal, and not counted anywhere. RouterOS proves the empty password to probe SSH none before prompting.
Unknown-Attribute(vendor=Cisco…) in Access-AcceptThe Taranac profile is built on the wrong vendor template.
Directory users rejected, local users fineThat user’s directory cannot serve MS-CHAPv2 — it is neither the joined Active Directory nor a directory with a readable NT hash.
Push MFA always fails/radius timeout too low. The default is 300 ms; use 30s.
One user rejected, reason mfa_provider_unsupportedThat account uses a TOTP/OTP factor, which cannot work over MS-CHAPv2. Move it to a push provider.
One user rejected, reason mfa_not_configuredPolicy requires MFA and the account has no factor enrolled.
Logins work, nothing in Taranacaccounting=no in /user aaa.
Administrative login times out, nothing in the Taranac logThe router sends from an address no registered device covers. Register the source address of its requests, or pin it with src-address on the /radius entry.
CoA has no effect/radius incoming not set to accept=yes, or its port= differs from the port Taranac resolved (device → device group → pinned vendor dictionary → nac.coa_port). A port mismatch fails as a silent timeout.
Wireless client associates, VLAN assigned in Taranac, no addressThe access point reads Mikrotik-Wireless-VLANID, not the tunnel attributes. Pin Mikrotik RouterOS as the device’s Vendor Dictionary and check that entry’s VLAN mapping lists the two MikroTik attributes.
802.1X VLAN assigned in Taranac, port stays on its pvidThe bridge is not VLAN-aware. vlan-filtering=yes plus an /interface bridge vlan table are what the assignment is applied to.
Nothing in the log at allRouterOS logs no RADIUS topics by default — add them.