MikroTik Security Hardening: 10 Checks Most People Miss

Nine services and settings that stay active on a hardened RouterOS 7.24 router and never appear in its export, with the commands to find each one.

There is a specific moment, usually about four minutes into an incident call, when someone pastes a router’s /export into the chat and says “the config looks fine.”

The config does look fine. That is the problem.

/export records the difference between your device and its factory state. Anything you never changed is absent — not shown as a default, not shown as off, just absent. So a service that was listening the day the device booted is invisible in exactly the artefact everyone reviews.

Everything below was run on a RouterOS 7.24 router that had already been hardened: FTP, Telnet, HTTP and the API were explicitly disabled, and the input chain ends in a drop rule. It is not a factory-default box. That makes the result more interesting rather than less, because nine things were still switched on and none of them appeared in the export.

1. Services you never touched

/ip service print
Flags: D - DYNAMIC; X - DISABLED, I - INVALID; c - CONNECTION
Columns: NAME, PORT, PROTO, CERTIFICATE, VRF, MAX-SESSIONS, LOCAL
 #     NAME                PORT  PROTO  CERT  VRF   MA  LOCAL
 0  X  ftp                   21  tcp          main  20
 1     ssh                   22  tcp          main  20
 4  X  telnet                23  tcp          main  20
 9  X  www                   80  tcp          main  20
10  X  www-ssl              443  tcp    none  main  20
11     reverse-proxy        443  tcp    none  main  20
14     winbox              8291  tcp          main  20
15  X  api                 8728  tcp          main  20
16  X  api-ssl             8729  tcp    none  main  20

The X flags are the hardening. Those five lines appear in the export, because disabling them was a change:

/ip service
set ftp disabled=yes
set telnet disabled=yes
set www disabled=yes
set api disabled=yes
set api-ssl disabled=yes

Now look at what has no X and no corresponding export line. winbox on 8291 and reverse-proxy on 443 are both enabled, and neither appears anywhere in /export.

Winbox is at least expected. reverse-proxy is worth stopping on: a service listening on 443, on by default, that most people have never configured and would not find by reading their own configuration. I have not yet established what it is for or what it exposes, and I would rather say that than guess. Check your own devices and see whether it is running.

Neither service is address-restricted. Note the empty LOCAL column on rows 1, 11 and 14 — no address= constraint, so they answer on every interface the firewall permits.

The fix for both is the same, and it is the part people skip:

/ip service set winbox address=10.10.10.0/24
/ip service set ssh address=10.10.10.0/24

A disabled service is closed. A service reachable only from your management subnet is closed to everyone who matters and still usable by you.

2. MAC-Telnet, which ignores your firewall

/tool mac-server print
/tool mac-server mac-winbox print
/tool mac-server ping print
  allowed-interface-list: all

  allowed-interface-list: all

  enabled: yes

All three defaults, all three invisible in the export.

This one surprises people who have written a careful input chain. MAC-server access operates at layer 2 and does not traverse the IP firewall, so every rule you wrote is irrelevant to it. Anyone on the same broadcast domain can attempt to reach the router by MAC address — including anyone on the segment your WAN port sits in.

/interface list add name=MGMT
/interface list member add list=MGMT interface=ether3
/tool mac-server set allowed-interface-list=MGMT
/tool mac-server mac-winbox set allowed-interface-list=MGMT
/tool mac-server ping set enabled=no

Setting allowed-interface-list=none is safe only if you have another working path to the device. MAC-Winbox is how people recover a router they have locked themselves out of. Restrict it to one trusted interface rather than removing it.

3. Neighbour discovery

/ip neighbor discovery-settings print
   discover-interface-list: static
         discover-interval: 30s
                  lldp-med: yes
                  protocol: cdp
                            lldp
                            mndp
                      mode: tx-and-rx

The default is static, not all — a distinction worth being precise about. It means every statically configured interface, which on a typical edge router includes the WAN. The router announces its identity, model and RouterOS version to whatever is on the other side of that link.

Note protocol includes CDP and LLDP as well as MNDP, and mode: tx-and-rx. It is both advertising and listening.

/ip neighbor discovery-settings set discover-interface-list=MGMT

Version disclosure is not an exploit by itself. It is how somebody decides you are worth the effort.

4. The bandwidth test server

/tool bandwidth-server print
                  enabled: yes
             authenticate: yes
  allocate-udp-ports-from: 2000
             max-sessions: 100
       allowed-addresses4:
       allowed-addresses6:

Enabled, with a hundred permitted sessions and no address restriction. authenticate: yes means a valid login is required, which is genuine mitigation — but a bandwidth test will saturate CPU on a small device, and this is a denial-of-service primitive that ships switched on and stays out of the export.

/tool bandwidth-server set enabled=no

If you use it, populate allowed-addresses4 rather than leaving it open.

5. An open DNS resolver

/ip dns print
                servers: 203.0.113.1
  allow-remote-requests: yes
             cache-size: 2048KiB

This one does appear in the export, because it was set deliberately:

/ip dns set allow-remote-requests=yes servers=203.0.113.1

Worth including anyway, because it is the check people most often assume is fine. If allow-remote-requests is yes and your firewall does not block UDP/53 inbound on the WAN, the router is an open resolver and internet-wide scanning will find it within days. It then becomes a DNS amplification reflector aimed at somebody else.

The LAN usually does need the router as its resolver, so block it at the edge rather than turning it off:

/ip firewall filter
add chain=input in-interface-list=WAN protocol=udp dst-port=53 action=drop
add chain=input in-interface-list=WAN protocol=tcp dst-port=53 action=drop

