---
title: 'Common Ports and Services'
source: 'https://academia.sh/en/courses/network-security/common-ports-and-services'
course: 'Network Security'
language: en
updated: '2026-10-21T05:02:57+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Defines an open port as notice that a class of claim is ready to be accepted'
    - 'Measures accept point counts, unused services, and zone access in a service inventory'
    - 'Calculates the cost of narrowing the surface in terms of cut periodic flow and excluded devices'
---

# Common Ports and Services

Measuring open services in claims: 20 services opening 49 accept points across 6 hosts, 21 accept points resting on no proof at all, 4 externally reachable services receiving not one legitimate request in 30 days, closing unused services and narrowing access cutting accept points to 27 while breaking 4 periodic flows, and verifying the last 7 accept points excluding 240 devices.

The previous lesson counted claims at the moment the network spoke: a reading traveling
from the field to the center carries eighteen claims, and with no defense in place none of
them had proof. Yet an endpoint does something before anyone ever sends it anything. It
listens.

Listening is not a passive act. An open port is a notice even if no message ever crosses
it: it says the service at that point is ready to accept a certain class of claim. A remote
shell service is ready to accept the claim "I am this user"; a measurement intake endpoint is
ready to accept the claim "this reading came from this meter." This lesson counts a service
inventory through that lens.

## An Open Point Is Notice of Acceptance

**PS4:** an open port announces, even if no message ever crosses it, that the service at
that point is ready to accept a specific class of claim. **PS5:** the size of the surface is
not the number of services but the number of **accept points**; an accept point is a pair of
one service and one zone that can reach that service. **PS6:** whether a service is used is
knowable only within an observation window; periodic use falling outside the window reads as
"never used."

PS5 is the item that separates this lesson's measure from a service count. The same service
open on two hosts is two items, but if one is reachable only from the center and the other
from all four of four zones, their contributions to the surface are not equal. Port
numbering, the distinction between a listening socket and a connected socket, and number
ranges were measured in the **Network Models and Protocols** course; they are not repeated
here. The only question here is which claim each open point accepts and on what proof.

The inventory below is a **model**: it counts the services of a fictional regional measurement
network; there is no real hostname or real public address. Producing such an inventory
outside one's own network — testing remotely which point is open — **is both illegal and
unprofessional without written authorization and a defined scope**.

```js
// networks/inventory.mjs — the service inventory of a fictional regional measurement network
// (model): there is no real network, no real hostname, and no real public address. No randomness.

// PS4: an open port is notice even if no message ever crosses it; it says the service at
// that point is ready to accept a specific class of claim.
// PS5: accept point = (service, zone that can reach it) pair; the size of the surface is
// not the number of services but the number of accept points.
// Columns: host, port, service class, verifier, 30-day legitimate requests, reachable
// zones, zones that sent requests in the last 30 days, zones that use it periodically,
// count of legacy devices sending requests that cannot verify (if these devices are
// excluded, the service's entire 30-day request volume stops).
// Zones: e = external network, f = field, b = branch, c = center.
export const SERVICE = `
  branch-gateway  22    remote-shell          client-proof      268     b,c      c      b  0
  branch-gateway  23    legacy-remote-shell   password          0       b,c      -      -  0
  branch-gateway  161   device-monitoring     community-string  9240    b,c      c      -  8
  branch-gateway  8080  management-interface  password          140     b,c      c      -  0
  collector       22    remote-shell          client-proof      412     f,b,c    b,c    f  0
  collector       1883  measurement-ingest   none              89400   e,f,b,c  f,b    -  220
  collector       9100  measurement-export   none              8640    b,c      c      -  0
  collector       514   log-collection        none              43200   f,b,c    b,c    -  14
  verifier        22    remote-shell          client-proof      190     b,c      c      -  0
  verifier        443   internal-service      token             61300   b,c      b,c    -  0
  verifier        5432  database-listener     password          0       b,c      -      c  0
  billing         443   internal-service      token             22800   b,c      b,c    -  0
  billing         80    unencrypted-web       none              1150    e,b,c    b      -  0
  billing         5432  database-listener     password          47600   b,c      c      -  0
  billing         21    legacy-file-transfer  password          36      e,b,c    c      -  0
  name-server     53    name-resolution       none              128400  e,f,b,c  f,b,c  -  0
  name-server     123   time-sync             none              34600   f,b,c    f,b,c  -  6
  directory       389   directory-query       password          19700   b,c      b,c    -  0
  directory       445   file-sharing          password          3300    b,c      b      c  0
  directory       631   printer-service       none              0       b,c      -      -  0`
  .trim().split("\n").map((r) => {
    const p = r.trim().split(/\s+/);
    const set = (x) => (x === "-" ? [] : x.split(","));
    return { host: p[0], port: +p[1], service: p[2], verifier: p[3], requests: +p[4],
      reach: set(p[5]), used: set(p[6]), periodic: set(p[7]), legacy: +p[8] };
  });

export const HOST = [...new Set(SERVICE.map((s) => s.host))];
export const points = (l) => l.reduce((t, s) => t + s.reach.length, 0);
export const openPoints = (l) =>
  l.filter((s) => s.verifier === "none").reduce((t, s) => t + s.reach.length, 0);
```

