MikroTik RouterOS 7 is the most capable routing platform at its
price point, but it’s also one of the most complex to configure
correctly. A few wrong firewall rules can lock you out. A missing
FastTrack exception can tank your throughput. An exposed admin
interface on the WAN side is an invitation for scans and exploits.
This guide is a distilled set of best practices gathered from
running RouterOS 7 in production homelab environments. It covers
security hardening, firewall architecture, VLAN design with
bridge filtering, FastTrack performance tuning, DNS over HTTPS
setup, container management, and backup automation — all with
concrete commands that work on RouterOS 7.15 and later.
Every rule, setting, and script below has been tested on
MikroTik CCR, RB5009, hAP ax, and CHR deployments. Adjust
interface names and IP ranges to match your network.
1. Initial Security Hardening#
Before configuring anything else, lock down the router itself.
These steps disable the default attack surface that makes
unconfigured MikroTiks a target.
Change the Default Admin User#
The first thing every automated scanner tries: admin with a
blank or weak password.
1
2
3
4
5
6
7
8
9
10
|
# Create a new admin user with a strong name
/user add name=netadmin group=full \
password="!={zQ8mN4fL2xPv!}"
# Disable the default admin user (don't delete it — keep for
# emergency recovery via reset, but disable it)
/user disable admin
# Verify
/user print where disabled=no
|
Why disable instead of delete: RouterOS keeps the admin
user in the system user database. If you ever need to factory
reset and restore from backup, an existing admin user in the
config can interact with the default admin account in unexpected
ways. Disabling it avoids that edge case.
Restrict Management Access#
By default, RouterOS listens on all interfaces for WinBox, SSH,
API, and web access. Restrict these to your management VLAN or
a specific trusted IP range.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
# Create a management address list
/ip firewall address-list
add list=mgmt_trusted address=10.0.20.0/24 comment="LAN mgmt subnet"
add list=mgmt_trusted address=10.0.30.0/24 comment="VPN pool"
# Set allowed interface lists for all services
/ip service set winbox address=10.0.20.0/24
/ip service set ssh address=10.0.20.0/24
/ip service set www address=10.0.20.0/24
/ip service set www-ssl address=10.0.20.0/24
/ip service set api address=none
/ip service set api-ssl address=none
/ip service set telnet address=none
/ip service set ftp address=none
# Enable strong SSH crypto
/ip ssh set strong-crypto=yes forwarding-enabled=no
# Disable MAC-telnet, MAC-WinBox, and neighbor discovery
/tool mac-server set allowed-interface-list=none
/tool mac-server mac-winbox set allowed-interface-list=none
/tool mac-server ping set enabled=no
/ip neighbor discovery-settings set discover-interface-list=none
# Disable bandwidth server, proxy, socks, UPnP
/tool bandwidth-server set enabled=no
/ip proxy set enabled=no
/ip socks set enabled=no
/ip upnp set enabled=no
# Disable MikroTik cloud (DDNS and remote access)
/ip cloud set ddns-enabled=no update-time=no
|
Update Firmware#
RouterOS releases frequently patch security vulnerabilities.
Pin a stable release channel and check for updates monthly:
1
2
3
4
5
6
7
8
9
|
# Set update channel to stable (not release-candidate)
/system package update set channel=stable
# Check for updates
/system package update check-for-updates
# Install and reboot
/system package update install
/system reboot
|
Make this a scheduled task:
1
2
3
4
|
/system scheduler
add name=check-updates interval=7d start-time=03:00 \
on-event="/system package update check-for-updates" \
comment="Weekly update check"
|
2. Firewall Architecture#
RouterOS 7’s firewall is stateful with connection tracking.
The classic three-chain architecture — input, forward, output —
handles every packet path. Good rule ordering is critical
because RouterOS evaluates rules top-down and stops on the first
match (for filter rules with action=accept or action=drop).
The Default Drop Pattern#
A production firewall starts with a single default-drop rule at
the bottom of each chain, then opens specific holes above it.
1
2
3
4
5
|
# Set default policies
/ip firewall filter
set [find where chain=input] action=drop
set [find where chain=forward] action=drop
set [find where chain=output] action=accept
|
Then build rules above the default drop. The order matters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/ip firewall filter
# Layer 1: Connection state — accept established/related first
add chain=input connection-state=established,related action=accept \
comment="Accept established/related input"
add chain=forward connection-state=established,related action=accept \
comment="Accept established/related forward"
# Layer 2: ICMP — rate-limited ping, accept everywhere
add chain=input protocol=icmp action=accept \
comment="Allow ICMP input"
add chain=forward protocol=icmp action=accept \
comment="Allow ICMP forward"
# Layer 3: Management access — restricted by address list
add chain=input protocol=tcp dst-port=22 src-address-list=mgmt_trusted \
action=accept comment="SSH from mgmt subnets"
add chain=input protocol=tcp dst-port=8291 src-address-list=mgmt_trusted \
action=accept comment="WinBox from mgmt subnets"
add chain=input protocol=tcp dst-port=80,443 \
src-address-list=mgmt_trusted action=accept \
comment="WebFig from mgmt subnets"
# Layer 4: Forwarded traffic — permit inter-VLAN routing
add chain=forward in-interface=bridge action=accept \
comment="Allow all bridge forwarding"
# Layer 5: Drop invalid — catch packets outside connection state
add chain=input connection-state=invalid action=drop \
comment="Drop invalid input"
add chain=forward connection-state=invalid action=drop \
comment="Drop invalid forward"
# Layer 6: Default drop is already set as chain default
|
Connection Tracking Limits#
RouterOS 7 defaults to 655k connection tracking entries. For
homelabs with many clients and P2P traffic, that can fill up.
Monitor and tune:
1
2
3
4
5
6
7
8
9
|
# View current tracking stats
/ip firewall connection tracking print
# Show connection count
/ip firewall connection print count-only
# Tune limits
/ip firewall connection tracking
set tcp-syncookie=yes max-entries=262144
|
Set a syslog warning when connections exceed 80%:
1
2
3
4
5
6
|
/system logging action
add name=conn_warn syslog-params=remote=10.0.20.50:514 \
syslog-params-facility=local0
/system logging
add topics=firewall action=conn_warn
|
FastTrack and Connection Tracking Exception#
FastTrack bypasses connection tracking for established UDP and
TCP connections, dramatically improving throughput. On a CCR
or RB5009, FastTrack can process 5-10 Gbps without breaking a
sweat. But it has a critical limitation: FastTrack connections
are invisible to the firewall, so NAT rules, address list
matching, and layer-7 inspection do not apply.
Place FastTrack rules before your general forward rules:
1
2
3
4
5
6
7
8
9
|
/ip firewall filter
# Must come before other forward rules
add chain=forward action=fasttrack-connection \
connection-state=established,related \
comment="FastTrack established connections"
add chain=forward action=accept \
connection-state=established,related \
comment="Accept established/related (non-fast-tracked)"
|
When to skip FastTrack:
- You use
queue tree or simple queues for bandwidth shaping
- You need per-connection logging or accounting
- You apply layer-7 protocol matching on forwarded traffic
- You use transparent proxy features
In those cases, leave FastTrack disabled and rely on connection
tracking. The throughput difference at <500 Mbps is negligible.
3. Bridge VLAN Filtering#
RouterOS 7’s bridge VLAN filtering is the recommended way to
segment your network. It works at the bridge level rather than
with switch chip ACLs, giving consistent behavior across all
hardware (x86, ARM, MIPS).
VLAN Layout#
Design your VLANs around security zones:
| VLAN |
Network |
Purpose |
| 10 |
10.0.10.0/24 |
Management (router/L2) |
| 20 |
10.0.20.0/24 |
Homelab servers |
| 30 |
10.0.30.0/24 |
IoT / untrusted devices |
| 40 |
10.0.40.0/24 |
Guest WiFi (internet only) |
| 50 |
10.0.50.0/24 |
Voice / SIP |
| 99 |
10.0.99.0/24 |
Native/untrusted uplink |
Bridge VLAN Configuration#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
# Create the bridge with VLAN filtering
/interface bridge
add name=bridge1 protocol-mode=rstp vlan-filtering=yes \
igmp-snooping=yes fast-forward=yes
# Add VLAN interfaces (one per VLAN, parent=bridge1)
/interface vlan
add name=vlan10 vlan-id=10 interface=bridge1
add name=vlan20 vlan-id=20 interface=bridge1
add name=vlan30 vlan-id=30 interface=bridge1
add name=vlan40 vlan-id=40 interface=bridge1
add name=vlan50 vlan-id=50 interface=bridge1
# Add physical ports to the bridge with PVID
/interface bridge port
add bridge=bridge1 interface=ether1 pvid=99 comment="WAN uplink"
add bridge=bridge1 interface=ether2 pvid=20 comment="Homelab server"
add bridge=bridge1 interface=ether3 pvid=30 comment="IoT devices"
add bridge=bridge1 interface=ether4 pvid=40 comment="Guest WiFi AP"
# Configure trunk port for APs or switches
add bridge=bridge1 interface=ether5 pvid=20 \
frame-types=admit-only-vlan-tagged comment="Trunk to AP"
# Define allowed VLANs on the bridge
/interface bridge vlan
add bridge=bridge1 tagged=bridge1,ether5 vlan-ids=10,20,30,40,50
add bridge=bridge1 tagged=bridge1 untagged=ether2 vlan-ids=20
add bridge=bridge1 tagged=bridge1 untagged=ether3 vlan-ids=30
add bridge=bridge1 tagged=bridge1 untagged=ether4 vlan-ids=40
|
Inter-VLAN Routing Rules#
If you need selective inter-VLAN routing, the cleanest approach
is an address list filter on the forward chain. Block all
inter-VLAN traffic by default, then open specific paths:
1
2
3
4
5
6
7
8
9
10
11
|
# Block inter-VLAN by default (before the general accept rule)
/ip firewall filter
add chain=forward in-interface=vlan30 out-interface=!bridge1 \
action=drop comment="Block IoT -> other VLANs"
add chain=forward in-interface=vlan40 out-interface=!bridge1 \
action=drop comment="Block Guest -> other VLANs"
# Allow IoT -> homelab for specific services (e.g., MQTT)
add chain=forward in-interface=vlan30 out-interface=vlan20 \
protocol=tcp dst-port=1883 action=accept \
comment="Allow IoT MQTT to homelab"
|
4. DNS and Caching#
RouterOS 7 supports DNS over HTTPS (DoH) natively, which
encrypts your DNS queries and prevents ISP-level snooping or
manipulation. Combined with the local DNS cache and optional
ad-filtering via address lists, you can replace Pi-hole for
basic network-wide blocking.
DNS over HTTPS Setup#
1
2
3
4
5
6
7
|
# Set upstream DoH servers
/ip dns set servers=1.1.1.1,8.8.8.8 \
use-doh-server=https://cloudflare-dns.com/dns-query \
verify-doh-cert=yes \
allow-remote-requests=yes \
cache-size=4096KiB \
max-udp-packet-size=4096
|
Server choices:
https://cloudflare-dns.com/dns-query — Cloudflare (low
latency, ECS support)
https://dns.quad9.net/dns-query — Quad9 (threat blocking)
https://dns.google/dns-query — Google (high reliability)
Note: The router MUST have a valid system clock for TLS
certificate verification. Ensure NTP is configured:
1
2
|
/system ntp client set enabled=yes server=ntp.pool.org
/system ntp client print
|
Ad-Blocking via Address Lists#
RouterOS can block DNS queries for known ad/malware domains by
maintaining an address list and a firewall rule that drops
traffic to those destinations. This is lighter than running
Pi-hole:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
# Script to update adlist (run via scheduler)
/system script
add name=update-adlist source={
:local url "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
:local file "/disk1/adlist.txt"
:local result [/tool fetch url=$url mode=https as-value output=file dst-path=$file]
/ip firewall address-list remove [find list=adblock]
:foreach line in=[/file get $file contents] do={
:if ([:find $line "0.0.0.0"] = 0) do={
:local domain [:pick $line 8 [:find $line " " 8]]
:if ($domain != "") do={
/ip firewall address-list add list=adblock address=$domain
}
}
}
:put "Adlist updated: $[:len [/ip firewall address-list find list=adblock]] entries"
}
# Firewall rule to drop traffic to adblock targets
/ip firewall filter
add chain=forward dst-address-list=adblock action=drop \
comment="Drop ad/malware destinations"
# Run every 12 hours
/system scheduler
add name=adlist-update interval=12h start-time=04:00 \
on-event="/system script run update-adlist"
|
Trade-off compared to Pi-hole: The RouterOS adlist approach
blocks at the IP level after DNS resolution, not at the DNS
query level. It’s more resource-efficient but cannot do
regex-based domain matching. For most homelabs, it handles the
top 99% of ad domains with zero extra containers.
5. Container Management#
RouterOS 7 on ARM64 and x86 hardware supports running Linux
containers directly on the router. This is useful for lightweight
services like a Tailscale exit node, Cloudflare Tunnel connector,
or simple HTTP health checkers — but it comes with resource and
security constraints.
Container Setup#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# Enable container mode and create a mount
/container config set ram-high=256M ram-low=128M
/disk/file-system add slot=usb1 type=ext4 label=containers
# Create mount point for persistent storage
/disk/directory add name=containers
/disk/mount-point add directory=containers slot=usb1
# Pull and run an image (example: cloudflared)
/container
add remote-image=cloudflare/cloudflared:latest \
envlist=cloudflare_env \
mount=[{"src=/containers/cloudflared" "dst=/home/nonroot"}] \
interface=vlan20 \
root-dir=/containers/cloudflared/root \
logging=yes
# Set environment variables
/container env
add name=cloudflare_env key=TUNNEL_TOKEN value="your-token-here"
|
Container Best Practices#
1
2
3
4
5
6
7
8
9
10
|
# Limit CPU and memory per container
/container set cloudflared cpu-limit=20% memory-limit=64M
# Isolate with a dedicated VLAN interface — don't bridge
# containers directly to the management VLAN
/interface vlan add name=container_vlan vlan-id=99 interface=bridge1
# Use container_vlan for all containers
# Monitor resource usage
/container/print stats detail
|
When to use containers on the router (vs. on a server):
| Good for router |
Better on a server |
| Tailscale/Headscale |
CPU-heavy apps |
| Cloudflare Tunnel |
Databases |
| Simple health checks |
Media transcoding |
| Net-data light monitoring |
Git servers |
The router has limited RAM (typically 512MB-2GB) and a modest
CPU. Running anything more than 2-3 lightweight containers will
impact routing performance.
These settings extract maximum throughput from RouterOS 7 on
homelab hardware.
Ethernet and Interface Settings#
1
2
3
4
5
6
7
8
9
10
11
|
# Disable auto-negotiation on SFP+ and set fixed rate
/interface ethernet
set sfp-sfpplus1 advertise=10G-full-duplex \
comment="Disable autoneg, lock to 10G"
# Enable flow control on high-throughput links
set sfp-sfpplus2 flow-control=on
# Disable interfaces you're not using
/interface print where running=no
# Then: set [find where name~"ether[5-9]"] disabled=yes
|
Queuing and FastTrack#
The default queue type on RouterOS 7 is only-pending for
egress, which can cause bufferbloat. Switch to a CoDel-based
queue for latency-sensitive traffic:
1
2
3
4
5
6
7
8
9
|
# Apply fq_codel on WAN interface for bufferbloat control
/queue type
add name=fq-codel kind=fq-codel
/queue simple
add name=wan-shaping target=10.0.99.0/24 \
queue=fq-codel/fq-codel \
max-limit=950M/950M \
comment="Shaped WAN with fq_codel"
|
Important: queue simple and queue tree are mutually
exclusive with FastTrack. If you use per-connection queuing,
remove the FastTrack rule:
1
2
3
4
|
# Find and disable the FastTrack rule
/ip firewall filter
print where action=fasttrack-connection
# Then disable or remove it
|
SFP+ DAC Cable Compatibility#
SFP+ DAC cables (passive twinax) sometimes fail to link on
MikroTik unless the port is configured correctly:
1
2
3
4
5
6
|
# Common fix: set the SFP+ interface to advertise only
# supported rates and disable auto-negotiation fallback
/interface ethernet
set sfp-sfpplus1 advertise=10G-full-duplex \
sfp-rate-select=high \
comment="10G DAC cable"
|
Disable Unnecessary Hardware Features#
1
2
3
4
5
6
|
# Disable IPv6 if not using it (saves CPU cycles)
/ipv6 settings set disable-ipv6=yes
# Disable MPLS and routing filter if not needed
/routing mpls interface print
# If no interfaces listed, keep it disabled
|
7. Backup Automation#
A lost MikroTik config is painful to rebuild. Automate backups
to an external location.
Export to an NFS or SMB Share#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# Backup to a mounted SMB share
/system script
add name=backup-router source={
:local hostname [/system identity get name]
:local date [/system clock get date]
:local filename ("$hostname-$date")
# Export config
/export terse file=$filename
# Create password-protected backup
/system backup save name="$filename.backup" password="your-backup-pw"
# Upload to SMB share (mount first: /disk/mount-point add ...)
:local smbPath "/mnt/smb/backups/"
/file print where name="$filename.backup"
/file print where name="$filename.rsc"
:put "Backup saved: $filename"
}
# Run daily at 02:00
/system scheduler
add name=daily-backup interval=1d start-time=02:00 \
on-event="/system script run backup-router"
|
Cloud Upload via Fetch#
If you don’t have an SMB/NFS share, push backups to a web server
or object storage:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/system script
add name=backup-upload source={
:local hostname [/system identity get name]
:local date [/system clock get date]
:local filename ("$hostname-backup-$date")
/export terse file="$filename"
/system backup save name="$filename"
# Upload to a web server via curl-compatible fetch
:local uploadUrl "https://backup.yourlab.com/upload"
:local result [/tool fetch url="$uploadUrl" \
http-method=post \
http-data-template=("file={\"$filename\"}") \
src-path="$filename.backup" as-value output=user]
}
# Include router identity in the backup name for multi-router
# environments
/system identity set name=CCR2004-Homelab
|
8. Monitoring and Logging#
Remote Syslog#
Send all firewall and system logs to your homelab logging stack
(Loki, Grafana, or a simple syslog server):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/system logging action
add name=remote_syslog \
syslog-params=remote=10.0.20.50:514 \
syslog-params-facility=local0
# Send firewall drops to remote
/system logging
add topics=firewall,!info action=remote_syslog
# Send critical system events
add topics=critical action=remote_syslog
# Keep local buffer reasonable (default is large)
/system logging action
set memory memory-lines=1000
|
SNMP for Grafana#
1
2
3
4
5
6
|
# Enable SNMP with read-only community (change the community!)
/snmp community
add name=homelab-mon address=10.0.20.0/24 read-access=yes
/snmp
set enabled=yes contact="[email protected]" location="Homelab Rack"
|
Pair with a Grafana dashboard using
the official MikroTik SNMP
MIBs for beautiful interface
traffic graphs and system health.
Interface Traffic Graphs#
RouterOS 7 can generate live traffic graphs in WebFig/WinBox.
Enable them with:
1
2
3
4
5
6
7
8
|
/interface monitor-traffic
add name=traffic-overview interface=ether1,ether2 \
allow-address=10.0.20.0/24
# Or via API/Grafana: poll /interface/print and
# /interface/monitor-traffic via REST
# Enable REST API
/ip service set www-ssl address=10.0.20.0/24
|
9. Upgrade Strategy#
RouterOS stable releases come every 4-8 weeks. A conservative
upgrade strategy prevents breaking changes from hitting your
production network:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# Wait 2-4 weeks after a new stable release, read the changelog
# for deprecation warnings, then upgrade from a maintenance window
# Before upgrading, export current config
/export file=pre-upgrade-config-$(date +%F)
# Upgrade
/system package update install
# Post-upgrade checks
/ip firewall filter print count-only
/interface print count-only
/ip route print count-only
/system resource print
# If something broke, roll back:
# 1. Downgrade via Netinstall
# 2. Restore config from backup:
/system backup load name=pre-upgrade-2025-06-01.backup
|
Keep spare hardware. A $50 hAP lite as a cold spare can save
your weekend when an upgrade bricks a primary router. With a
backup export, you can have a replacement online in 10 minutes.
10. Quick Audit Checklist#
Run this script periodically to verify your security posture:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# One-liner audit of key security settings
:put "=== RouterOS 7 Security Audit ==="
:put "Default admin disabled: $[/user get [find where name=admin] disabled]"
:put "SSH strong crypto: $[/ip ssh get strong-crypto]"
:put "Neighbor discovery: $[/ip neighbor discovery-settings get discover-interface-list]"
:put "Bandwidth server: $[/tool bandwidth-server get enabled]"
:put "UPnP: $[/ip upnp get enabled]"
:put "MAC WinBox: $[/tool mac-server mac-winbox get allowed-interface-list]"
:put "Socks: $[/ip socks get enabled]"
:put "Proxy: $[/ip proxy get enabled]"
:put "RouterOS version: $[/system package update get installed-version]"
:put "Uptime: $[/system resource get uptime]"
:put "CPU load: $[/system resource get cpu-load]%"
:put "Free RAM: $[/system resource get free-memory]"
:put "==================================="
|
Save it as a boot-on-failure event:
1
2
3
4
|
/system script add name=audit source={...}
/system scheduler
add name=audit-run interval=7d start-time=06:00 \
on-event="/system script run audit"
|
Summary#
RouterOS 7 is a remarkable platform for homelab and small-biz
networking, but its flexibility demands disciplined configuration.
These best practices cover the critical bases:
- Hardening — Change the admin user, restrict management
access, disable unused services, enable SSH strong crypto,
update RouterOS regularly.
- Firewall — Use the default-drop pattern with proper rule
ordering: stateful tracking first, then ICMP, then management
access, then forwarding. Place FastTrack rules before general
accept rules.
- VLAN segmentation — Bridge VLAN filtering with
vlan-filtering=yes
and explicit tagged/untagged port configuration. Block
inter-VLAN traffic by default, open specific paths.
- DNS — DoH via Cloudflare or Quad9 with local caching.
Optional DNS-based ad-blocking using address lists.
- Containers — Lightweight services only, with CPU/RAM limits
and dedicated VLAN isolation.
- Performance — FastTrack for throughput, fq_codel for
latency control, proper SFP+ configuration, disable unused
features.
- Backup — Daily automated exports with remote upload.
Test restores quarterly.
Apply these configurations incrementally. Change one section,
test it for a few days, then move to the next. RouterOS does not
abstract complexity away — it rewards those who understand every
rule they write.