6. Proxy, SOCKS and UPnP

/ip proxy print
/ip socks print
/ip upnp print
  enabled: no
  enabled: no
  enabled: no

All three off by default, and all three absent from the export — which means an enabled one would also be easy to overlook if you inherited the device. An enabled SOCKS proxy on a router nobody deliberately configured as one is worth treating as a compromise indicator rather than a misconfiguration.

7. The admin account

/user print detail
0  ;;; system default user
   name="admin" group=full inactivity-timeout=10m inactivity-policy=none
   address="" last-logged-in=[redacted]

/user does not appear in the export at all. The account with full privileges on this router, the username every attacker already knows, and address="" meaning it may be used from anywhere — none of it is in the configuration you would review.

/user add name=YOURNAME group=full password="..." address=10.10.10.0/24
# log in as YOURNAME on a separate session and confirm it works, then:
/user remove admin

The address= restriction limits where the account may be used from and is independent of the service restriction in check 1. Have both.

8. SSH accepting weak ciphers

/ip ssh print
                           ciphers: auto
                forwarding-enabled: no
           password-authentication: yes-if-no-key
  publickey-authentication-options: none
                     strong-crypto: no
                     host-key-size: 2048
                     host-key-type: rsa

Every line a default, the whole block invisible in the export. strong-crypto: no permits older ciphers and MACs, and the host key is 2048-bit RSA.

/ip ssh set strong-crypto=yes

Confirm your management tooling still connects afterwards — old jump hosts occasionally cannot. Regenerating the host key to a stronger type is a separate step, and changing it will make every client warn about a changed fingerprint, so do it deliberately rather than during an incident.

9. RoMON

/tool romon print
  enabled: no
       id: 00:00:00:00:00:00

Off by default here, and absent from the export. RoMON is layer-2 device-to-device management and genuinely useful, but it is also a lateral movement path: a compromised device on the same segment can reach others through it. If you find it enabled on a device you inherited, that is worth explaining before dismissing.

10. The firmware behind the software

Two separate things update on a MikroTik. /system package update handles RouterOS. The RouterBOOT firmware has its own version, and upgrading RouterOS does not upgrade it — you have to run /system routerboard upgrade and reboot. A device patched for years can still be running its original bootloader.

This check does not exist on CHR, which is what the rest of this article was verified on. There is no RouterBOOT to be out of date, and the command is not recognised:

[admin@hq-edge-01] > /system routerboard print
syntax error (line 1 column 20)

On physical hardware, run both:

/system package update check-for-updates
/system routerboard print

Compare current-firmware against upgrade-firmware. I will publish captured output for this check when the RB5009 it belongs to is back on my bench; until then it is the one item here I am describing rather than demonstrating.

The export, for comparison

Here is the export from the same router, taken immediately after every command above. The lab management interface and its firewall rule have been removed, and the system ID and a WireGuard peer key redacted — those omissions are marked.

# 2026-08-27 22:26:20 by RouterOS 7.24
# system id = [redacted]
#
/interface ethernet
set [ find default-name=ether1 ] disable-running-check=no
set [ find default-name=ether2 ] disable-running-check=no
/interface wireguard
add comment="Remote access" listen-port=13232 mtu=1420 name=wg-roam
/interface list
add name=WAN
add name=LAN
/ip pool
add name=lan-pool ranges=10.10.10.100-10.10.10.200
/ip dhcp-server
add address-pool=lan-pool interface=ether2 name=lan-dhcp
/interface list member
add interface=ether1 list=WAN
add interface=ether2 list=LAN
/ip address
add address=203.0.113.10/24 comment=WAN interface=ether1 network=203.0.113.0
add address=10.10.10.1/24 comment=LAN interface=ether2 network=10.10.10.0
/ip dhcp-client
add interface=ether1 name=client1
/ip dns
set allow-remote-requests=yes servers=203.0.113.1
/ip firewall filter
add action=accept chain=input connection-state=established,related
add action=drop chain=input connection-state=invalid
add action=accept chain=input protocol=icmp
add action=accept chain=input in-interface-list=LAN
add action=drop chain=input comment="drop all else"
/ip firewall nat
add action=masquerade chain=srcnat comment=masquerade out-interface-list=WAN
/ip route
add comment="Default via transit-01" dst-address=0.0.0.0/0 gateway=203.0.113.1
/ip service
set ftp disabled=yes
set telnet disabled=yes
set www disabled=yes
set api disabled=yes
set api-ssl disabled=yes
/system identity
set name=hq-edge-01

Read it as a reviewer would. There is no winbox, no reverse-proxy, no mac-server, no neighbor, no bandwidth-server, no user, no ssh, no romon. Every one of them is running. The only reason the disabled services appear is that somebody disabled them.

That is the whole point: an export tells you what was decided, not what is running.

Run all nine

/ip service print
/tool mac-server print
/tool mac-server mac-winbox print
/tool mac-server ping print
/ip neighbor discovery-settings print
/tool bandwidth-server print
/ip dns print
/ip proxy print
/ip socks print
/ip upnp print
/user print detail
/ip ssh print
/tool romon print

Ninety seconds. Then run /export and compare. Almost nothing you just looked at will be in it.

What to do next

Fix the findings on one device, then write down what you changed somewhere durable. The value is in doing this identically on every router you run, not in doing it once carefully.

Verified on RouterOS 7.24 (stable), build 2026-08-14, running as CHR on VMware Workstation. Behaviour changes between releases — check the version stamp against what you are running before assuming any of this transfers.