NetPilot
Back to Blog
Tutorial••Updated •10 min

MTCNA Practice Lab: RouterOS Exercises Without Hardware

A free MTCNA practice lab on RouterOS CHR: WAN DHCP, a LAN bridge, NAT, firewall rules, port forwarding, simple queues and PPPoE, with real output and a map to the training outline.

S
Sarah Chen
Network Engineer

An MTCNA practice lab needs a router to configure, something to route for, and a way to prove each step worked. RouterOS CHR gives you all three without RouterBOARD hardware. This lab builds a small branch network from five nodes, and it covers the parts of the outline most people want to repeat until they are routine: WAN DHCP, a LAN bridge, NAT, firewall rules, port forwarding, simple queues and PPPoE.

All output below comes from a real run on RouterOS 7.24.5. The topology is in our public mikrotik-labs repository.

MTCNA exam facts

From MikroTik's training page:

  • Test: 25 single or multiple choice questions, 60 minutes, pass score 60%
  • Training: a training session has to take place before the certification test
  • Validity: a MikroTik certificate is valid for 3 years from the date of issue

So this lab is practice around the course, never a way around it. The MTCNA outline lists nine modules and asks for a good understanding of TCP/IP and subnetting.

What this lab covers

Outline moduleCovered hereTested in this lab
1 Introduction✅ MostDHCP client, masquerade, users, services, backup and export
2 DHCP✅ YesServer, client, leases, ARP table
3 Bridging⚠️ Wired onlyBridge and ports
4 Routing✅ YesDefault route, static route
5 Wireless❌ NoCHR has no radios
6 Firewall⚠️ MostInput, forward, src-nat, dst-nat
7 QoS⚠️ PartSimple queue, not PCQ
8 Tunnels⚠️ PartPPPoE, pools and profiles, not PPTP or SSTP
9 Misc⚠️ PartPing, traceroute, Torch, logs

Bottom line: CHR can run most of the outline, and radios and RouterBOARD hardware are the gaps. For a hosted version with nothing to install, NetPilot preloads RouterOS CHR and an AI agent builds this kind of lab from a prompt, then you practice on the real CLI.

The lab

pc1 ─┐
     ├─ lan bridge ─ gw ─ ether2 ─ isp ─ ether3 ─ web
pc2 ─┘   192.168.88.0/24     198.51.100.0/24   203.0.113.0/24

gw is the router you practice on. isp hands it a WAN address by DHCP. web runs nginx and iperf3 and stands in for the internet.

Build it with the agent

"Build an MTCNA practice lab: a MikroTik CHR gateway with a DHCP WAN from a CHR ISP router, a LAN bridge with a DHCP server and two Linux PCs, and a Linux web server behind the ISP. Leave NAT and the firewall for me to configure."

The agent designs the topology, writes the RouterOS configs, deploys, and tells you what it checked. Direct CLI is always available too, and for exam practice that is the point: open a terminal on gw and type every command below by hand.

Or run it yourself

On a Linux host with containerlab v0.82.0 or newer:

git clone https://github.com/netpilot-labs/mikrotik-labs
cd mikrotik-labs/02-mtcna-practice
sudo containerlab deploy -t mtcna-practice.clab.yml

The startup config gw.rsc already applies exercises 1 to 4, so you can read along and check the output. To type them yourself, delete those lines from gw.rsc before you deploy. Exercises 5 to 8 start from a clean slate either way. Log in with admin and the password admin.

Exercise 1: WAN DHCP client

/ip dhcp-client add interface=ether2 add-default-route=yes use-peer-dns=no
[admin@gw] > /ip dhcp-client print
Flags: X - DISABLED
Columns: NAME, INTERFACE, USE-PEER-DNS, ADD-DEFAULT-ROUTE, STATUS, ADDRESS
#   NAME     INTERFACE  USE-PEER-DNS  ADD  STATUS   ADDRESS
0 X client1  ether1     yes           yes  stopped
1   client2  ether2     no            yes  bound    198.51.100.20/24

