Skip to content
academia.sh

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.

Start typing to search.

↑↓ ↵ Esc navigate · open · close