apernet-traced: How One C Program Can Lie Convincingly to traceroute
A compact Linux packet engine that forges ICMP Time Exceeded replies, injects MPLS labels, and makes a single host look like a whole provider backbone.
- apernet-traced turns traceroute into a stage act, because the packet replies are convincing enough to rewrite what an observer thinks the network looks like.
- Its real trick is not spoofing one hop, but speaking traceroute's dialect well enough to expose MPLS labels through RFC 4950.
- The repo's two capture modes, TUN and inline, change how packets enter the system without changing the illusion they produce.
- A tiny C codebase, plus a Bison and Flex config language, gives this project the feel of a programmable backbone emulator rather than a simple traceroute hack.
Traceroute is supposed to reveal truth. `apernet-traced` uses that trust as the attack surface. A single Linux box can answer low-TTL probes with synthetic ICMP Time Exceeded packets, then dress those replies in MPLS label stacks so the path on screen looks like a provider backbone instead of a lone host.
That is the real story here. The repo is not a traceroute tool in the usual sense. It is a packet illusion engine that turns network visibility into a controlled performance.
The internet, as traceroute thinks it looks
The first surprise is conceptual, not technical. Traceroute only sees what routers choose to tell it, and `apernet-traced` exploits that rule directly. It intercepts packets with low TTL values, then emits handcrafted replies that make the outside world believe a path exists where there is only one machine.
That matters because traceroute is more than a troubleshooting command. It is a cultural habit in networking. Engineers use it to infer topology, blame latency, and sketch the shape of a path from the shape of replies. If the replies are fabricated well enough, the sketch still looks plausible.
Why fake MPLS labels at all?
The sharpest technical move in the repo is RFC 4950 support. `apernet-traced` does not stop at returning a generic ICMP response. It can append MPLS Label Stack Entries, which lets traceroute variants display the kind of metadata usually associated with carrier cores and backbone transit.
That is useful in two ways. As a teaching aid, it lets you see how MPLS-related traceroute output is formed without needing real ISP gear. As a diagnostic tool, it can simulate a transit path that is intentionally opaque or deliberately crafted for testing.
Two ways to stand in the path
The repo supports two operating modes, and that distinction is the key to its Linux plumbing. In TUN mode, the program behaves like a Layer 3 endpoint. Traffic is routed into a virtual interface, processed, and answered.
Inline mode is more invasive and more elegant. It uses `AF_PACKET` with promiscuous capture to sit transparently on a physical interface, inspect frames before the host stack claims them, and inject synthetic responses back into the flow.
| Purpose | What it observes | What it emits | Network layer | Main value | Typical user |
|---|---|---|---|---|---|
| apernet-traced | Low-TTL probes aimed at a configured path | Synthetic ICMP Time Exceeded replies, optionally with MPLS labels | L2 or L3 depending on mode | Makes one host impersonate a longer path | Network engineer, researcher, tinkerer |
| Standard traceroute | Live routers along the route | Probe packets and observed ICMP replies | Primarily L3 | Finds the path that already exists | Anyone debugging reachability |
| Jaeger or OpenTelemetry | Application spans and service calls | Tracing telemetry | Application layer | Explains request latency across services | Backend teams and platform engineers |
| Wireshark | Captured packets on an interface | Decoded packet views | L2 through L7 | Shows what actually crossed the wire | Protocol analyst, incident responder |
The table hides a useful distinction. `apernet-traced` is not an observability stack and not a packet sniffer. It is a reply synthesizer. It sits between observation and belief.
The packet engine under the hood
The core logic lives in a small set of C files. `build_reply()` decides whether an incoming packet matches a configured hop and then constructs the response. `build_rfc4950()` attaches MPLS metadata when requested. `cksum()` finishes the job by calculating the Internet checksum for the resulting headers.
// Simplified shape of the reply path
if (match(packet, rule)) {
icmp = build_reply(packet, rule);
if (rule->mpls_enabled) {
build_rfc4950(icmp, rule->label_stack);
}
icmp->checksum = cksum(icmp, icmp_len);
send_packet(icmp);
}
What makes that interesting is the level of control. The repo can randomize IP addresses and MPLS fields, which gives the fake path some variance. It does not have to look like a static demo. It can look like a living network.
The config file is a tiny language
The strongest design choice may be the least visible one. Instead of a plain text file or a JSON blob, the project uses Flex and Bison to define a small DSL for rules and hops. That lets the author describe a path with code-like precision.
rule {
hop 10.0.0.1
hop $src
hop random_ip(192.0.2.10, 192.0.2.99)
mpls label 16000 exp 0 s 1 ttl 64
}
The DSL matters because it shifts the repo from a one-off demo to a programmable topology generator. A hop can echo the sender, pick from a range, or alter label fields per response. That is a lot of expressive power for a compact codebase.
What it is built to outsmart
This project does not compete with Jaeger, Zipkin, or OpenTelemetry. It does not replace Wireshark either. Those tools are built to reveal reality. `apernet-traced` is built to shape it.
That puts it in a category of its own. It is closest to a packet-stage illusion generator, something you would use to simulate transit, teach MPLS behavior, or mask the shape of a small network behind a much larger story.
The comparison is useful because it prevents category confusion. If you expect monitoring, you will miss the point. If you expect deception with protocol literacy, the repo makes immediate sense.
Why this tiny repo is worth noticing
`apernet-traced` is niche, but the idea behind it is broad. Network topology is partly a story told by packets, and stories can be edited. Once you accept that, the project reads less like a curiosity and more like a clean demonstration of how much authority a convincing reply can have.
That is why this repository is memorable. It makes a single host look like a backbone, then shows every layer of the trick in plain C.