HomeIncident library
Incident library

INCIDENT REPLAY · 2022-06-23 (publication; pattern ongoing for years)

MikroTik prepend misconfiguration makes single-digit ASNs appear as hijackers

Operators typed a prepend count where MikroTik RouterOS expects an AS number, so paths appeared to contain or originate from AS2, AS3 and so on. Hijack detectors flagged the single-digit ASNs, and paths with the bogus AS could be dropped by networks filtering on it.

Fits no familyAS path / attribute anomalyCatalog confidence: high

A reconstruction, not the operator's network. Hammerhead's authors rebuilt the change from the public record as a small network of their own. No configuration here is the operator's. What follows is what the tool reported on that reconstruction; it is not a claim that the tool would have prevented the outage.

What happened

Who: Many small networks (MANRS names AS44227, AS138362, AS134159, AS135216 among them); AS1 to AS9 holders such as University of Delaware (AS2) wrongly implicated

The summary at the top is paraphrased from the sources below. Hammerhead's catalog rates its confidence in this account high.

Sources

What the public record says

  • Operators typed a prepend count where MikroTik RouterOS expects an AS number, so paths appeared to contain or originate from AS2, AS3 and so on. Hijack detectors flagged the single-digit ASNs, and paths with the bogus AS could be dropped by networks filtering on it.
  • Who: Many small networks (MANRS names AS44227, AS138362, AS134159, AS135216 among them); AS1 to AS9 holders such as University of Delaware (AS2) wrongly implicated

What the reconstruction assumed

Decided by Hammerhead's authors to build a network that runs. None of it describes the operator's network.

Everything below is ours.

  • This replay is the mistake in Cisco IOS syntax, where set as-path prepend 3 means AS 3. It was written before RouterOS was parsed. The RouterOS rows (tools/replays/gen_family_routeros.py, tests/gauntlet/replays-routeros.yaml) replay it as the operators wrote it: v6 set-bgp-prepend=N is a count and set-bgp-prepend-path= takes AS numbers, so set-bgp-prepend-path=3 puts AS 3 in the path; on v7 set bgp-path-prepend 3 is a count and passes.
  • Cisco IOS syntax and stand-in address space throughout. A reconstruction, not any operator's configuration.

What Hammerhead said

Each run below is pinned by Hammerhead's replay tests at commit 0ee9732: the verdict and the quoted text are checked against the tool's output, and a run that disagrees fails the test. Reason lines are copied verbatim; a pinned line can be part of a longer reason. Every preflight run uses --max-blast-radius 100, so a change is never counted as caught merely because it touched many devices of a small network.

Hammerhead's own first-versus-now record

First verdict
pass. The announcement still goes out and nothing inside the snapshot moves.
Verdict now
fail: the route-map clause would prepend AS 3, which is not the router's own AS. A neighbour's local-as counts as one's own.

Quoted from docs/replays/families/individual.md. “First” is the tool before the fixes this replay prompted.

the provider's own router (IOS syntax; the RouterOS rows are in replays-routeros.yaml)

now: fail

On the reconstruction, hammerhead preflight on a before and an after snapshot returned fail, for the reasons below.

Reason text pinned (some reason contains each line)

  • route-map PREPEND seq 10 would prepend AS 3, which is not this router's AS (64496)

Pinned in tests/gauntlet/replays-individual.yaml.

RouterOS v6: a count typed into `set-bgp-prepend-path`

now: fail

On the reconstruction, hammerhead preflight on a before and an after snapshot returned fail, for the reasons below.

Reason text pinned (some reason contains each line)

  • route-map transit-out seq 10 would prepend AS 3, which is not this router's AS (64496)

Pinned in tests/gauntlet/replays-routeros.yaml.

RouterOS v7 control: `set bgp-path-prepend 3` is a count, not AS 3

now: pass

On the reconstruction, hammerhead preflight on a before and an after snapshot returned pass.

Text no reason may contain

  • would prepend AS 3

Pinned in tests/gauntlet/replays-routeros.yaml.

What changed in Hammerhead because of it

From the “What was fixed” table in Hammerhead's replay notes, where each fix landed after a failing test. “Found by” is copied as written; a family name means the batch this incident belongs to.

Prepending an AS that is not one's own

set as-path prepend 3 puts AS 3 in the path; AS 3 drops the route as a loop and monitors name it as the culprit. A neighbour's local-as counts as one's own.

Found by: MikroTik prepends

MikroTik RouterOS parsed

Both incidents had to be rebuilt in IOS syntax. A dropped filter rule used to renumber the rest, which read as a policy widening; rules are numbered by their place in the chain.

Found by: SuproNet, MikroTik prepends

Limits

  • The configurations are a reconstruction. Where the record is silent, the assumptions above fill the gap; if one is wrong, the replay is wrong in that respect.
  • A verdict describes the reconstructed network's converged state. Timing, traffic load, and anything a device does that no configuration states, such as software reacting to a health check or a firmware bug, are outside it.
  • A pass is reported as a pass. A fail says a gate fired on the reconstruction, nothing more.
  • Why the catalog counts this outage as in scope: A prepend statement whose AS is not the local AS is a pure config lint, provided the vendor dialect is parsed.

Not fixed: RouterOS forms that are not read

OSPF v6, the v6 VRF, v7 per-connection redistribution, RFC 9234 roles, the firewall input chain and NAT stay unparsed, so a change touching them is refused, not evaluated. What the 2009 software did with an out-of-range prepend count is not guessed.

Recorded against: SuproNet, MikroTik prepends

Imported from docs/replays/mikrotik-prepend-2022/FACTS.md and the replay manifests in the Hammerhead repository at commit 0ee9732.