---
title: 'Common Network Attacks'
source: 'https://academia.sh/en/courses/wireless-and-security/common-network-attacks'
course: 'Wireless Networks and Network Security'
language: en
updated: '2026-08-17T18:07:21+00:00'
license: 'CC BY-SA 4.0'
---

# Common Network Attacks

When the six controls built in this course are switched on together, the number of flows on which each of four attack classes closes is counted; with the narrow selector none of them closes across all forty flows, with full tunnel only one closes, and denial of service stays open on twenty-two flows.

Six controls were built across the course, and each measured its own boundary in both
directions at once: generation and coverage on the wireless side; segmentation, the rule
chain, detection, the tunnel, and the criterion moving from location to identity on the
security side. One question is left: when these six controls are switched on **together**,
which class of network attacks actually closes, how many classes remain open, and what is
there in hand for the ones that stay open? What is measured is not attack; it is **the
scope of defense**.

## What This Lesson Does Not Do

**How** eavesdropping, spoofing, on-path attack, and denial of service are carried out is
not this course's subject. All four were covered by procedure across eight lessons in the
Network Attacks topic of the Cybersecurity curriculum; procedure, tooling, payload, and
evasion stay there. Here the four names appear only as **class names**, and what stands in
for them is not a procedure but a **condition** — a sentence, read only from the defending
side, that says for which flow the class stays accessible.

| Class | Read from the defending side |
|---|---|
| Eavesdropping | Is the flow's content readable in transit |
| Spoofing | Can the flow's source claim be verified |
| On-path attack | Is content readable **and** the source unverifiable |
| Denial of service | Does the service sit somewhere the flow can reach |

A class is **closed** for a flow if its condition does not hold; it is **open** if the
condition holds.

## A Control Being On Is Not the Same as a Class Closing

The real distinction this measurement carries is this: a control being **set up** is not
the same as a class being **closed for that flow**. The tunnel is set up, but it does not
touch a flow left outside its selector. The identity criterion is set up, but it produces
no decision for a flow with no credential. The generation requirement is in force, but it
has nothing to do with a flow that has no wireless leg. This is why the measurement is
done at the flow level: forty flows and four classes, **160 flow-class pairs**.

The measurement's assumptions:

- **NS64** — The forty flows are produced from the course's shared fixture; the oracle is
  the `policy` function and is **not changed** in this lesson. Two fields are added to
  each flow: `wireless`, saying whether the first leg is on the wireless segment;
  `credential`, saying whether the source claim can be verified. Both come from the
  fixture and preserve the same flow set as the previous lesson's draws.
- **NS65** — Eavesdropping closes if the flow is inside the tunnel selector **and**, if it
  has a wireless leg, the generation requirement is in force; it does not close if either
  leg is uncovered.
- **NS66** — Spoofing closes if the zero-trust criterion is on **and** the flow has a
  credential. On-path attack requires both to close at once.
- **NS67** — Denial of service closes only when the service is unreachable: segmentation
  and the rule chain are both on, and intent already blocks that flow. On a flow that
  stays reachable, this class is open **by definition**.
- **NS68** — The detection system closes no class; this is not a gap in the setup but the
  mechanism's definition, and contributing zero to the measurement is the expected
  result.
- **NS69** — Two tunnel selectors are compared: narrow selector and full tunnel. In the
  coverage-report measurement, the oracle is closure computed at the flow level.
- **NS70** — The set is 160 pairs; the smallest measurable difference is `1/160`. In rows
  read at the flow level, the resolution is `1/40 = 0.025`.

## Measurement

