I find where any packet dies

I know the RouterOS packet-flow engine the way you know your own street: the RAW table, connection tracking, mangle, filter and NAT, in the exact order a packet meets them. I do not love packet-flow debugging; it is slow, finicky work. But bring me a packet that will not arrive, on any network of any size, and I will find where it stops. That one I guarantee.

Verified at the source — MikroTik’s own exams, each score confirmable on mikrotik.com.

The order I filter by

How I think before I write a single rule. A firewall is a pipeline, and where a rule sits in it decides what the rule can see and what it costs. These are the habits that keep the flow legible.

  • 01

    Hold the whole flow in your head

    Before I place a rule I know exactly where in the packet flow it will sit — what the packet has already been through, what it has become, and what still lies ahead of it. The most common firewall fault I am called in to fix is a rule in the wrong chain: correct in isolation, useless where it was put, because the ordering was never internalised. Get the map right and half the bugs never happen.

  • 02

    Accept what’s known, drop what’s broken, deny the rest

    The first rules a packet meets accept the connections already tracked as established or related, and drop the ones connection tracking marks invalid; everything not explicitly allowed falls through to a default deny. State does the heavy lifting up front, so the rule list stays short and the router stays fast.

  • 03

    Drop it where it’s cheapest

    A rule’s leverage is its position. A flood dropped in the filter chain has already cost a connection-tracking entry, CPU and table space by the time it dies; the same flood dropped in the RAW table, before tracking ever runs, sheds for almost nothing. I match as early as the job allows — the cheapest certain point, not the first place a rule fits.

  • 04

    Identify traffic by where it is, not by guesswork

    When I have to single out traffic — to steer it, mark it, or let it past a default drop — I match on where it actually is in the flow: the interface-list it arrived on, the IPsec policy that decrypted it, the connection it belongs to. A guess-by-address rule ages badly; a match anchored to the packet’s real position holds.

What I run in production

The firewall stack I run live on RouterOS: the stateful filtering, the NAT, the pre-tracking RAW drops and the address-list defence that decide what moves and what does not. Everything below except the NAT helpers runs in production at the depth I can teach, and on mangle marking the deployment runs a notch past the book.

Command by area

1 Learning · 2 Aware · 3 Confident · 4 Fluent · 5 Teach

  • deployed leaf
  • deployed ahead of the textbook
Packet Flow (2)
  • Routing vs Bridging PathsTeach
  • Connection ScenariosTeach
Connection Tracking (1)
  • Connection StatesTeach
Firewall Filter (6)
  • Chains & ActionsTeach
  • Address ListsTeach
  • ICMP FilteringTeach
  • Advanced Filter OptionsTeach
  • Default Config & Management AccessTeach
  • Critical-Service Attack DetectionTeach
NAT (4)
  • Source NAT & MasqueradeTeach
  • Destination NAT & RedirectTeach
  • Hairpin NATTeach
  • NAT HelpersAware
FastTrack (1)
  • FastTrackTeach
Mangle (3)
  • Mangle Chains & ActionsTeach
  • Mark Connection / Packet / RoutingTeach, deployed ahead of the textbook
  • Advanced Mangle ConditionsTeach
RAW Table (1)
  • SYN-Flood MitigationTeach
Bridge Filter (router-side) (1)
  • Bridge Filter (router-side)Teach
UPnP (1)
  • UPnPTeach