```js
// networks/surface.mjs — how many claim accept points an open service opens, how many are
// never used at all, what narrowing and adding verification cost.
import { SERVICE, HOST, points, openPoints } from "./inventory.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 ZONE = ["e", "f", "b", "c"];
const empty = SERVICE.filter((s) => s.requests === 0);

console.log(`${SERVICE.length} services, ${HOST.length} hosts, ${ZONE.length} zones; ` +
  `accept points ${points(SERVICE)}, unverified accept points ${openPoints(SERVICE)}, ` +
  `services with no requests in 30 days ${empty.length}`);

const A = [-16, 9, 15, 14, 10, 14];
console.log("\n1. per host");
write(A, "host", "service", "unverified", "unused", "accept", "30d requests");
for (const h of HOST) {
  const l = SERVICE.filter((s) => s.host === h);
  write(A, h, l.length, l.filter((s) => s.verifier === "none").length,
    l.filter((s) => s.requests === 0).length, points(l),
    l.reduce((t, s) => t + s.requests, 0));
}

const B = [-18, 9, 9, 14];
console.log("\n2. the proof the accepted claim rests on");
write(B, "verifier", "service", "accept", "30d requests");
for (const d of [...new Set(SERVICE.map((s) => s.verifier))]) {
  const l = SERVICE.filter((s) => s.verifier === d);
  write(B, d, l.length, points(l), l.reduce((t, s) => t + s.requests, 0));
}

const C = [-48, 8, 14, 18, 14, 10];
console.log("\n3. steps to narrow the surface (cumulative)");
write(C, "step", "accept", "unverified", "stopped requests", "cut flow", "excluded");
let remaining = SERVICE, cut = 0, stopped = 0, excluded = 0;
const row = (name) => write(C, name, points(remaining), openPoints(remaining), stopped, cut, excluded);
row("none");
cut += empty.reduce((t, s) => t + s.periodic.length, 0);
remaining = remaining.filter((s) => s.requests > 0);
row("close never-used services");
cut += remaining.reduce((t, s) => t + s.periodic.filter((z) => !s.used.includes(z)).length, 0);
remaining = remaining.map((s) => ({ ...s, reach: s.used }));
row("narrow access to zones that use it");
const verify = (sel) => {
  const l = remaining.filter((s) => s.verifier === "none" && sel(s));
  excluded += l.reduce((t, s) => t + s.legacy, 0);
  stopped += l.filter((s) => s.legacy > 0).reduce((t, s) => t + s.requests, 0);
  remaining = remaining.map((s) => (l.includes(s) ? { ...s, verifier: "added" } : s));
};
verify((s) => s.legacy === 0);
row("add verification where no legacy device exists");
verify(() => true);
row("add verification to the rest");

const D = [-14, -20, 8, 14, 16];
console.log("\n4. services still unverified after narrowing");
write(D, "host", "service", "accept", "30d requests", "legacy devices");
for (const s of SERVICE.filter((x) => x.verifier === "none" && x.requests > 0 && x.legacy > 0))
  write(D, s.host, s.service, s.used.length, s.requests, s.legacy);

const E = [-8, 11, 12, 14, 14];
console.log("\n5. reachable and used services per zone");
write(E, "zone", "reachable", "used", "unused", "unverified");
for (const z of ZONE) {
  const r = SERVICE.filter((s) => s.reach.includes(z));
  const u = SERVICE.filter((s) => s.used.includes(z));
  write(E, z, r.length, u.length, r.length - u.length,
    r.filter((s) => s.verifier === "none").length);
}
```