```python
"""The scope of defense: which control closes which class, what stays open.

Part 1 - closure at the flow level, across two tunnel selectors.
Part 2 - the flow-class pairs lost when a control is switched off.
Part 3 - the coverage report's two-way error.
"""
SEED = 20260811
ZONES = ("ext", "dmz", "int", "mgmt")
CLASSES = ("eavesdropping", "spoofing", "on-path attack", "denial of service")
CONTROLS = ("segmentation", "rule chain", "tunnel", "detection", "zero trust",
            "wireless generation")


def generator(seed):
    d = seed % 2147483646 + 1

    def r(n):
        nonlocal d
        d = (d * 48271) % 2147483647
        return d % n
    return r


def flows(count=40, seed=SEED):
    r, out = generator(seed), []
    for i in range(count):
        out.append({"no": i + 1, "source": ZONES[r(4)],
                    "dest": ZONES[r(4)],
                    "port": (80, 443, 22, 3306, 8080)[r(5)]})
    return out


def add_surfaces(flows_list, seed=SEED + 6, env=SEED + 11):
    """Whether the flow has a wireless leg, whether its source claim has a credential."""
    r, o, out = generator(seed), generator(env), []
    for a in flows_list:
        r(9), r(4)      # identity draws; keeps the same flow set
        out.append({**a, "credential": r(8) != 0, "wireless": o(3) == 0})
    return out


def policy(a):
    if a["source"] == "ext":
        return a["dest"] == "dmz" and a["port"] in (80, 443)
    if a["source"] == "dmz":
        return a["dest"] == "int" and a["port"] == 3306
    if a["source"] == "mgmt":
        return True
    return a["dest"] != "mgmt"


def diff(events, intent, device):
    d = {"correct_pass": 0, "correct_block": 0, "false_admit": 0, "false_deny": 0}
    for o in events:
        n, g = intent(o), device(o)
        if n and g:
            d["correct_pass"] += 1
        elif not n and not g:
            d["correct_block"] += 1
        elif g:
            d["false_admit"] += 1
        else:
            d["false_deny"] += 1
    return d


def closure(a, enabled, selector):
    """Which class is closed per flow. Only the defending side is read."""
    eavesdropping = ("tunnel" in enabled and selector(a)
                     and (not a["wireless"] or "wireless generation" in enabled))
    spoofing = "zero trust" in enabled and a["credential"]
    unreachable = ("segmentation" in enabled and "rule chain" in enabled
                   and not policy(a))
    return {"eavesdropping": eavesdropping, "spoofing": spoofing,
            "on-path attack": eavesdropping and spoofing,
            "denial of service": unreachable}


SELECTORS = {"narrow selector": lambda a: a["dest"] in ("int", "dmz"),
             "full tunnel": lambda a: True}
NARROW = SELECTORS["narrow selector"]
ALL = set(CONTROLS)

ak = add_surfaces(flows())
pairs = [(a, s) for a in ak for s in CLASSES]
print(f"flow {len(ak)} | class {len(CLASSES)} | flow-class pair {len(pairs)}"
      f" | with a wireless leg {sum(a['wireless'] for a in ak)} | credentialed "
      f"{sum(a['credential'] for a in ak)} | crossing a zone boundary "
      f"{sum(a['source'] != a['dest'] for a in ak)}")
print()
print(f"{'class':<18s} {'narrow selector':>18s} {'full tunnel':>18s}")
print(f"{'':18s} {'closed':>9s} {'open':>8s} {'closed':>9s} {'open':>8s}")
for s in CLASSES:
    h = []
    for sec in SELECTORS.values():
        k = sum(closure(a, ALL, sec)[s] for a in ak)
        h += [k, len(ak) - k]
    print(f"{s:<18s} {h[0]:9d} {h[1]:8d} {h[2]:9d} {h[3]:8d}")

print()
whole = sum(closure(a, ALL, NARROW)[s] for a, s in pairs)
print(f"{'control switched off':<22s} {'closed pairs':>12s} {'lost':>6s}")
print(f"{'(none)':<22s} {whole:12d} {0:6d}")
for c in CONTROLS:
    n = sum(closure(a, ALL - {c}, NARROW)[s] for a, s in pairs)
    print(f"{c:<22s} {n:12d} {whole - n:6d}")

print()
REPORTS = {"control checklist": lambda a, s: s != "denial of service",
           "boundary only": lambda a, s: closure(a, ALL - {"wireless generation",
                                                            "zero trust"},
                                                  NARROW)[s]}
print(f"{'coverage report':<18s} {'correct':>7s} {'false admit':>12s} "
      f"{'false deny':>12s}")
for name, report in REPORTS.items():
    d = diff(pairs, lambda c: closure(c[0], ALL, NARROW)[c[1]],
             lambda c: report(c[0], c[1]))
    print(f"{name:<18s} {d['correct_pass'] + d['correct_block']:7d} "
          f"{d['false_admit']:12d} {d['false_deny']:12d}")
```

