Lesson 01 / 20
Layer Models and Attack Surface
Measuring the network surface in claims: a single meter reading carrying 18 claims across four layers with none of them having proof, five defenses making 11 claims verifiable while leaving 7 open, a defense being unable to see any claim of the layer beneath it, and verification costing 4 extra round trips, 13 key items, 25 manual items, 11 rejected connections, and 6 devices left out.
Published Updated
In this lesson
- Counts the claims network messages carry per layer and measures how many have proof
- Distinguishes the number of claims a defense makes verifiable from the number it leaves open
- Calculates the cost of verification in extra round trips, keys, manual items, and rejected connections
Contents
The previous course counted the machine’s boundary: permission bits, the hypervisor wall, partitioning. The question left open at its close was this — a branch server does not stand alone; every endpoint that connects to it opens a path that passes outside the boundary the operating system draws, and nobody counts those paths. This lesson turns those paths into a countable unit.
The unit is not the connection itself. A cable existing between two machines says nothing on its own; what matters is what the messages crossing that cable say and what the receiver’s belief rests on. Every message on the network carries one or more claims: “the source address is mine,” “this name corresponds to this address,” “this segment belongs to an open session.” This course’s unit of measurement is the number of claims accepted without verification.
The Claim’s Proof
PS1: every message carries a claim; a claim is a proposition the receiver is expected to accept as true. PS2: a claim’s proof is data the receiver can test independently of the sender; a claim with no proof is accepted without verification. PS3: a defense makes verifiable only the claims of its own layer and the layer above it; the claim of the layer beneath it is invisible to it.
“This protocol is insecure” carries no decision. Three numbers carry the decision, and every lesson in this course writes these three throughout: how many claims are accepted without verification, how many the defense makes verifiable and how many still cannot be verified, and what verification costs. Cost is measured in five items: the number of round trips added to the handshake, the ongoing key items to manage, the manually held configuration items, the rejected legitimate connections, and the number of legacy devices left out.
The layers’ responsibilities, header fields, and protocol mechanics were measured in the Network Models and Protocols course; they are not repeated here. Layer is used here only as a counting axis: how many claims each layer carries and how many have proof.
The Eighteen Claims a Reading Carries
The list below is a model: it counts the claims a meter reading carries as it travels from the field to the center in a fictional regional measurement network. There is no real network, no real hostname, and no real public address. Carrying out this count on a real network is both illegal and unprofessional without written authorization and a defined scope.
// networks/claim.mjs — the claims a single meter reading carries from the field to the // center in a fictional regional measurement network (model): there is no real network, no // real hostname, and no real public address. No randomness. // PS1: every message carries a claim; a claim is a proposition the receiver is expected // to accept as true. PS2: a claim's proof is data the receiver can test independently of // the sender; a claim with no proof is accepted without verification. The last column is // which lesson in this topic measures the claim. export const CLAIM = ` link the source hardware address is mine endpoint-registry 03 link this network address belongs to this hardware address endpoint-registry 03 link I am this segment's gateway endpoint-registry 03 link this frame belongs to this segment - - network the packet's source address is mine source-filtering 06 network this network is reached through me - 07 network this fragment is part of this whole - 06 network this control message comes from the network - 06 transport this segment belongs to an open session session-binding 08 transport I opened this session session-binding 06 transport I am closing this session session-binding 07 application this name corresponds to this address signed-name 04 application I am the server assigning addresses - 05 application I am the server at the far end endpoint-verification 07 application I am this field terminal endpoint-verification 02 application this response answers my request endpoint-verification 04 application this reading came from this meter - 08 application this request has not been sent before - 08` .trim().split("\n").map((r) => { const p = r.trim().split(/\s{2,}/); return { layer: p[0], name: p[1], verifier: p[2], lesson: p[3] }; }); // PS3: a defense makes verifiable only the claims of its own layer and the layer above // it; the claim of the layer beneath it is invisible to it. // Cost columns: rtt = round trips added to the handshake; key = ongoing key items to // manage; manual = manually held configuration items; rejected = rejected legitimate // connections; legacy = devices left out. export const DEFENSE = { "endpoint-registry": { layer: "link", rtt: 0, key: 0, manual: 14, rejected: 3, legacy: 0 }, "source-filtering": { layer: "network", rtt: 0, key: 0, manual: 6, rejected: 2, legacy: 0 }, "session-binding": { layer: "transport", rtt: 1, key: 0, manual: 0, rejected: 0, legacy: 2 }, "signed-name": { layer: "application", rtt: 1, key: 4, manual: 2, rejected: 1, legacy: 0 }, "endpoint-verification": { layer: "application", rtt: 2, key: 9, manual: 3, rejected: 5, legacy: 4 }, }; export const LAYER = ["link", "network", "transport", "application"]; export const COST = ["rtt", "key", "manual", "rejected", "legacy"]; export const open = (active) => CLAIM.filter((i) => i.verifier === "-" || !active.includes(i.verifier)).length; export const totalCost = (active) => COST.map((c) => active.reduce((s, d) => s + DEFENSE[d][c], 0));
// networks/count.mjs — claims per layer: how many have proof, how many the defense makes // verifiable, how many still cannot be verified, and what it costs. import { CLAIM, DEFENSE, LAYER, open, totalCost } from "./claim.mjs"; const write = (g, ...s) => console.log(s.map((v, i) => (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join("")); const all = Object.keys(DEFENSE); console.log(`${CLAIM.length} claims, ${LAYER.length} layers, ${all.length} defenses; ` + `claims with proof ${CLAIM.length - open([])}, accepted without verification ${open([])}`); const A = [-13, 8, 9, 14, 13]; console.log("\n1. claims per layer and claims with proof"); write(A, "layer", "claims", "proof", "verifiable", "undefended"); for (const l of LAYER) { const s = CLAIM.filter((i) => i.layer === l); write(A, l, s.length, 0, s.filter((i) => i.verifier !== "-").length, s.filter((i) => i.verifier === "-").length); } const B = [-23, -13, 12, 11, 8, 9, 8, 10]; console.log("\n2. each defense open on its own"); write(B, "defense", "layer", "verified", "remaining", "rtt", "key", "manual", "rejected"); for (const d of all) { const s = DEFENSE[d]; write(B, d, s.layer, CLAIM.filter((i) => i.verifier === d).length, open([d]), s.rtt, s.key, s.manual, s.rejected); } const C = [-23, 12, 11, 8, 9, 8, 10, 8]; console.log("\n3. if defenses are added bottom to top (cumulative)"); write(C, "added", "verified", "remaining", "rtt", "key", "manual", "rejected", "legacy"); const active = []; write(C, "none", 0, open([]), 0, 0, 0, 0, 0); for (const d of all) { active.push(d); write(C, d, CLAIM.length - open(active), open(active), ...totalCost(active)); } const D = [-45, -13, 8]; console.log("\n4. claims that stay unverified with every defense open"); write(D, "claim", "layer", "lesson"); for (const i of CLAIM.filter((x) => x.verifier === "-")) write(D, i.name, i.layer, i.lesson); const E = [-23, 8, 13, 13, 13]; console.log("\n5. how many claims of the layers beneath it a defense sees"); write(E, "defense", "below", "verifies", "open below", "open above"); for (const d of all) { const limit = LAYER.indexOf(DEFENSE[d].layer); const a = CLAIM.filter((i) => LAYER.indexOf(i.layer) < limit); const u = CLAIM.filter((i) => LAYER.indexOf(i.layer) >= limit); write(E, d, a.length, CLAIM.filter((i) => i.verifier === d).length, a.filter((i) => i.verifier !== d).length, u.filter((i) => i.verifier !== d).length); }
18 claims, 4 layers, 5 defenses; claims with proof 0, accepted without verification 18 1. claims per layer and claims with proof layer claims proof verifiable undefended link 4 0 3 1 network 4 0 1 3 transport 3 0 3 0 application 7 0 4 3 2. each defense open on its own defense layer verified remaining rtt key manual rejected endpoint-registry link 3 15 0 0 14 3 source-filtering network 1 17 0 0 6 2 session-binding transport 3 15 1 0 0 0 signed-name application 1 17 1 4 2 1 endpoint-verification application 3 15 2 9 3 5 3. if defenses are added bottom to top (cumulative) added verified remaining rtt key manual rejected legacy none 0 18 0 0 0 0 0 endpoint-registry 3 15 0 0 14 3 0 source-filtering 4 14 0 0 20 5 0 session-binding 7 11 1 0 20 5 2 signed-name 8 10 2 4 22 6 2 endpoint-verification 11 7 4 13 25 11 6 4. claims that stay unverified with every defense open claim layer lesson this frame belongs to this segment link - this network is reached through me network 07 this fragment is part of this whole network 06 this control message comes from the network network 06 I am the server assigning addresses application 05 this reading came from this meter application 08 this request has not been sent before application 08 5. how many claims of the layers beneath it a defense sees defense below verifies open below open above endpoint-registry 0 3 0 15 source-filtering 4 1 4 13 session-binding 8 3 8 7 signed-name 11 1 11 6 endpoint-verification 11 3 11 4
The numbers belong to the measurement class; their inputs are PS1–PS3.
Eighteen Claims, Zero Proof
The opening line is this course’s starting point: none of the eighteen claims has any proof. With no defense open, the receiver counts all eighteen propositions as true solely because the sender said so. This is not a defect; most of the protocols being counted were designed for an environment in which parties on the network do not intend to harm each other, and verification is not part of that design.
The first table gives the distribution. The application layer is the heaviest with seven claims, because a reading’s meaning is established there: who sent it, which meter it came from, which name it corresponds to. The link layer carries four, the network layer four, the transport layer three claims. Three of the network layer’s four claims cannot be tied to any defense; the transport layer ties all three of its claims. This difference between the two layers determines in advance where the defense budget goes.
The reason the transport layer can tie all three at once is that all three claims rest on the same proof: a binding the two parties agree on when a session opens and that can be tested on every following message. The network layer’s three open claims, on the other hand, each require a separate proof, and none of them can be carried inside the message itself — which path a packet took cannot be derived from the data in the receiver’s hand. Whether the claims of a layer can be reduced to a single proof is the property that actually determines that layer’s defense cost.
What a Defense Cannot See
The second table opens each defense on its own. Endpoint verification, the most expensive defense, verifies three claims and leaves fifteen open; endpoint registry, one of the cheapest, also verifies three claims and leaves the same fifteen. On its own, no defense closes more than a sixth of the claims.
The fifth table shows why, and turns PS3 into a number. Endpoint verification is at the application layer; there are eleven claims beneath it, and all eleven stay open to it. Signed name resolution has the same number: eleven. Session binding does not see eight of its eight claims beneath it. In every row, the number of claims a defense closes at a layer beneath it is zero.
This is the measure of why a secure application-layer connection says nothing about the state of the network underneath it. With endpoint verification open, who the far end is gets verified; which address was used to reach that endpoint, which hardware address that address resolves to, and which network the packet crossed are not verified. These are separate claims and require separate defenses.
The Cost of Verification
The third table opens the five defenses cumulatively, bottom to top. The number of verified claims progresses 0, 3, 4, 7, 8, 11; the remainder drops from 18 to 7. Cost accumulates along the same rows: four extra round trips, thirteen key items, twenty-five manually held configuration items, eleven rejected legitimate connections, and six legacy devices left out.
The shape of the cost changes from defense to defense, and this difference determines the management burden. Endpoint registry needs no extra round trip and no key at all, but on its own it brings fourteen manual items: one record per endpoint. Endpoint verification, on the other hand, holds only three manual items but adds nine key items and two extra round trips. The first defense’s cost is written to a person, the second’s to every connection. Fourteen manual items grow linearly as the network grows and a forgotten item leaves it silently open; two extra round trips do not grow with the network — they stay the same on every connection.
The source-filtering row sits at the opposite end: it verifies a single claim and costs six manual items and two rejected connections. The cost per verified claim is the worst ratio in the table. And yet that single claim — that the source address really belongs to the sender — is the input to all of the capacity arithmetic measured in the sixth lesson. The number of claims verified is not, on its own, a ranking criterion; which claim is verified comes before the count.
Seven Claims Stay Open
The fourth table is this lesson’s most important result. With all five defenses open, seven claims still cannot be verified. These are not the result of weak configuration; they fall outside the scope of every defense counted here. Three are at the network layer, three at the application layer, one at the link layer.
Six of the seven are measured one by one across the rest of this topic. Who the server assigning addresses is is counted in the fifth lesson, who the path runs through in the seventh, fragmentation and the control message in the sixth, the reading’s source and the request’s freshness in the eighth. Only one — which segment a frame belongs to — is not measured in this topic, because its answer lies not in the protocol but in the boundary the network is drawn along.
These seven rows are also this topic’s map. Each of the next seven lessons takes one or more of these rows, runs them against its own message set, and writes the same three columns. The count starts at eighteen and, in each lesson, changes only for the claims that lesson takes up.
Summary
- The network surface’s unit of measurement is the number of claims accepted without verification: a meter reading carries 18 claims across four layers, and with no defense open, the number of them with proof is zero.
- The distribution is not even: the application layer carries 7, the link and network layers 4 each, the transport layer 3 claims; 3 of the network layer’s 4 claims cannot be tied to any defense.
- No defense on its own verifies more than three claims; both the most expensive and the cheapest defense leave 15 claims open.
- A defense verifies none of the claims of the layers beneath it: in all five defenses, the number of claims closed at a layer beneath it is zero.
- The five defenses together verify 11 claims, leave 7 open, and cost 4 extra round trips, 13 key items, 25 manual items, 11 rejected connections, and 6 devices left out.
Next Step
This lesson counted claims across a reading’s journey — that is, it measured the moment the network speaks. But an endpoint does something before anyone ever sends it anything: it listens. An open port is a notice even if no message ever crosses it; it says the service at that endpoint is ready to accept a certain class of claim. Seven open endpoints mean seven separate acceptances waiting, and how many of them actually have work to do on that machine is a separate count. The next lesson counts a service inventory through that lens: which port accepts which claim, how many services are never used, and how many claims closing the unused ones eliminates.
To keep your progress and take notes, Log in
My notes
Log in to take notes.