Grouped by curriculum topic, deepest first. Solid indigo runs to the depth I deploy in production; the one dashed notch (mangle marks) is where deployment ran ahead of the courseware.

  • Any undelivered packet traced to exactly where it stops.

    A packet that will not arrive was dropped, mis-marked, NATed wrong or sent down the wrong table at one knowable point in the flow. Because the pipeline is deterministic and I know it end to end, finding that point is patient work, not luck — I follow the packet stage by stage until it names the rule that killed it.

  • Only the traffic you allow ever moves.

    A default-deny ruleset built on connection state: established and related accepted up front, invalid dropped, the untrusted side segmented by interface-list, and everything unasked-for falling through to a drop — so what passes is what you meant to pass, nothing incidental.

  • A flood dropped before it costs you anything.

    Hostile traffic shed in the RAW table, before connection tracking spends a single entry on it, paired with a per-source rate-limit so a SYN flood or a scan burns the attacker’s effort, not your router’s CPU or its state table.

  • Scanners and brute-forcers caught and held off.

    Port scans picked up by RouterOS’s own detection and progressive address-lists that escalate a repeat offender from a short cool-off to a long ban — the noisy edge traffic parked on a drop list before it reaches anything that matters.

  • Servers reachable from outside — safely.

    Destination-NAT and port-forwarding that expose exactly the service you intend and nothing beside it, hairpin NAT so the same name works from inside and out, and the return path checked so a forward does not quietly open more than it should.

  • A router that stays fast under load.

    Established connections handed to FastTrack so the bulk of the traffic skips the per-packet walk through the rule list entirely — the firewall does its thinking on the connection’s first packet, and the rest ride through.

What the flow taught me the hard way

Three lessons I did not get from the manual — I got them from the recovery afterwards. Every one comes back to the same thing: knowing exactly where a packet is in the flow.

  • The teardown that locked me out

    When you tear down a live ruleset, the order you disable in decides whether you lock yourself out.

    I was refactoring a firewall remotely — the old, messy ruleset on top, a new clean one built below it, ready to take over once it proved out. To retire the old block I selected its rules and disabled them in one go. The trap: that is not one atomic act. The accept rules went dead a beat before the old default-drop did, and for that instant the drop was the first rule the traffic met — including my own management session, from the far end of the internet. Since then the order is a rule I never break: when you dismantle a live firewall, kill the drop and reject rules FIRST and the accepts last, so a bare default-drop is never left sitting on top. And I never do it without Safe Mode holding the door — one dropped session and the box rolls the whole change back on its own.

    # tearing down a live filter: disable drop/reject FIRST, accept LAST — under safe-mode
  • IPsec has no interface

    In RouterOS, IPsec traffic rides the real interface it arrived on — so a road-warrior’s packets land in your WAN’s drop.

    A remote IPsec road-warrior dials in and cannot reach a thing, and the reflex is to blame the tunnel. It is not the tunnel. Unlike a tunnel interface you can name, IPsec-transported traffic has no interface of its own — after it is decrypted it surfaces on the physical interface it came in on, your untrusted WAN, which the forward chain drops by default, exactly as it should. The fix is not to open the WAN. It is to identify the decrypted traffic by its policy — match the IPsec policy and accept THAT, ahead of the WAN drop. Miss it and you either lock the road-warrior out or, worse, punch a hole in the WAN to make it work. Knowing where IPsec traffic appears in the flow is the whole difference between a safe rule and a dangerous one.

    /ip firewall filter add chain=forward ipsec-policy=in,ipsec action=accept
  • Policy routing is bi-directional

    A connection is bi-directional — so you mark the connection, not the packet, and one routing mark carries the whole flow both ways along the path you chose.

    A site-to-site job: steer selected traffic from the HQ LAN out through one specific branch’s VPN tunnel — to reach a service that only answers from that location — while everything else keeps the default route. The trap that catches juniors is thinking in one-way packets. You do not route-mark a direction; you mark the CONNECTION on its first packet, and connection tracking then ties that one mark to BOTH halves of the flow. So the routing decision is not something you re-derive for the reply — the same connection-mark drives it in both directions at once: the egress is steered into the tunnel, and the return that arrives back through the tunnel inherits the same mark and stays pinned to that path, instead of escaping out the default route and breaking the session one way. One connection-mark, both directions — obvious only once you hold the whole packet-flow diagram in your head and stop seeing a connection as a single packet. That case is what taught me marking is a precision instrument, not a sprinkle.

    /ip firewall mangle add chain=prerouting action=mark-connection passthrough=yes \ connection-mark=no-mark dst-address-type=!local \ src-address-list=pbr-steer-clients dst-address-list=via-branch-dst \ new-connection-mark=cm-via-branch add chain=prerouting action=mark-routing passthrough=yes \ connection-mark=cm-via-branch dst-address-type=!local \ src-address-list=!pbr-steer-clients routing-mark=!rt-via-branch \ new-routing-mark=rt-via-branch

