
[{"content":" Protobuf # 1. Origins \u0026amp; History # Protobuf was born inside Google around 2001 back when Jeff Dean and Sanjay Ghemawat were building the core infrastructure. In the beginning, it was yet another attempt to fix a recurring scale problem: thousands of servers needed to exchange structured data over the network and store it on disk, and the existing options were bad. Most nonstandard binary formats broke every time someone added a field. XML was oversized and slow to parse at the scale they needed. So they built an in-house format that was eventually named proto1. It was compact, fast, and reliably adaptable. It allowed old code to ingest new message formats and new code could read the old without anything breaking. Between 2005 and 2010 it had become the connective tissue in Google\u0026rsquo;s infrastructure — pretty much every server-to-server call and most stored data at the company was (and still is) in the protobuf format. In July 2008, Google open-sourced the cleaned-up second generation as proto2, in a release led by Kenton Varda. Proto3 followed with its stable 3.0 release in 2016, simplifying the language and allowing it to support many languages consistently — the \u0026ldquo;serialization\u0026rdquo; layer of gRPC was made available to the open-source community in 2015 as the public descendant of its internal Stubby RPC system. Currently, the \u0026ldquo;editions\u0026rdquo; models (released in 2023 \u0026amp; 2024) comprise the current generation. A fun genealogical footnote: Varda, the engineer who open-sourced protobuf and maintained proto2, later left and built Cap\u0026rsquo;n Proto, a competing format designed around eliminating the parse step entirely. Facebook\u0026rsquo;s Thrift was built by ex-Googlers reproducing the idea. Protobuf isn\u0026rsquo;t just a format; it\u0026rsquo;s the common ancestor of a whole family.\nAdoption # Inside Google, it\u0026rsquo;s total — the company has stated there are hundreds of thousands of distinct message types in its codebase. Outside, adoption rode two vehicles. The first is gRPC, which made protobuf the default serialization of the cloud-native world: Kubernetes components, etcd, Envoy, and most service-mesh internals speak it. The second is network telemetry: the OpenConfig ecosystem (gNMI, gNOI) standardized on protobuf over gRPC, which is precisely why Juniper\u0026rsquo;s JTI, Cisco\u0026rsquo;s model-driven telemetry, and Radware\u0026rsquo;s stream API all reach for it. It\u0026rsquo;s also embedded in TensorFlow model formats, game networking stacks, and countless mobile apps where payload size and battery matter.\n2. Who owns the protobuf Intellectual Property? # Google, more or less, but the answer is layered.\nThe Implementation: Google owns the copyright on the reference implementation (the protoc compiler and runtime libraries) and licenses it under the BSD 3-clause license — a permissive license that lets anyone use, modify, and redistribute it, commercially or otherwise, with attribution. So Google \u0026ldquo;owns\u0026rdquo; it in the copyright sense but has granted the world nearly unrestricted rights.\nThe Specification: Google owns this outright in a governance sense. As we saw (see?) in the IETF media-type draft, even the IETF\u0026rsquo;s own document lists Google\u0026rsquo;s protobuf team as the change controller and cites protobuf.dev as the normative reference. There is no standards body — no ISO, no IETF, no ECMA — with authority over the format. So, Google decides what protobuf is.\nThe Format: here\u0026rsquo;s the subtle part — a wire format as such is very hard to \u0026ldquo;own.\u0026rdquo; Copyright doesn\u0026rsquo;t protect ideas or methods of operation, and the encoding rules are published openly. Anyone can (and many do) write independent, clean-room protobuf implementations without touching Google\u0026rsquo;s code.\nOne caveat worth knowing when looking to hitch your horse:\nBSD-3 contains no express patent grant (unlike Apache 2.0, which is what gRPC uses). In practice Google has never asserted patents over protobuf in seventeen years of open availability, and the ecosystem treats it as unencumbered — but the formal patent posture rests on implied license and Google\u0026rsquo;s behavior rather than an explicit grant. The \u0026ldquo;BSD 3-clause\u0026rdquo; and \u0026ldquo;Apache 2.0\u0026rdquo; are two standardized, off-the-shelf open-source license texts that any copyright holder can apply to their own work.\nGoogle chose to release protobuf under the BSD 3-clause terms (and, incidentally, gRPC under the Apache 2.0 terms). Same owner, two different rental agreements for two different properties. So, my interpretation is that Google owns the trademark-level identity, the reference code copyright, and complete change control over the spec — while the format itself functions as a public good because independent implementation is trivial and legally uncontested.\nThat said, I\u0026rsquo;m not a lawyer and that\u0026rsquo;s the practical picture, not legal advice.\nLicense Comparison: Protobuf vs. gRPC\nAspect Protobuf (BSD 3-Clause) gRPC (Apache 2.0) Copyright holder Google Google License type Permissive Permissive Commercial use, modification, redistribution ✅ Allowed ✅ Allowed Attribution required ✅ Yes — retain copyright notice and license text ✅ Yes — retain notices, license text, and NOTICE file if present Express patent grant ❌ None — license is silent on patents ✅ Yes — contributors explicitly grant a patent license for the code Patent retaliation clause ❌ None ✅ Yes — file a patent suit over the code and your patent grant terminates Practical patent posture Rests on implied license doctrine + Google\u0026rsquo;s ~18-year non-assertion track record Written into the license itself Must state changes made ❌ No ✅ Yes — modified files must carry prominent change notices Endorsement restriction ✅ Explicit — can\u0026rsquo;t use Google\u0026rsquo;s name to promote derivatives without permission Implicit — no trademark rights granted Copyleft / share-alike obligation ❌ None — derivatives can be closed-source ❌ None — derivatives can be closed-source License text length ~3 short clauses, fits on a page ~9 sections, several pages Both are permissive licenses from the same owner; the load-bearing difference is the patent column — Apache 2.0 puts Google\u0026rsquo;s patent promise in writing, BSD-3 leaves it to implied license and Google\u0026rsquo;s non-assertion track record. Practical engineering picture, not legal advice.\n3. Protobuf Innovation # Protobuf needed to solve an interoperability problem in a largely heterogeneous and rapidly evolving environment: thousands of services, written in different languages, deployed independently, all exchanging structured data that changed shape constantly. To do this, it needed to perform three functions effectively within a single format — functions that had previously been handled by separate standards, tools, and conventions that rarely worked well together.\nFirst, it needed to describe the data — a formal, language-neutral definition of message structure that both sides of an exchange could treat as a standard. Previously, this was done by interface definition languages and schema notations: CORBA\u0026rsquo;s OMG IDL, ASN.1\u0026rsquo;s abstract syntax, XML Schema, or — as I\u0026rsquo;m told — a header file and a design doc that drifted out of sync with reality. Protobuf\u0026rsquo;s .proto file collapsed this into a small, readable schema where the field numbers are the contract.\nNext, it needed to deliver the data efficiently on the wire — a compact, fast-to-parse binary encoding. Previously, this was a separate standards layer entirely: ASN.1\u0026rsquo;s competing encoding rule sets (BER, DER, PER), Sun\u0026rsquo;s XDR, CORBA\u0026rsquo;s CDR, or the homespun TLV and die-cast formats every C shop maintained. Protobuf replaced the menu with exactly one encoding — varint-based, four wire types, no options to debate — it exchanged theoretical flexibility for a format simple enough to implement quickly and audit for security.\nThis is serialization, and THIS aspect makes protobuf genuinely valuable for OOB traffic inspection. Finally, it needed to age well. To connect any two endpoints across languages and across time — turning the schema into idiomatic, type-safe code in every language in use, and guaranteeing that yesterday\u0026rsquo;s compiled code could safely exchange messages with tomorrow\u0026rsquo;s. Previously, code generation belonged to expensive vendor compilers (ASN.1) or framework-locked stub generators (rpcgen, CORBA ORBs), and schema evolution belonged to nothing at all — it was managed by version fields, flag days, and luck. Protobuf shipped a free, polished compiler as the product itself, and made compatibility structural: unknown fields are skipped, names never travel, and retired field numbers are reserved forever.\n4. Serialization- What it actually does # Serialization converts a structured, in-memory object — with its types, its named fields, its nested sub-objects — into a flat sequence of bytes that can cross a wire or rest on disk, in a way that lets a receiver who shares the schema reconstruct the identical structure. It does so by creating an somewhat agnostic and minimalistic format, while parsing out expensive artifacts (usually verbosity) in the native data. \u0026ldquo;Flattening\u0026rdquo; the data (i.e. dumping the stream at the binary level) is not really the hard part. The challenge is in the interpretation of the structure. PCAP, for example, can be streamed, but PCAP needs to be understood by sender and consumer alike in order to be effective. This associated overhead is the baggage that limits PCAP to represent traffic flows, and not any other data structures. Does PCAP work well? Yes. But it will not scale as effectively as protobuf in heavy applications.\nProtobuf\u0026rsquo;s simple approach is a single recursive convention: every unit of data is preceded by a compact instruction for reading it. Feild types are assigned tags, and the tag declares which field is coming and what shape it takes — a self-terminating varint, a fixed 4- or 8-byte value, or a run of bytes whose exact length is stated up front. The parser never searches for boundaries and never relies on terminators; it advances recursively through addition. Read the instruction, consume exactly what it prescribes, and consistantly land on the next instruction in the bitstream.\nThis is the same engineering discipline that framing at the lower layers has always used. An IP header\u0026rsquo;s IHL and Total Length fields declare the header\u0026rsquo;s extent and the packet\u0026rsquo;s end before the parser reaches either; a TCP header\u0026rsquo;s Data Offset does the same for its options. Nothing in a well-designed protocol scans for an end marker, because content can always impersonate a marker. Protobuf takes that principle — declare extent in a prefix, never delimit with a sentinel — and applies it recursively to arbitrary application data. This single property is what makes the format extensible: the scaffolding that frames today\u0026rsquo;s fields frames tomorrow\u0026rsquo;s identically, so old parsers glide over new data without breaking. A nested message is simply a length-delimited field whose bytes happen to be another protobuf message; the parser can descend into it, or skip it wholesale, using the same length prefix either way.\nBecause the convention composes, structures of any depth — messages inside messages, lists of messages, maps of messages — reduce on the wire to the same primitive: instruction, then exactly-measured content. And because every unit is self-measuring, a receiver can traverse data it only partially understands, skipping unknown fields by their declared extent. That single property is what makes the format extensible: the scaffolding that frames today\u0026rsquo;s fields frames tomorrow\u0026rsquo;s identically, so old parsers glide over new data without breaking.\nWhat the format deliberately does not do is frame itself at the top. A serialized message has no header, no footer, no overall length — it is only the concatenation of its fields.\nThe outermost boundary is delegated to whatever carries the message: gRPC frames it on the HTTP/2 stream with a five-byte prefix, a Kafka record frames it with the record\u0026rsquo;s length, a file frames it with the file\u0026rsquo;s size. Each layer measures its own payload and lets the layer below carry it.\n5. Protobuf Field Mapping: Ethernet / IPv4 / TLS Record # *Field numbers are per-message (each protocol is its own protobuf message); they are schema choices, not standards. Wire types: varint = self-terminating variable-length integer; fixed32 = always 4 bytes; len-delim = length prefix\nraw bytes.* Field Tag # Protobuf Encoding Target — Ethernet Header — Destination MAC 1 len-delim bytes, length 6 DA — fixed 48 bits Source MAC 2 len-delim bytes, length 6 SA — fixed 48 bits 802.1Q VLAN Tag 3 varint uint32; absent = untagged frame VLAN — optional 32 bits EtherType 4 varint uint32; 2 wire bytes for values ≥ 0x0800 EtherType — fixed 16 bits — IPv4 Header — Version 1 varint uint32; 1 byte Ver — fixed 4 bits IHL 2 varint uint32; 1 byte IHL — fixed 4 bits DSCP / ECN 3 varint uint32; 1 byte ToS — fixed 8 bits Total Length 4 varint uint32; 1–2 bytes Len — fixed 16 bits Identification 5 varint uint32; 1–3 bytes ID — fixed 16 bits Flags 6 varint uint32; 1 byte Flags — fixed 3 bits Fragment Offset 7 varint uint32; 1–2 bytes FragOff — fixed 13 bits TTL 8 varint uint32; 1 byte TTL — fixed 8 bits Protocol 9 varint uint32; 1 byte Proto — fixed 8 bits Header Checksum 10 fixed32; full-width value, varint saves nothing Csum — fixed 16 bits Source Address 11 fixed32; always 4 bytes, no small-value bias SA — fixed 32 bits Destination Address 12 fixed32; always 4 bytes DA — fixed 32 bits Options 13 len-delim bytes; absent when no options Options — variable, ≤ 40 bytes — TLS Record Header — Content Type 1 varint uint32; 1 byte (22 = handshake) Type — fixed 8 bits Legacy Version 2 varint uint32; 2 wire bytes (0x0303) Ver — fixed 16 bits Record Length 3 varint uint32; 1–2 bytes Len — fixed 16 bits Fragment (payload) 4 len-delim bytes; length prefix states extent Payload — variable, ≤ 2^14 B 6. A Happy Ending # Focusing on serialization is my doing(for better or worse), but the story and conditions that led to the rise of protobuf and its continuing impact on traffic telemetry is a good one. The innovation was not any one function per se, but the refusal to treat them as separate concerns. Protobuf is one solution, a single artifact checked into version control, delivering the interface contract, the wire format, and the compatibility guarantee.\nThis makes Protobuf one of those rare elements that simply show up and provide universal value without garnering revenue intrinsically. Google considers it to be the core \u0026ldquo;glue\u0026rdquo; for its internal services and infrastructure. As it reaches across systems and applications, I think it\u0026rsquo;s like a network of highways. It\u0026rsquo;s value is really measured in proportion to what it makes possible, not what it actually costs to use.\nProtobuf succeeded so completely that it became boring, which is the reason gRPC/protobuf packet streaming is quietly appearing in vendor products without fanfare. The roads were already built; vendors and operators need only to add an on-ramp.\n","date":"6 July 2026","externalUrl":null,"permalink":"/posts/qb-protobuf/","section":"Posts","summary":"Protobuf # 1. Origins \u0026 History # Protobuf was born inside Google around 2001 back when Jeff Dean and Sanjay Ghemawat were building the core infrastructure. In the beginning, it was yet another attempt to fix a recurring scale problem: thousands of servers needed to exchange structured data over the network and store it on disk, and the existing options were bad. Most nonstandard binary formats broke every time someone added a field. XML was oversized and slow to parse at the scale they needed. So they built an in-house format that was eventually named proto1. It was compact, fast, and reliably adaptable. It allowed old code to ingest new message formats and new code could read the old without anything breaking. Between 2005 and 2010 it had become the connective tissue in Google’s infrastructure — pretty much every server-to-server call and most stored data at the company was (and still is) in the protobuf format. In July 2008, Google open-sourced the cleaned-up second generation as proto2, in a release led by Kenton Varda. Proto3 followed with its stable 3.0 release in 2016, simplifying the language and allowing it to support many languages consistently — the “serialization” layer of gRPC was made available to the open-source community in 2015 as the public descendant of its internal Stubby RPC system. Currently, the “editions” models (released in 2023 \u0026 2024) comprise the current generation. A fun genealogical footnote: Varda, the engineer who open-sourced protobuf and maintained proto2, later left and built Cap’n Proto, a competing format designed around eliminating the parse step entirely. Facebook’s Thrift was built by ex-Googlers reproducing the idea. Protobuf isn’t just a format; it’s the common ancestor of a whole family.\n","title":"A quick bit on Protobuf","type":"posts"},{"content":"Networking, cybersecurity, and infrastructure — notes from the field.\n","date":"6 July 2026","externalUrl":null,"permalink":"/","section":"Code Mule","summary":"Networking, cybersecurity, and infrastructure — notes from the field.\n","title":"Code Mule","type":"page"},{"content":"Technical writing on networking, cybersecurity, and infrastructure.\n","date":"6 July 2026","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"Technical writing on networking, cybersecurity, and infrastructure.\n","title":"Posts","type":"posts"},{"content":" IPFIX vs. IE315/SPM: Flow Telemetry Architectures for DDoS Detection # 1. Framing: What DDoS Detection Demands from Telemetry # The Traditional Paradigm: Splitting the Defense # Traditionally, DDoS defense was a game of architectural division. Network operators split attacks into two categories based on how they were most efficiently managed: volumetric floods and application-layer exploits. For Layer 3 and 4 volumetric floods (like UDP amplification / reflection blasts), the primary goal was protecting core bandwidth. Every day the core performance is handicapped by a perpetual barrage of short-term, high frequency attack traffic. The collective effect of these attacks are significant, and can be difficult to effectively/efficiently count. On a particularly bad day, a large flood carried into the core will actually overwhelm interface links between routers. For enterprise this translates to lost availability, while for service providers this could break tier one services like DNS, or simply impact customer experience.\nConsequently, these attacks were detected and policed at the outermost network edge. Operators monitored basic NetFlow metadata from edge routers to spot massive packet-per-second spikes, then utilized high-throughput ACLs or BGP routing redirections to drop or scrub the raw volume before it could enter the core network. Conversely, Layer 7 application attacks required an entirely different philosophy. Because these threats mimic legitimate user traffic (like malicious HTTP GET floods), standard edge routers could not see them. Efficiency demanded moving the defense inline, right at the point of convergence closest to the target application. This allowed an inline Web Application Firewall (WAF) or local application proxy to step in. Because it sat directly in the traffic path, the WAF possessed the cryptographic and processing capacity to decrypt TLS traffic, inspect deep packet headers, analyze cookies, and issue JavaScript challenges to weed out bots from human users.\nThe Modern Shift: Centralized Brain, Distributed Muscle # Today, this rigid separation of duties is rapidly dissolving. The architecture is shifting toward an intelligent, unified model: centralized detection paired with distributed policing. Rather than relying on siloed edge routers and localized inline WAFs to detect threats independently, modern systems stream real-time telemetry from across the entire ecosystem into a centralized, cloud-native detection engine. This centralized \u0026ldquo;brain\u0026rdquo; synthesizes network-wide data to detect highly sophisticated, multi-vector campaigns—such as low-and-slow application scraping paired simultaneously with a distributed L4 carpet-bombing attack—that single nodes would entirely miss. Once an attack signature is identified, the centralized controller does not pull the malicious traffic inward for cleaning. Instead, it uses automation protocols to push dynamic mitigation instructions outward to the absolute closest enforcement points. By utilizing NETCONF and RESTCONF, the controller can instantly reconfigure edge interfaces, while leveraging BGP FlowSpec to rapidly distribute precise packet-filtering rules across upstream peering routers. Concurrently, it can deploy lightweight rate-limiting scripts or IP blocklists to distributed Anycast CDN edge workers. This combination ensures that the computational weight of detection is centralized, while the physical policing of the traffic happens dynamically at the network perimeter, shielding core bandwidth and application compute resources alike.\nIterative Defense: The Slipknot Dynamic of Centralized Detection # DDoS defense is not a single decision — it is a loop. Deploy a coarse filter fast, watch what the traffic does, tighten, watch again. Each pass squeezes out more false positives while preserving legitimate flows. That progressive tightening is the slipknot effect, and it is the operating rhythm of every detection platform. The rest of this section unpacks why the loop exists and where you choose to set the knot.\nI might better have named this section \u0026ldquo;The Slipknot Dynamic of Centralized Characterization\u0026rdquo; — but let\u0026rsquo;s talk through it. In this article, \u0026ldquo;detection\u0026rdquo; means: there is evidence of a condition (an attack) that must be mitigated per my policy criteria. Once the centralized detection mechanism flags the anomaly, the real question begins: what am I looking at?\nMost attacks spoof — they forge the L3 source address to obfuscate origin. A naive detector could simply block traffic from the observed source, but that punishes legitimate flows sharing the address while the attack continues under new spoofed sources. This is where characterization comes in: nailing down the specificity of the attack until the most efficient rule can be built. Characterization is what each turn of the loop refines.\nWhy not characterize fully before acting? Because the clock is running. The centralized model displaces expensive inline IDS/IPS and firewall functions by sampling traffic from many points across the network — but the metric it must answer for is time to mitigation: the delta between the moment the attack is identified and the moment a deployed rule is actively treating the traffic. For a reflection attack, that\u0026rsquo;s the window between first sight of attack traffic and a live filter ventilating it.\nAnd unlike an inline IDS/IPS or firewall, which sees attack traffic in its entirety, the centralized model works from data that is sampled, incomplete, and inconsistent across observation points. So the first turn of the loop — usually a discard rule — is deployed as quickly as possible to minimize time to mitigation, knowing it is rarely as finely tuned as it could be. An over-aggressive discard rule will mistake legitimate customer traffic for attack traffic and drop it too: a false positive. The subsequent turns exist to walk those back.\nThe initial mitigation deliberately trades specificity for speed, producing a false-positive transient that the slipknot loop then decays toward, eventually reaching steady state. Where you set the knot is administrative preference. This is where balance is engineered into policy, driven by how much DDoS the target can reasonably absorb without falling over. The defense can be aggressive — deflate the attack immediately, then fine-tune to walk back false positives — or it can be required to meet specific characterization criteria before any blocking rule deploys at all.\nThe Centralized Data Diet: Fueling Accurate Interpretation # To accurately interpret incoming traffic samples and avoid costly false positives during an attack, a centralized detection mechanism requires a diverse and rich set of ingestion sources. Beyond network flows (NetFlow/IPFIX/IE315) and application logs, the engine leans heavily on external threat intelligence: real-time lists of compromised bulletproof hosting providers, known botnet command-and-control (C2) addresses, and active proxy and VPN exit nodes.\nA brief rant, because this matters. Security sales folks will position external threat intelligence as an optional line item — an OPEX add-on you can decline. This is a very limiting view. We live in a world of Software as a Service: consider the market saturation of Google Workspace and Microsoft 365, or the exodus from private DNS resolvers toward public resolution services. The notion that an enterprise or service provider could effectively collect and cultivate its own daily threat data is not realistic. And the economics already favor the model — the cost reduction of centralized detection platforms like Deepfield versus inline IDS/IPS covering the same footprint is compelling even with the associated subscription (Genome, in Deepfield\u0026rsquo;s case). Put plainly: ingesting user-plane traffic via IPFIX and IE315 is mandatory for visibility into the network, and the forensic context of external threat intelligence is equally mandatory for characterizing what that visibility shows you.\nOne without the other is half a detector. Flow telemetry gives you visibility; external threat intelligence gives you the context to characterize what you\u0026rsquo;re seeing. Flow data and threat feeds still aren\u0026rsquo;t the whole matrix. The engine combines them with reputation scoring and BGP routing tables to map global traffic origins and flag anomalies like route leaks or suspicious AS-path hijacks; with historical traffic baselines and DNS telemetry; and with cryptographic threat feeds tracking active TLS fingerprinting trends, such as the JA3/JA4 profiles that identify automated attack tooling. Cross-referencing live sampled traffic against this multi-dimensional matrix — external intelligence plus internal behavioral baselines — is what lets the engine confidently distinguish a coordinated assault from a sudden, legitimate surge of holiday shopping traffic.\nDetection Requirement What the Telemetry Must Provide Volumetric attacks (floods, amplification) Accurate aggregate rate estimation per target — tolerant of sampling State-exhaustion attacks (SYN floods, connection-table attacks) Per-packet protocol behavior: flag sequences, source cardinality Application-layer attacks (HTTP floods, TLS abuse) Visibility above L4 — payload-prefix or handshake fingerprints Low-and-slow / carpet-bombing Sensitivity to many small flows, not just elephant flows Detection speed Bounded, short delay between packet-on-wire and record-at-ingestor Telemetry survivability The export path must not degrade during the attack it is reporting Modern networks require both depth and speed in visibility. Traditional IPFIX (NetFlow v10) delivers rich flow context but with inherent latency. Sampled Port Mirroring (SPM) provides near real-time packet samples with payload visibility. IPFIX IE 315 bridges the two by exporting sampled packet data inside standard IPFIX records. These technologies are not competitors — they are powerful complements, especially in high-speed DDoS protection scenarios. More importantly, traffic detection systems that take advantage of these diverse sources contribute to an improved efficiency within the layered defense ecosystem. This article will focus on traffic telemmetry, specifically IPFIX and IE315. It is intended as an introduction to these protocols.\n2. IPFIX: Stateful Flow Telemetry # 2.1 The Pipeline: Selection → Metering → Export # An IPFIX exporter manages high-speed traffic through three pipeline stages: Selection (sampling and filtering), Metering (flow caching), and Export (templating and transport).\nSelection: Sampling and Filtering # Rather than processing every packet, the exporter uses a Packet Sampling (PSAMP) approach to reduce load on high-bandwidth links:\nSampling rate. The exporter is configured with a sampler map (e.g., N = 1000), selecting one of every N packets. Filtering. Sampled packets are checked against configured criteria — a specific interface, prefix, or direction — to isolate traffic of interest. Observation point. The selected packets are the statistical samples from which all downstream flow data is derived. Metering: Flow Construction and Caching # Selected packets feed a metering process that groups them into flows — \u0026ldquo;conversations\u0026rdquo; identified by a configured key set:\nFlow keys. Packets are aggregated on standard keys: source/destination IP, L4 ports, and protocol (see 2.3). State maintenance. The exporter holds each active flow in a local memory cache, updating byte counts, packet counts, and timestamps as matching samples arrive. Flow expiration (aging). A cache entry persists until an expiration trigger fires: an inactivity timeout (e.g., no packets for 30 seconds), an active timeout (e.g., a long-lived flow force-flushed at 60–1800 seconds), or a TCP FIN/RST indicating connection teardown. On expiry, the entry is packaged as a flow record and moved to the export buffer. This cache is the defining architectural commitment of standard IPFIX — and, as Sections 2.3 and 4 will show, its defining vulnerability. Export: Templates and Transport # Unlike fixed-format predecessors, IPFIX uses a template-based architecture:\nTemplates. The exporter transmits IPFIX Templates — layout dictionaries declaring which fields will follow and in what order — so the collector can decode subsequent binary records. Because the common transport is stateless (see below), templates are retransmitted at a refresh interval; a collector joining mid-stream is blind until the next template arrives. Encoding. Expired flow records are encoded per the template and grouped into sets within an IPFIX Message. Transport. IPFIX is a push protocol: the exporter periodically sends messages to a collector, typically over UDP port 4739. (RFC 7011 actually mandates SCTP support, with UDP and TCP optional —IRL we pretty much smiled and nodded at this while continuing to use UDP) Sequence numbers in the message header let the collector detect dropped records. 2.2 The IANA Information Element Registry # To give exporters and collectors a unified vocabulary, IANA maintains a centralized registry of IPFIX Information Elements (IEs). Every common observable attribute — an IPv4 address, an MPLS label, a timestamp, a counter — has a globally unique IE number. (Vendors can still define proprietary elements: a flag bit in the template field scopes the ID to the vendor\u0026rsquo;s Private Enterprise Number instead of the IANA registry — the extensibility hook that lets platforms carry telemetry the standard never anticipated.)\nAn exporter never sends field names. It sends a template of IANA IDs:\nIE #8 — sourceIPv4Address IE #12 — destinationIPv4Address IE #1 — octetDeltaCount (bytes) IE #2 — packetDeltaCount IE #4 — protocolIdentifier The collector resolves each numeric ID against the registry and decodes the binary payload accordingly. Each IE also carries a registered data type (unsigned32, ipv4Address, dateTimeMilliseconds, \u0026hellip;) and a semantics property (identifier, deltaCounter, totalCounter, \u0026hellip;) — a distinction that becomes functional in the next subsection. (This registry is also where IE #315 lives — the single element on which Section 3\u0026rsquo;s entire architecture is built.)\n2.3 Flow Keys vs. Metrics: How the Cache Behaves Under Attack # Within a flow record, IEs play one of two roles, and the difference determines how the router\u0026rsquo;s cache behaves under attack.\nIdentifiers (flow keys) define a flow\u0026rsquo;s identity — who is talking, to whom, over what protocol (e.g., IE #8, #12, #7 sourceTransportPort, #4). Keys are evaluated as a strict logical AND: a sampled packet must match every configured key of an existing cache entry to join that flow. Any single mismatch — a different source port, a different IP — creates a new cache entry. The number of distinct key tuples the router observes — the cardinality of the key space — is therefore the number of rows the cache must hold. Keys are immutable for the life of the entry, and the key tuple is what the hash engine uses to index the cache in memory.\nMetrics (non-keys) are the measurements attached to that identity (e.g., IE #1, #2, flowStartMilliseconds #152 / flowEndMilliseconds #153, flowEndReason #136). On a cache hit, metrics are accumulated or overwritten in place — counters add, timestamps update. Crucially, changing metric values never creates new rows.\nAttribute Flow Keys Metrics Cache behavior Any mismatch → new entry Match → update in place Cardinality risk High — each unique tuple is a row None — no new rows The asymmetry in that second line is the DDoS-relevant insight: cache growth is driven entirely by key cardinality. A spoofed-source SYN flood presents millions of unique source IP/port tuples. Every one is a key mismatch; every mismatch carves a new row. The attack does not merely generate traffic for the router to report — it weaponizes the reporting mechanism itself, exploding the flow cache precisely when accurate telemetry matters most. Section 2.4 shows how the exporter signals this degradation; Section 4 examines what the ingestor can and cannot do about it.\n2.4 Options Templates: Telemetry About the Telemetry # An IPFIX Options Template differs fundamentally from a data template. Where data templates describe traffic, an options template exports metadata about the tracking system itself — sampling configuration, cache health, interface drop counters. For DDoS detection this context is not optional: without it, the ingestor cannot distinguish a genuine traffic surge from a degrading exporter, and cannot scale sampled counts into real-world magnitudes. Three anomaly classes matter most:\nThe sampling multiplier — tracking the active sampling rate so all flow data can be normalized. Resource exhaustion — flagging cache overflow caused by high-cardinality attacks (the SYN-flood side effect from 2.3). Interface drop statistics — counting packets discarded at the ASIC before the sampler ever saw them. A Practical DDoS-Oriented Options Template # Template Record (the layout, sent first): Template ID 258, Scope Field Count 1, Field Count 4.\nField IANA IE # Length (bytes) Role ingressInterface (scope) 10 4 The interface this option describes samplingPacketInterval 305 4 Current 1:N denominator flowEndReason 136 1 Flags early flushes — 0x03 = cache full droppedPacketDeltaCount 133 8 Packets dropped before sampling tcpControlBits 6 2 Accumulated TCP flag states Data Record (decoded example, mid-attack): { \u0026#34;TemplateID\u0026#34;: 258, \u0026#34;Scope\u0026#34;: { \u0026#34;ingressInterface\u0026#34;: 10101 }, \u0026#34;Metrics\u0026#34;: { \u0026#34;samplingPacketInterval\u0026#34;: 4000, \u0026#34;flowEndReason\u0026#34;: 3, \u0026#34;droppedPacketDeltaCount\u0026#34;: 14200500, \u0026#34;tcpControlBits\u0026#34;: 2 } } How the Ingestor Uses This # Normalization. Reading samplingPacketInterval: 4000, the ingestor multiplies all flow records from interface 10101 by 4,000 to compute true volumetric attack size. Detecting telemetry degradation. flowEndReason: 3 (lack of resources) arriving alongside a surge of unique flow records is the signature of a cache-flooding attack — a warning that the exporter\u0026rsquo;s own view is degrading under memory pressure. Accounting for blind spots. droppedPacketDeltaCount at 14.2M reveals traffic discarded at line rate before sampling — ensuring the detection platform sees the true magnitude of a flood even when the sampler cannot. 3. IE315 / SPM: Stateless Packet-Section Telemetry # Section 2 ended with the flow cache as the victim: an architecture whose per-flow state is precisely the resource a spoofed flood exhausts. Stream Packet Metering inverts the design premise. Rather than asking the router to summarize traffic — hash it, correlate it, hold it in memory until a timer fires — SPM asks it to do something routers are already very good at: grab a section of the sampled packet and forward it, immediately, with no state retained. The intelligence doesn\u0026rsquo;t disappear; it relocates. Everything the cache used to do on the ASIC now happens on the ingestor, where memory is horizontally scalable and an attacker\u0026rsquo;s cardinality explosion is just more rows in a database. The subsections that follow mirror Section 2 deliberately — same pipeline stages, same registry mechanics, same failure analysis — so the two architectures can be compared joint by joint.\n3.1 The Pipeline: Selection → Extraction → Immediate Export # Same sampler, deleted middle stage. Draft the \u0026ldquo;no cache, no state, no timers\u0026rdquo; contrast diagram; establish ASIC-path line-rate export; note aggressive sampling rates become affordable. [CONFIRM FP4/FP5 specifics.]\nStandard IPFIX: [Packets] -\u0026gt; [Sample 1:N] -\u0026gt; [Flow cache: hash, match, accumulate] -\u0026gt; [Timer expiry] -\u0026gt; [Export summary] IE315 / SPM: [Packets] -\u0026gt; [Sample 1:N] -\u0026gt; [Copy header section] -\u0026gt; [Export immediately] 3.2 What IE315 Actually Carries # SPM is not a rival protocol. It is standard IPFIX — same templates, same transport, same port 4739 — carrying one unusual Information Element: IE #315, dataLinkFrameSection (RFC 7133). Where the elements of Section 2 carry derived values — counters accumulated, timestamps computed — IE 315 carries a verbatim octet slice of the raw frame itself. The collector receives evidence, not testimony.\nOne Slice, Anchored at Byte Zero # IE 315 belongs to a small family of packet-section elements (#313–#317), and the differences are entirely about where the slice begins. ipHeaderPacketSection (#313) starts at the IP header; mplsLabelStackSection (#316) at the MPLS stack. IE 315 starts at layer 2 — byte zero of the frame. There is no per-layer selection happening: the element is a single contiguous copy of bytes 0 through N, and everything it captures falls out of the fact that the layers are nested in order on the wire:\nbyte 0 byte N ↓ ↓ [ Ethernet | VLAN tags | MPLS stack | IP hdr | TCP hdr | payload… ]cut L2 L2.5 L2.5 L3 L4 L7 The L2 anchor is why IE 315 wins for provider networks: everything above L2 comes along for free. The 802.1Q VLAN tags, the full MPLS label stack, the IP header, the L4 header — captured in order, exactly as they appeared on the wire. Slice from the IP header instead (#313) and the L2/2.5 context that maps traffic to a customer — not just an address — is gone before it was ever recorded. Consider 5G slicing at the PDN and NGPON mapping at the BNG. This context is invaluable as access networks shift from DDoS targets to DDoS origins. The Depth Knob: What N Is and Is Not # The depth of the slice is configurable, and it is worth being precise about what kind of value N is, because it behaves differently at three layers:\nOn the wire, IE 315 is a variable-length octetArray: each record carries its own length. RFC 7133 explicitly permits the exported section to be shorter than the configured depth when the packet itself is shorter — a 64-byte SYN yields 64 bytes, not a padded slice. The companion element dataLinkFrameSize (#312) preserves the frame\u0026rsquo;s original length, so the collector can always distinguish small packet, captured whole from large packet, truncated. In configuration, N is a fixed cap set on the exporter: every slice is min(configured depth, frame length). The copy is deliberately dumb — the router does not inspect the packet and decide to grab more for interesting traffic. Any per-packet judgment about how much to capture would reintroduce exactly the processing the stateless design deleted; the dumb copy is what makes line-rate export on the forwarding ASIC affordable. [CONFIRM SR-OS default depth.] In planning, N is a bandwidth lever: export stream ≈ traffic rate ÷ sampling ratio × (N + record overhead). Double the depth, roughly double the telemetry stream. Section 3.4\u0026rsquo;s worked example prices this out. Depth Is What Makes Fingerprinting Possible # Set N past the Ethernet, IP, and TCP headers and the slice reaches the initial payload bytes: for HTTPS traffic, the TLS ClientHello — precisely the bytes that JA3/JA4 fingerprinting hashes. Depth is the difference between header telemetry and fingerprint-capable telemetry.\nOne operational caution follows directly from the anchor diagram: variable-length encapsulation spends the depth budget. A frame carrying two VLAN tags and a four-label MPLS stack pushes the TCP header roughly 24 bytes deeper into the slice than an untagged frame — an N tuned on the lab bench can clip the ClientHello in production where the encapsulation is heavier. Size N for the worst-case stack you actually forward, not the cleanest one.\nCompanions and the Honest Boundary # The slice does not travel alone. Companion elements in the same record carry its context: dataLinkFrameSize (#312) as above; interface identifiers recording where the packet was observed. [Template 258 table here — pull the field list from SR-OS docs or a Wireshark capture of the template set.]\nThe honest boundary: this is a truncated section of one sampled packet, not packet capture. The slice reaches as high up the stack as its configured depth allows — through L4 and into initial payload bytes if set generously — but it is still the first N bytes of one frame, in isolation. No full payloads, no reassembly, no conversations: the head of the frames the sampler selected, and nothing more.\n3.3 The Ingestor Side: Flow Reconstruction as a Service # The state removed from the router moved to the ingestor: parse → key → correlate at millions of records/sec. Key argument to build toward: the cardinality explosion from 2.3 lands on a horizontally scalable analytics cluster instead of a forwarding ASIC\u0026rsquo;s cache — the attack that poisons IPFIX telemetry is, under SPM, just more data. Add per-packet capabilities no flow record contains: TCP flag microstructure, TTL/IP-ID distributions, inter-arrival timing, payload-prefix signatures. Honest sizing paragraph on why SPM ships tethered to purpose-built platforms.\n3.4 Costs and Operational Context # Bandwidth math for the export stream (worked 400G / 1:1000 / 128B example); normalization still required, but the entire state-degradation signal class(flowEndReason 0x03) has no SPM equivalent — as there is no cache to exhaust; loss semantics (one lost record = one lost sample, not a lost conversation); deployment maturity and platform coupling caveat.\n4. Feeding the Ingestor: Detection Consequences # [Your efficacy material lands here, expanded into the comparison it implies.]\n4.1 What Sampled Flow Records Can and Cannot See # When an exporter samples at 1:1000, it is running a statistical poll; the ingestor compensates with a statistical multiplier. Effectiveness varies sharply by objective:\nUse Case Efficacy Why Capacity planning \u0026amp; billing High Large flows are sampled consistently; scaling maps macro trends accurately Volumetric DDoS detection High A flood of millions of packets reliably hits the 1:1000 lottery Forensics \u0026amp; incident response Low Low-and-slow flows and short conversations are missed entirely Application-layer monitoring None Skipped packets mean no reliable flag sequences, handshakes, or payload visibility The first two rows explain why sampled IPFIX has served providers well for a decade. The last two rows define the gap SPM was built to close. 4.2 Time to Detection # Standard IPFIX detection latency is bounded below by cache timers: worst case ≈ active timeout + export interval. [Do the arithmetic with real default timer values — turn \u0026ldquo;minutes vs. sub-second\u0026rdquo; from an assertion into a calculation.] IE315 streams within the forwarding epoch: detection latency collapses to transport + ingestor processing time, enabling sub-second volumetric alarming and the fast mitigation loops (Flowspec triggering) that providers actually deploy. [One sentence only — mitigation is out of scope.]\n4.3 Detecting Through Degradation # Section 2.3 established that the cardinality of the traffic\u0026rsquo;s key space — the number of distinct tuples presented to the exporter — dictates flow cache occupancy, and that an attacker controls that number. Under a cache-flooding attack the cache saturates, and IPFIX telemetry degrades. Its virtue is that it degrades loudly: entries are force-expired early and stamped flowEndReason 0x03, while the options-template counters (droppedPacketDeltaCount, the sampling interval) report the exporter\u0026rsquo;s own distress. Detection through self-diagnosis. On the consumer side the signature is unmistakable: a surge of unique, short-lived, mostly single-packet flow records arriving hand-in-hand with 0x03 — the cache being drained faster than any legitimate traffic mix would drain it. SPM sidesteps the failure mode entirely: there is no cache to exhaust, so the attacker\u0026rsquo;s key randomization — the entire weapon against the flow cache — is a no-op against the export path. The same flood arrives at the ingestor as ordinary records at the sampler-set rate, the source-cardinality explosion is plainly visible in the data, and the detection platform\u0026rsquo;s compute scales horizontally where a line card\u0026rsquo;s cache cannot. The distinction worth naming: IPFIX detects the attack partly by noticing its own injuries; SPM detects it with uninjured instruments. Self-aware degradation versus structural immunity — and in a detection architecture built on input diversity, both signals are valuable. A flowEndReason 0x03 storm from the IPFIX tier is itself a detection input: few things say \u0026ldquo;spoofed high-cardinality flood\u0026rdquo; more plainly than the multiple flow caches winging at the same time.\n4.4 Attack-Class Coverage Matrix 🔨 # [The gap flagged earlier — make it explicit. Suggested rows:]\nAttack Class Sampled IPFIX IE315/SPM Volumetric floods / amplification ✔ Strong ✔ Strong Carpet-bombing / spread attacks Partial — [draft: aggregation across prefixes] ✔ [draft: per-packet granularity] State-exhaustion (SYN floods) Partial — sees volume, may self-degrade ✔ Flag microstructure + cardinality at scale Application-layer (HTTP/TLS) ✖ ✔ Payload-prefix / handshake fingerprints Low-and-slow ✖ Statistically invisible Partial — [draft: sampling still applies; discuss honestly] 5. Head-to-Head and Deployment Guidance # Dimension Standard IPFIX IE315/SPM Router resource load Flow cache in memory; scales with flow count [softened per note below] Near-zero — stateless ASIC path; scales with sampling rate Ingestor load Light — pre-summarized records Heavy — flow reconstruction + analytics cluster Detection latency Timer-bounded (tens of seconds–minutes) Sub-second Attack-class coverage Volumetric Volumetric + state-exhaustion + application-layer Telemetry bandwidth Minimal Significant, linear in sampling rate (3.4 math) Under-attack behavior Self-aware degradation Structurally unaffected Ecosystem Universal — any collector Encoding standardized; analytics platform-coupled Enterprise networks with modest scale, generic collectors, and volumetric-dominant threat models are well served by stateful IPFIX. High-scale service-provider edges facing diverse attack classes — and able to justify a purpose-built analytics platform — are where IE315/SPM earns its cost. Many real deployments run both: IPFIX for universal baseline visibility, SPM feeding the DDoS detection tier.\n6. Conclusion and Scope # IPFIX taxes the router; SPM taxes the ingestor — and the ingestor is the side built to scale. Strip away the registry numbers and the pipeline diagrams, and the article reduces to that single architectural symmetry. Standard IPFIX asks the forwarding plane to summarize: hash, correlate, hold state, report on a timer. That summary is cheap to transport and universal to consume, but the cache it depends on is a fixed-size resource sitting in the data path — and Section 2.3 showed that an attacker doesn\u0026rsquo;t have to overwhelm your links to hurt you; presenting enough unique key tuples weaponizes the reporting mechanism itself, degrading your visibility at precisely the moment you need it most. IPFIX\u0026rsquo;s saving grace is that it degrades honestly: flowEndReason 0x03 and the options-template counters are the exporter telling you its own view is failing. Self-aware degradation is a real virtue. Structural immunity is a better one.\nIE 315 buys structural immunity by relocating the intelligence, not inventing a protocol. Same templates, same transport — one element carrying a verbatim slice of the frame instead of a derived summary. Evidence instead of testimony. Everything the flow cache used to do moves to a horizontally scalable analytics tier, where the cardinality explosion that poisons a cache is just more rows in a database. The price is real and was priced honestly in 3.4: significant export bandwidth, a heavyweight ingestor, and coupling to a purpose-built platform. There is no free lunch here — only a choice about which side of the wire pays for it.\nFaster, richer telemetry isn\u0026rsquo;t just better detection — it\u0026rsquo;s a tighter loop. Sampled flow records remain the best option for calculating aggregate rate estimation, capacity trends, volumetric alarming. But the modern threat model — state-exhaustion floods,TLS-fingerprinted botnets, carpet-bombing across prefixes — lives in exactly the per-packet detail a flow summary discards: flag microstructure, payload prefixes, the ClientHello bytes that JA3/JA4 hashes. And speed compounds the advantage, because the centralized model of Section 1 is a loop — sample, characterize, deploy, tighten. Telemetry that arrives in seconds instead of timer-bounded minutes means the slipknot starts closing sooner and the false-positive transient decays faster.\nIPFIX + SPM (or IE315) together are best suited for Service Providers. Enterprises with modest scale, generic collectors, and volumetric-dominant threat models are well served by stateful IPFIX alone. High-scale provider edges facing diverse attack classes run both — IPFIX for universal baseline visibility, SPM feeding the detection tier — and let each architecture do the job it was shaped for.\nIn the earnest interest of brevity, there was quite a bit cut from this article. What was cut is deliberate, and each cut is worthy of a follow-up article. Mitigation mechanics (BGP FlowSpec rule construction, RTBH, and the filter feedback loops that close the slipknot) were held to single sentences here; vendor configuration syntax (SR-OS cflowd and SPM stanzas, template tuning) was omitted entirely; and collector/ingestor deployment — sizing the analytics tier that Section 3.3 hand-waved as \u0026ldquo;horizontally scalable\u0026rdquo; —deserves its own honest treatment.\nReferences # IPFIX protocol and information model\nRFC 7011 — Specification of the IP Flow Information Export (IPFIX) Protocol for the Exchange of Flow Information. Transport, message format, template mechanics, sequence numbers. https://www.rfc-editor.org/rfc/rfc7011 RFC 7012 — Information Model for IP Flow Information Export (IPFIX). IE data types and semantics (the identifier/deltaCounter distinction from 2.2). https://www.rfc-editor.org/rfc/rfc7012 RFC 7013 — Guidelines for Authors and Reviewers of IPFIX Information Elements. How new IEs enter the registry. https://www.rfc-editor.org/rfc/rfc7013 RFC 7014 — Flow Selection Techniques. https://www.rfc-editor.org/rfc/rfc7014 RFC 7015 — Flow Aggregation for the IP Flow Information Export (IPFIX) Protocol. https://www.rfc-editor.org/rfc/rfc7015 Packet sampling (PSAMP)\nRFC 5476 — Packet Sampling (PSAMP) Protocol Specifications. The export side of the Selection stage in 2.1 and 3.1. https://www.rfc-editor.org/rfc/rfc5476 RFC 5477 — Information Model for Packet Sampling Exports. Defines the packet-section IE family, including ipHeaderPacketSection (#313). https://www.rfc-editor.org/rfc/rfc5477 RFC 5475 — Sampling and Filtering Techniques for IP Packet Selection. The statistical basis behind the 1:N lottery in 4.1. https://www.rfc-editor.org/rfc/rfc5475 IE 315 and data-link sections\nRFC 7133 — Information Elements for Data Link Layer Traffic Measurement. Defines dataLinkFrameSection (#315), dataLinkFrameSize (#312), and the L2 anchor semantics that Section 3.2 is built on. https://www.rfc-editor.org/rfc/rfc7133 Registries\nIANA — IP Flow Information Export (IPFIX) Entities. The live registry of IE numbers, types, and semantics referenced throughout. https://www.iana.org/assignments/ipfix/ipfix.xhtml Vendor documentation\nNokia SR OS documentation — cflowd and Deepfield SPM export configuration. [CONFIRM exact guide title, release version, and default section depth before publish.] Nokia Deepfield Defender technical documentation — ingestor-side flow reconstruction and Genome threat intelligence. [CONFIRM public-facing doc availability; some material may be customer-portal only.] Fingerprinting background\nJA3/JA4 TLS fingerprinting methodology — Salesforce\u0026rsquo;s original JA3 specification and the JA4+ suite (FoxIO). [Link the GitHub repositories; verify current canonical URLs at publish time.] ","date":"3 July 2026","externalUrl":null,"permalink":"/posts/ipfix-ie315-spm/","section":"Posts","summary":"IPFIX vs. IE315/SPM: Flow Telemetry Architectures for DDoS Detection # 1. Framing: What DDoS Detection Demands from Telemetry # The Traditional Paradigm: Splitting the Defense # Traditionally, DDoS defense was a game of architectural division. Network operators split attacks into two categories based on how they were most efficiently managed: volumetric floods and application-layer exploits. For Layer 3 and 4 volumetric floods (like UDP amplification / reflection blasts), the primary goal was protecting core bandwidth. Every day the core performance is handicapped by a perpetual barrage of short-term, high frequency attack traffic. The collective effect of these attacks are significant, and can be difficult to effectively/efficiently count. On a particularly bad day, a large flood carried into the core will actually overwhelm interface links between routers. For enterprise this translates to lost availability, while for service providers this could break tier one services like DNS, or simply impact customer experience.\nConsequently, these attacks were detected and policed at the outermost network edge. Operators monitored basic NetFlow metadata from edge routers to spot massive packet-per-second spikes, then utilized high-throughput ACLs or BGP routing redirections to drop or scrub the raw volume before it could enter the core network. Conversely, Layer 7 application attacks required an entirely different philosophy. Because these threats mimic legitimate user traffic (like malicious HTTP GET floods), standard edge routers could not see them. Efficiency demanded moving the defense inline, right at the point of convergence closest to the target application. This allowed an inline Web Application Firewall (WAF) or local application proxy to step in. Because it sat directly in the traffic path, the WAF possessed the cryptographic and processing capacity to decrypt TLS traffic, inspect deep packet headers, analyze cookies, and issue JavaScript challenges to weed out bots from human users.\n","title":"Understanding IPFIX, IE 315 \u0026 SPM: Complementary Telemetry for Modern Networks","type":"posts"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"}]