```
flow 40 | class 4 | flow-class pair 160 | with a wireless leg 9 | credentialed 35 | crossing a zone boundary 27

class                 narrow selector        full tunnel
                      closed     open    closed     open
eavesdropping             18       22        40        0
spoofing                  35        5        35        5
on-path attack            16       24        35        5
denial of service         18       22        18       22

control switched off   closed pairs   lost
(none)                           87      0
segmentation                     69     18
rule chain                       69     18
tunnel                           53     34
detection                        87      0
zero trust                       36     51
wireless generation              79      8

coverage report    correct  false admit   false deny
control checklist       91           51           18
boundary only          105            0           55
```

## What Closes and What Does Not

The upper table places the four classes side by side in two tunnel configurations, and
**with the narrow selector, no class closes on all forty of the forty flows.** The best
row is spoofing: **35 closed, 5 open**. Eavesdropping is **18/22**, on-path attack
**16/24**, denial of service **18/22**.

When the tunnel selector covers every destination, eavesdropping becomes **40 closed, 0
open** — **one class closes entirely.** Its cost was measured in the tunnel lesson:
closing a class entirely requires the control to be applied **without exception**, and the
price of that exceptionlessness is paid on the rule side. On-path attack, being an
intersection, is always narrower (**16** and **35**); the two controls need to cover **the
same set of flows**.

Denial of service stays at **18/22** in both columns, and this fixedness is structural:
this class closes only when the service is unreachable, and intent itself passes **22** of
the forty flows. **Reachability is the reason this class cannot be closed**, not a gap in
configuration.

The middle table shows what each control carries. With all six controls on, **87**
flow-class pairs are closed. Switching off zero trust opens **51** pairs; the tunnel,
**34**; segmentation or the rule chain, **18**; wireless generation, **8**. Switching off
detection opens **0** pairs: detection closes no class; it gives visibility along with its
two-way error, and the set it sees is the **27** flows crossing a zone boundary.

## The Two Directions of the Coverage Report

The lower table carries the lesson's central warning. A coverage report that **looks at
the control checklist** — one that says "the tunnel is set up, zero trust is set up,
generation is in force, so three classes are closed" — gives **91 correct, 51 false
admit, 18 false deny**. On fifty-one pairs it calls something closed that is not; on
eighteen pairs it fails to see something that is closed, because it does not account for
denial of service narrowing through the rule chain.

A report counting only the controls **at the boundary** — one that treats generation and
zero trust as another team's job and leaves them out — gives **105 correct, 0 false
admit, 55 false deny**. It has no false admits at all; its entire error comes from
undercounting.

Both reports are wrong, and **their wrongness runs in opposite directions**: one shows
coverage as wider than it is, the other as narrower. **A coverage report that counts only
one direction hides the other.**

## Classes Left Open, and Narrowings

In the narrow-selector configuration, all four classes leave open flows. What is left in
hand must be written next to each of them.

**Eavesdropping — 22 flows open.** What stays open are the flows outside the tunnel
selector. **Narrowing:** widen the selector; at full tunnel, open drops to **0**, and its
cost was measured in the tunnel lesson. On the **9** flows with a wireless leg, coverage
depends on both conditions at once.

**Spoofing — 5 flows open.** What stays open are flows with no credential. **Narrowing:**
widen credential coverage. Dropping an uncredentialed flow to implicit deny grew false
deny; widening coverage is the one move that improves both numbers together.

**On-path attack — 24 flows open.** Being an intersection, the widest opening is here.
**Narrowing:** **align** the two controls' coverage sets; matching the tunnel selector to
credential coverage gains more than widening a single control does.

**Denial of service — 22 flows open, and no configuration closes it.** **Narrowing:** the
surface, with segmentation and the rule chain together, drops from **40** to **22**; the
remaining twenty-two are flows intent passes and that stay reachable because that is the
service's job. What remains of this class's surface narrows **on the capacity side, not
the rule side**, and that side is not this course's subject.

## Summary

- The four classes appear in this lesson only as **class names**; their procedures stay in
  the Network Attacks topic of the Cybersecurity curriculum. Here each class is reduced to
  a condition read from the defending side, and the measurement is done on **160
  flow-class pairs**.
- A control being set up and a class closing are separate things: with the narrow
  selector, spoofing is **35/5**, eavesdropping **18/22**, on-path attack **16/24**,
  denial of service **18/22**, and no class closes on all forty flows at once.