```
20 services, 6 hosts, 4 zones; accept points 49, unverified accept points 21, services with no requests in 30 days 3

1. per host
host              service     unverified        unused    accept  30d requests
branch-gateway          4              0             1         8          9648
collector               4              3             0        12        141652
verifier                3              0             1         6         61490
billing                 4              1             0        10         71586
name-server             2              2             0         7        163000
directory               3              1             1         6         23000

2. the proof the accepted claim rests on
verifier            service   accept  30d requests
client-proof              3        7           870
password                  7       15         70776
community-string          1        2          9240
none                      7       21        305390
token                     2        4         84100

3. steps to narrow the surface (cumulative)
step                                              accept    unverified  stopped requests      cut flow  excluded
none                                                  49            21                 0             0         0
close never-used services                             43            19                 0             1         0
narrow access to zones that use it                    27            12                 0             4         0
add verification where no legacy device exists        27             7                 0             4         0
add verification to the rest                          27             0            167200             4       240

4. services still unverified after narrowing
host          service               accept  30d requests  legacy devices
collector     measurement-ingest         2         89400             220
collector     log-collection             2         43200              14
name-server   time-sync                  3         34600               6

5. reachable and used services per zone
zone      reachable        used        unused    unverified
e                 4           0             4             3
f                 5           3             2             4
b                20          10            10             7
c                20          14             6             7
```
The numbers belong to the **measurement** class; their inputs are PS4–PS6.

## Forty-Nine Accept Points

Twenty services open **49 accept points** across six hosts. That is two and a half times the
service count, and the reason for the gap is access breadth: most services in the inventory
are reachable from two zones, and some from all four. **Twenty-one** of the forty-nine points
rest on no proof at all.

The second table separates services by what their proof rests on. Seven services perform no
verification at all, and with 21 accept points they are the largest group in the inventory;
the same seven services carry 305,390 of the thirty-day request volume — the largest share.
Seven services open 15 accept points with a password. Three services require client proof
and open only 7 accept points; the request volume they carry is 870. **The most tightly
verified services are the ones carrying the least work**; where verification is entirely
absent, the whole of the work flows. This inverse relationship is no coincidence: adding
verification requires changing every client that uses that service, and the most-used
service is the most expensive change.

The first table shows where the load collects. The collector performs no verification on
three of its four services and opens 12 accept points on its own. The name server performs
no verification on either of its two services and, with 163,000 requests, is the busiest
host in the inventory. The branch gateway, by contrast, requires proof on all four of its
four services.

Service count per host is also not a stand-in for the surface. The branch gateway and
billing each carry four services, but one opens 8 accept points and the other 10; the
directory opens 6 points with three services while the verifier also opens 6 points with
three services, yet their unverified point counts differ. **Host count, service count, and
accept point count are three separate quantities, and only the third feeds a narrowing
decision.**

## What Thirty Days Does Not Show