client1 on ether1 is disabled by the lab's management setup. The DAd flag marks a dynamic, active route that came from DHCP:

[admin@gw] > /ip route print where routing-table=main
Flags: D - DYNAMIC; A - ACTIVE; c - CONNECT, d - DHCP
Columns: DST-ADDRESS, GATEWAY, ROUTING-TABLE, DISTANCE
    DST-ADDRESS      GATEWAY       ROUTING-TABLE  DISTANCE
DAd 0.0.0.0/0        198.51.100.1  main                  1
DAc 172.20.20.0/24   ether1        main                  0
DAc 192.168.88.0/24  lan           main                  0
DAc 198.51.100.0/24  ether2        main                  0

Exercise 2: LAN bridge and DHCP server

/interface bridge add name=lan
/interface bridge port add bridge=lan interface=ether3
/interface bridge port add bridge=lan interface=ether4
/ip address add address=192.168.88.1/24 interface=lan
/ip pool add name=lan-pool ranges=192.168.88.100-192.168.88.150
/ip dhcp-server add name=lan-dhcp interface=lan address-pool=lan-pool lease-time=1h
/ip dhcp-server network add address=192.168.88.0/24 gateway=192.168.88.1 dns-server=192.168.88.1

Ask for a lease from a PC, then give it a route to the far side. The route is needed because each lab host keeps its management default route:

docker exec clab-mtcna-practice-pc1 udhcpc -i eth1 -n -q
docker exec clab-mtcna-practice-pc1 ip route add 203.0.113.0/24 via 192.168.88.1

Do the same on pc2, then read the leases and the ARP table. Addresses are handed out from the top of the pool, and which PC gets which depends on who asks first:

[admin@gw] > /ip dhcp-server lease print
Flags: D - DYNAMIC
Columns: ADDRESS, MAC-ADDRESS, SERVER, STATUS, LAST-SEEN
#   ADDRESS         MAC-ADDRESS        SERVER    STATUS  LAST-SEEN
0 D 192.168.88.150  AA:C1:AB:47:1D:E5  lan-dhcp  bound   18s
1 D 192.168.88.149  AA:C1:AB:99:FA:2E  lan-dhcp  bound   17s

Exercise 3: Masquerade and a static route

/ip firewall nat add chain=srcnat out-interface=ether2 action=masquerade comment="LAN to WAN"

Now test what NAT does for you. Disable the rule and pc1 loses the far side, because isp has no route back to 192.168.88.0/24:

/ip firewall nat disable [find comment="LAN to WAN"]
$ docker exec clab-mtcna-practice-pc1 ping -c2 -W1 203.0.113.10
2 packets transmitted, 0 received, 100% packet loss, time 1026ms

Add the missing route on isp and the ping works with no NAT at all:

/ip route add dst-address=192.168.88.0/24 gateway=198.51.100.20
$ docker exec clab-mtcna-practice-pc1 ping -c2 -W1 203.0.113.10
2 packets transmitted, 2 received, 0% packet loss, time 1041ms

Remove that route and enable the NAT rule again before you go on. Use the WAN address your gw got if it is not .20.

Exercise 4: Firewall filter

Rules run top to bottom, and the first match decides. The input chain protects the router and the forward chain protects what is behind it:

/ip firewall filter add chain=input connection-state=established,related action=accept comment="input: return traffic"
/ip firewall filter add chain=input connection-state=invalid action=drop comment="input: drop invalid"
/ip firewall filter add chain=input protocol=icmp action=accept comment="input: ping"
/ip firewall filter add chain=input in-interface=lan action=accept comment="input: from LAN"
/ip firewall filter add chain=input in-interface=ether2 action=drop comment="input: drop from WAN"
/ip firewall filter add chain=forward connection-state=established,related action=accept comment="forward: return traffic"
/ip firewall filter add chain=forward connection-state=invalid action=drop comment="forward: drop invalid"
/ip firewall filter add chain=forward in-interface=lan out-interface=ether2 action=accept comment="forward: LAN to WAN"
/ip firewall filter add chain=forward connection-nat-state=dstnat action=accept comment="forward: port forwards"
/ip firewall filter add chain=forward action=drop comment="forward: drop everything else"