Where you drop it changes what it costs

Point the same flood at two routers. One drops it in the filter chain, and by the time each packet reaches that rule it has already cost a connection-tracking entry, some CPU and a slot in the state table. The other drops it in the RAW table, before tracking runs at all, and sheds it for almost nothing. Both rules drop the same packets. The cost depends on where in the flow the rule sits.

The RouterOS forward-path packet pipeline, in order: a packet arrives, then RAW, connection tracking, mangle prerouting, destination NAT, the routing decision, mangle forward, filter forward, and source NAT, before it leaves. Where a rule sits in this order decides what it costs and what it can still see.A single left-to-right pipeline. A forwarded packet meets each checkpoint in a fixed order: RAW (the cheapest place to drop, before any tracking), connection tracking (where cost begins), mangle prerouting, destination NAT, the routing decision (a diamond — forward or local), mangle forward, filter forward (the firewall proper, still seeing the real source), and source NAT (masquerade, on the way out). A cost ledger below the row leaps the instant tracking turns on.
RAWprerouting/ip firewall raw
What it does
The earliest place you can act on a packet — before the router spends anything tracking it.
What it sees
The bare packet only. There is no connection state yet — nothing to match on but the packet itself.
The insight
Drop a flood here and it costs almost nothing — you shed it before the router opens a single tracking entry. The cheapest possible drop, and it is cheap only because of where it sits.
Cost so far
Nothing allocated yet — a drop here is essentially free.

a drop here — vs a drop at FILTER

RAW, before connection tracking — the earliest and cheapest place to drop. Nothing is tracked yet.

Want just the map, to keep or to share? The trace lives on its own here — a packet-flow diagram you can bookmark. Open the standalone diagram →

The frontier — where the flow runs past me

Where the packet flow runs deep for me and where it goes past my daily work. I name it precisely, because a firewall you half-know is worse than none.

  1. In production

    The core pipeline, run and supported in the field: packet-flow debugging, connection tracking, the filter chains and address-lists, NAT (source, destination and hairpin), RAW-table DoS mitigation and FastTrack. This is the ground I stand on for every firewall I touch.

  2. The frontier

    The NAT connection-tracking helpers — the protocol ALGs that open a return pinhole for the likes of FTP or SIP, and the security surface that opens with them. It is the one corner of an otherwise fully-run specialty I had genuinely not met when the map was drawn. I would lab it before I bill it — the same rule I hold everywhere.

Where the packet-flow command comes from

The packet flow stopped being a diagram on a page for me a long time ago. Here is where the command came from, and why I will put a guarantee on the trace.

  • The diagram I can draw blind

    Ten years of reading the RouterOS packet flow until it became reflex.

    The packet-flow diagram — the map of every chain a packet crosses and the order it crosses them — is the one drawing I can put on a whiteboard with my eyes closed. It is not a poster on a wall; it is the model I debug from and the one I teach from. Nearly every hard firewall problem I have untangled came down to the same move: knowing exactly where in that flow the packet was when something decided its fate. A decade of doing it turned the map into instinct.

  • Why I can guarantee the trace

    Every undelivered packet stops somewhere the flow can name.

    A packet that will not arrive has not vanished — it was dropped, mis-marked, translated wrong or sent down the wrong table at one specific, knowable point. Because the flow is deterministic and I know it end to end, finding that point is patience, not luck. I do not enjoy the tedium of it. But I have not yet met the network where I could not, in the end, put my finger on exactly where the packet stopped — and that is why I will stand behind it.

A firewall whose every rule sits where I meant it to, a router that stays fast under load, and any packet that will not arrive traced to exactly where it stops. That is the whole of the brief.

Bring the firewall problem — a packet that will not arrive, a ruleset to refactor without locking yourself out, a NAT or hairpin, or a flood to drop before it costs you. I will scope it.

Scope my firewall problem