The fifth table reads per zone and produces this lesson's most striking line: **four
services are reachable from the external network, yet none of those four services received a
single legitimate request from the external network in thirty days**. Three of the four have
no verification. These four items are an accept surface that does no work in return, while
standing fully open to the external network.

A similar gap exists in the field zone: five services are reachable, three are used. The
branch zone uses ten of twenty services, the center fourteen. The gap between reachable and
used exists in every zone, and its total is close to half the surface.

Three services received no requests at all in thirty days. This is where PS6 comes into play
and measures the window's lie: one of these three services — the database listener on the
verifier — is used **periodically** by the center and did not fall inside the thirty-day
window. Closing it based on usage data cuts a flow that is actually working on this item.

## The Four Steps of Narrowing

The third table narrows the surface step by step and records the cost of each step. Closing
the three never-used services drops the accept point count from 49 to 43, stops no requests,
and cuts **one periodic flow**. Narrowing access to the zones that actually use it gives the
biggest gain: it falls from 43 to **27**, again stopping no requests, but the number of cut
periodic flows rises to four. Together, the first two steps close 44.9% of the surface while
spending zero of the thirty-day request volume.

What the four cut flows have in common is that none of them appeared in the thirty-day
window: the remote shell connecting to the branch gateway from the branch, the remote shell
connecting to the collector from the field, the access from the center to the file sharing on
the directory, and the closed database listener. All four are legitimate, and all four would
have shown up had the observation window been longer. **The cost of every narrowing based on
usage data is a function of window length.** A thirty-day window catches monthly jobs; it
does not catch quarterly closing jobs. Lengthening the window reduces the cut flow, but it
also reduces the number of items that can be closed.

## Seven Points That Cannot Be Verified

The last two steps try to close the remaining unverified accept points and do not change the
accept point count at all — it stays at 27. What changes is the unverified point count, which
falls from 12 to 7 and then to 0. Accept points and unverified accept points are **two
separate numbers**: if a service is not closed, it is on the surface; if it is verified, it
is only no longer without proof.

The fourth table shows the cost of the last step. Devices that cannot verify are sending
requests to all three of the three services that remain unverified: 220 devices to the
measurement intake, 14 to log collection, 6 to time sync. Adding verification excludes these
**240 devices** and stops the entirety of the three services' 167,200 thirty-day requests.
The measurement intake is the network's actual work, and it is the single largest item that
cannot be verified.

This is where defense falls short. The first three steps are free or nearly free; the last
step is equivalent to shutting down the service that carries the most work in the inventory.
Seven unverified accept points are the result not of a wrong configuration decision but of
endpoint devices being unable to produce proof.

## Summary

- An open port is notice that a class of claim is ready to be accepted; the size of the
  surface is not the number of services but the number of service–reachable-zone pairs.
- The 20 services in the inventory open **49 accept points** across 6 hosts; **21** of them
  rest on no proof at all, and the same 21 points carry the largest share of the thirty-day
  request volume.
- 4 services are reachable from the external network, and none of the four received a single
  legitimate request from the external network in thirty days; three have no verification.
- Closing unused services and narrowing access to the zones that use it drops the accept
  point count from 49 to 27, stops no requests, but cuts **4 periodic flows** that fall
  outside the window.
- Adding verification to the remaining 7 unverified accept points excludes 240 devices and
  stops 167,200 requests; these services are unverifiable not because they are misconfigured
  but because their endpoints cannot produce proof.

## Next Step

This lesson assumed a service is **reachable**: every row in the inventory was written by
accepting that a packet can reach a host from a zone. But even two machines on the same
segment reaching each other rests on a claim. An endpoint knows its target's network address
but not which hardware address to send the frame to; it asks, and it writes the first reply
into its cache **without demanding any proof**. The next lesson builds that cache as a data
structure and counts it: how many records an unverified reply corrupts, how many a
consistency check catches, how many a pinned record rescues, and what the manual-management
cost of that is.