Prove it from both sides. The router's web page answers from the LAN and times out from the WAN:

$ docker exec clab-mtcna-practice-pc1 curl -s -m4 -o /dev/null -w 'webfig from lan %{http_code}\n' http://192.168.88.1/
webfig from lan 200
$ docker exec clab-mtcna-practice-web curl -s -m4 -o /dev/null -w 'webfig from wan %{http_code}\n' http://198.51.100.20/
webfig from wan 000

The counters tell you which rule did the work:

[admin@gw] > /ip firewall filter print stats
Columns: CHAIN, ACTION, BYTES, PACKETS
# CHAIN    ACTION      BYTES  PACKETS
;;; input: return traffic
0 input    accept        584        9
;;; input: drop invalid
1 input    drop            0        0
;;; input: ping
2 input    accept        140        2
;;; input: from LAN
3 input    accept      1 372        5
;;; input: drop from WAN
4 input    drop        1 628       10
;;; forward: return traffic
5 forward  accept  3 226 784    2 215
;;; forward: drop invalid
6 forward  drop            0        0
;;; forward: LAN to WAN
7 forward  accept        624       10
;;; forward: port forwards
8 forward  accept         60        1
;;; forward: drop everything else
9 forward  drop            0        0

Exercise 5: Port forwarding

Publish the nginx server on pc1 through the WAN address. Use the address your pc1 leased:

/ip firewall nat add chain=dstnat in-interface=ether2 protocol=tcp dst-port=8080 action=dst-nat to-addresses=192.168.88.150 to-ports=80 comment="web on pc1"
$ docker exec clab-mtcna-practice-web curl -s -m5 -o /dev/null -w 'wan to pc1 http %{http_code}\n' http://198.51.100.20:8080/
wan to pc1 http 200

Exercise 6: Simple queue

Start iperf3 on web with docker exec clab-mtcna-practice-web iperf3 -s -D, then limit one PC. Without a queue, pc1 read about 1.3 Mbit/s, which is the CHR free license at work. With a 256k queue on the other PC, the same test drops to the limit:

/queue simple add name=pc2-limit target=192.168.88.149/32 max-limit=256k/256k
$ docker exec clab-mtcna-practice-pc2 iperf3 -c 203.0.113.10 -t 5 -R
[  5]   0.00-5.00   sec   448 KBytes   734 Kbits/sec    0             sender
[  5]   0.00-5.00   sec   160 KBytes   262 Kbits/sec                  receiver

The queue's own counters show the rate and the drops:

[admin@gw] > /queue simple print stats
0  name="pc2-limit" target=192.168.88.149/32 rate=12.1kbps/255.5kbps
   total-rate=0bps packet-rate=22/21 total-packet-rate=0 queued-bytes=0/0
   total-queued-bytes=0 queued-packets=0/0 total-queued-packets=0
   bytes=547239/483079 total-bytes=0 packets=701/570 total-packets=0
   dropped=19/43 total-dropped=0

Exercise 7: PPPoE, pools and profiles

On isp, build the server side:

/ip pool add name=ppp-pool ranges=100.64.0.10-100.64.0.20
/ppp profile add name=ppp1 local-address=100.64.0.1 remote-address=ppp-pool rate-limit=512k/512k
/ppp secret add name=gw1 password=lab123 service=pppoe profile=ppp1
/interface pppoe-server server add service-name=isp interface=ether2 disabled=no default-profile=ppp1

On gw, dial it:

/interface pppoe-client add name=pppoe-wan interface=ether2 user=gw1 password=lab123 add-default-route=no disabled=no
[admin@isp] > /ppp active print
Columns: NAME, SERVICE, CALLER-ID, ADDRESS, UPTIME
# NAME  SERVICE  CALLER-ID          ADDRESS      UPTIME
0 gw1   pppoe    52:54:00:F6:E4:01  100.64.0.20  11s

Exercise 8: Tools, backup and users

Torch shows live traffic on an interface while pc1 pings:

[admin@gw] > /tool torch interface=lan duration=4s src-address=0.0.0.0/0 ip-protocol=any
Columns: MAC-PROTOCOL, IP-PROTOCOL, DSCP, SRC-ADDRESS, DST-ADDRESS, TX, RX,
         TX-PACKETS, RX-PACKETS
MA  IP-PROTOCOL  DSCP  SRC-ADDRESS     DST-ADDRESS   TX      RX      T  R
ip  icmp            0  192.168.88.150  203.0.113.10  784bps  784bps  1  1

Traceroute and the DHCP log finish the troubleshooting set:

[admin@gw] > /tool traceroute 203.0.113.10 count=1
Columns: ADDRESS, LOSS, SENT, LAST, AVG, BEST, WORST, STD-DEV
#  ADDRESS       LOSS  SENT  LAST   AVG  BEST  WORST  STD-DEV
0  198.51.100.1  0%       1  0.3ms  0.3  0.3   0.3          0
1  203.0.113.10  0%       1  0.2ms  0.2  0.2   0.2          0

Learn the difference between a backup and an export. A backup is a binary file for the same router, and an export is a readable script you can edit:

/system backup save name=before-change dont-encrypt=yes
/export hide-sensitive file=gw-export
/user add name=student group=read password=lab123

What needs real hardware

CHR is a virtual router, so hardware topics are out of its reach. There are no radios, so module 5 needs a real device or the concepts alone, and the RouterBOARD menu is not there:

[admin@gw] > /system routerboard print
bad command name routerboard (line 1 column 9)

Netinstall, RouterBOOT upgrades and the reset button also belong to hardware. MikroTik's training schedule says sessions are practical and use real MikroTik equipment, so you will get that time in class. This lab did not test PPTP, SSTP, FastTrack, address lists or PCQ, so take those as your own next exercises.

FAQ

Can I practice for the MTCNA without MikroTik hardware?

Yes, for most of the outline. RouterOS CHR runs the same RouterOS CLI as a router, and this lab covers DHCP, bridging, static routes, firewall filter, NAT, simple queues, PPPoE and the diagnostic tools. CHR has no radios, so the wireless module needs real hardware.

How many questions are on the MTCNA exam?

The MTCNA test has 25 single or multiple choice questions and a 60 minute limit, and the pass score is 60 percent. MikroTik states that a training session has to take place before the certification test, so practice labs add to the course and do not replace it.

Do I need to attend training to take the MTCNA?

Yes. MikroTik says a training session has to take place prior to the certification test. Training is run by independent MikroTik Training Centers. A MikroTik certificate is valid for 3 years from the date of issue.

Which MTCNA topics can CHR not cover?

Wireless is the main gap, because CHR has no radios and answers bad command name on the wireless menus. RouterBOARD topics such as RouterBOOT firmware and Netinstall also need hardware. This lab did not test PPTP, SSTP, FastTrack or PCQ, so those remain exercises for you.

Keep practicing

Try the dual WAN PCC lab next, or go back to the CHR in containerlab tutorial for the setup details. The MikroTik lab page has the hosted route, and app.netpilot.io will build a variation of this lab from a sentence.

MikroTik, RouterOS and MTCNA are trademarks of their owner. NetPilot is not affiliated with MikroTik, and this lab is not official MikroTik training material.

Try NetPilot Free

Build enterprise-grade network labs in seconds with AI assistance

Get Started Free