- At full tunnel, only eavesdropping rises to **40/0**; a class closing entirely requires
  the control to be applied without exception, and its cost was measured in the tunnel
  lesson.
- With all six controls on, **87** pairs are closed; zero trust carries **51**, the
  tunnel **34**, segmentation and the rule chain **18**, generation **8**. Detection
  closes **0** pairs, and this is by definition.
- The coverage report's two directions err separately: the report reading the control
  checklist produces **51 false admits**, the report counting only the boundary produces
  **55 false denies**. Denial of service closes under no configuration; the remaining
  **22** flows narrow on the capacity side.

## Course Wrap-Up

The course asked a single question fourteen times: **what is the difference between the
boundary the design intended and what actually crosses it?** Every lesson built one
mechanism, changed one thing, and counted the difference in both directions at once. The
table below collects the boundary each lesson measured and both of its directions; the
numbers come from each lesson's own run.

| Lesson | Boundary Measured | False Admit | False Deny |
|---|---|---|---|
| Physics of Wireless Transmission | cell intent of thirty meters at power 52 | 0 | 4 |
| Access Points and Controllers | location of the decision: standalone → controller | 2 → 0 | 4 → 4 |
| Channel Planning and Coverage | power budget 58 → 40 | 5 → 0 | 1 → 14 |
| Roaming and Band Steering | handover threshold 30 → 14 | 8 → 0 | 0 → 8 |
| Wireless Security Protocols | generation condition 1 → 3 | 5 → 2 | 1 → 20 |
| Short-Range and Wide-Area Wireless | short / local / wide range | 3 / 0 / 1 | 0 / 4 / 2 |
| Mobile Networks | inter-site distance 90 → 30 | 5 → 0 | 1 → 0 |
| Firewall Types | unmirrored / mirrored / stateful / application-aware | 6 / 6 / 0 / 0 | 7 / 4 / 0 / 8 |
| Access Control Lists | narrow 7 / wide 6 / misordered 8 / tightened 7 rules | 0 / 2 / 2 / 0 | 0 / 0 / 0 / 2 |
| Network Segmentation and DMZ | zone graph 2 → 4, narrow / wide derivation | 0 / 6 → 0 / 0 | 22 / 0 → 0 / 0 |
| Intrusion Detection and Prevention | network-based threshold 7 → 9; 19 flows the host-based system never sees | 0 → 5 | 7 → 0 |
| VPN Technologies | tunnel selector: full tunnel → split | 0 → 6 | 0 → 10 |
| Zero Trust Network Model | location criterion stripped → identity criterion | 18 → 1 | 0 → 1 |
| Common Network Attacks | coverage report: control checklist / boundary only | 51 / 0 | 18 / 55 |

The table has a single reading, and it shows up in all fourteen rows: **the two columns do
not move together.** Every adjustment that zeroes one column grows the other. Lower the
power budget and the leak stops while the miss count rises to fourteen; tighten the
generation condition and the leak drops from five to two while the miss count rises to
twenty; narrow the tunnel selector and the unreachable count becomes ten. A control that
counted only one direction would have shown a flawless table in all fourteen of the
fourteen lessons.

The second reading concerns rule count. Seven rules gave 40/40 correct, seven rules gave
38; six rules leaked, eight rules both leaked and shadowed. **Counting rules does not
measure policy** — and stripping a criterion can turn a rule into an implicit allow
without changing the rule count at all. The reason two rows are left blank sits in the
same place: in this course, the source of a number is not a shared definition, it is **the
lesson that ran it**.

This is also where the course leaves off. Fourteen lessons measured how the boundary gets
**written**: which power, which threshold, which rule chain, which criterion, which
selector. None of them asked what happens to the boundary after it is written. A written
boundary sits inside a living system: its load changes, its rules get edited by hand, its
deviation is invisible to anyone, and its two-way error is known only once it is measured.
**Writing the boundary and operating what was written are separate jobs.**

The next course, **Network Operations and Automation**, takes on the second job: how
traffic gets distributed, which measurements the network uses to report its own state, and
which failure modes close when configuration is managed as code. The two columns counted
in this course become, there, a measurement problem: **how is a boundary's two-way error
seen while it is running?**
