---
title: 'Proxy Servers and the Jump Server'
source: 'https://academia.sh/en/courses/network-security/proxy-servers-and-jump-server'
course: 'Network Security'
language: en
updated: '2026-09-26T03:02:54+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Separates connection classes into those passing through the checkpoint and those skipping it, and counts them by period volume'
    - 'Separates the skip path that a rule change can close from the one it cannot, and measures the remaining share'
    - "Counts the point's own load, the connections its failure cuts, and the claim it makes provable"
---

# Proxy Servers and the Jump Server

Ten connection classes run across four layouts: once a checkpoint is set up, how many of the period's connections pass through a single point, how many skip the point, how many classes remain once skip paths are closed by a rule change, what the point's own load is and how much path its failure cuts, and which claim becomes provable at the point.

The previous lesson left the management zone as an unresolved item: a single zone written directly into six zones, the one zone segmentation closed no path for. This lesson's move is not to remove that zone but to route the connections leaving it through a single point. The same move also has a reverse direction: connections going from inside to outside can also be gathered at a single point.

The two do different things. The point gathering what goes from inside to outside is the forward proxy; the point gathering what comes in from outside or from the management zone is the jump server. What they share is measurable: both split a connection in two, leave a record in the middle, and become a new item themselves. The reverse proxy's configuration and the information it loses when forwarding to the application were measured in another course; the axis here rests on a single question — how many connections actually pass through that point.

- PD13. The ten connection classes and period counts belong to a fictional regional measurement network. No real connection is established; what is measured is the model built with `node`.
- PD14. The skip reasons were written by hand, and two of them were marked as unclosable by a rule change. In reality which skip can be closed depends on the physical layout of the network.
- PD15. The point's load was counted as twice the connections passing through it: a point carries two connections, a front leg and a back leg. Concurrency and duration were not modeled.
- PD16. The claim the point proves was taken from the previous lessons' claim list. What the proof rests on is outside this course.
- PD17. The number of zones the jump server reaches was read from the previous lesson's management-zone rule count.

## Connection Classes and Layouts

The model holds four things for each connection class: its source, the period's connection count, which checkpoint it naturally belongs to, and, if any, the reason it skips the point. A non-empty skip reason means that class reaches its target by another path even if the point is set up.

```js
// checkpoint.mjs — connection classes and checkpoint layouts; a model, not a real connection
// [name, source, target, period connections, natural checkpoint, skip reason ('' if it does not skip)]
export const CONNECTION = [
  ['branch -> outside interface', 'branch', 'outside', 184000, 'proxy', ''],
  ['application -> package repository', 'application', 'outside', 90, 'proxy', ''],
  ['application -> outside measurement service', 'application', 'outside', 26400, 'proxy', ''],
  ['field terminal -> outside map', 'field', 'outside', 5100, 'proxy', 'edges exit over a cellular connection'],
  ['backup -> outside storage', 'backup', 'outside', 12, 'proxy', 'written directly for transfer volume'],
  ['every machine -> time source', 'all', 'outside', 43200, 'proxy', 'the proxy does not carry this protocol'],
  ['management -> machine shell', 'management', 'inside', 372, 'jump', ''],
  ['management -> management interface', 'management', 'inside', 860, 'jump', ''],
  ['deployment automation -> shell', 'management', 'inside', 1860, 'jump', 'automation connects directly with its own key'],
  ['branch -> shell (emergency path)', 'branch', 'inside', 26, 'jump', 'the emergency rule was never removed'],
];
export const LAYOUT = {                    // which checkpoint is set up and whether skip paths are closed
  none: { point: [], closed: false },
  jump: { point: ['jump'], closed: false },
  both: { point: ['proxy', 'jump'], closed: false },
  'both+closed': { point: ['proxy', 'jump'], closed: true },
};
// Two skips that cannot be closed: the cellular exit and the protocol that cannot be carried do not close with a network rule
const UNCLOSABLE = ['edges exit over a cellular connection', 'the proxy does not carry this protocol'];
export const passes = (b, y) => y.point.includes(b[4]) &&
  (b[5] === '' || (y.closed && !UNCLOSABLE.includes(b[5])));
export const skips = (b, y) => y.point.includes(b[4]) && !passes(b, y);
export const TOTAL = CONNECTION.reduce((a, b) => a + b[3], 0);
export const sum = (l) => l.reduce((a, b) => a + b[3], 0);
// The checkpoint records the connection and authenticates the subject itself
export const PROVEN = ['subject-identity', 'request-path'];
export const POINT_ACCESS = { proxy: 1, jump: 6 };   // number of zones the point can reach directly
```

The four layouts separate along two axes: which points are set up, and whether skip paths were closed by a rule change. Closing does not resolve every skip; two reasons were marked as unclosable. Field endpoints exit over a cellular connection without ever entering the organization's network, so there is no point on the network a written rule could reach them through. The time-source query, in turn, is not a protocol the proxy can carry; if a rule were written, the connection would not form and the job would stop. These two reasons are not a gap, they are a measurement input.

## How Many Connections Actually Pass

```js
// run1.mjs — passing, skipping and never-monitored connections across four layouts
import { CONNECTION, LAYOUT, TOTAL, sum, passes, skips } from './checkpoint.mjs';

console.log(`ten connection classes, ${TOTAL} connections in the period\n`);
const pct = (n) => `${(n * 100 / TOTAL).toFixed(1)}%`;
console.log(`${'layout'.padEnd(13)} ${'passing class'.padStart(14)} ${'passing connections'.padStart(20)} ${'share'.padStart(6)} ` +
  `${'skipping class'.padStart(14)} ${'skipping connections'.padStart(21)} ${'unmonitored'.padStart(11)}`);
for (const [name, y] of Object.entries(LAYOUT)) {
  const g = CONNECTION.filter((b) => passes(b, y)), a = CONNECTION.filter((b) => skips(b, y));
  const u = CONNECTION.filter((b) => !passes(b, y));
  console.log(`${name.padEnd(13)} ${String(g.length).padStart(14)} ${String(sum(g)).padStart(20)} ${pct(sum(g)).padStart(6)} ` +
    `${String(a.length).padStart(14)} ${String(sum(a)).padStart(21)} ${String(sum(u)).padStart(11)}`);
}
const last = LAYOUT['both+closed'];
console.log('\nclasses still skipping with both points set up and skip paths closed:');
for (const b of CONNECTION.filter((x) => skips(x, last)))
  console.log(`  ${b[0].padEnd(30)} ${String(b[3]).padStart(6)}  ${b[5]}`);
console.log('\nclasses closing resolves with a rule change:');
for (const b of CONNECTION.filter((x) => skips(x, LAYOUT.both) && passes(x, last)))
  console.log(`  ${b[0].padEnd(30)} ${String(b[3]).padStart(6)}  ${b[5]}`);
```

```
ten connection classes, 261920 connections in the period

layout         passing class  passing connections  share skipping class  skipping connections unmonitored
none                       0                    0   0.0%              0                     0      261920
jump                       2                 1232   0.5%              2                  1886      260688
both                       5               211722  80.8%              5                 50198       50198
both+closed                8               213620  81.6%              2                 48300       48300

classes still skipping with both points set up and skip paths closed:
  field terminal -> outside map    5100  edges exit over a cellular connection
  every machine -> time source    43200  the proxy does not carry this protocol

classes closing resolves with a rule change:
  backup -> outside storage          12  written directly for transfer volume
  deployment automation -> shell   1860  automation connects directly with its own key
  branch -> shell (emergency path)     26  the emergency rule was never removed
```

The first row is the starting point: with no checkpoint set up, all two hundred sixty-one thousand nine hundred twenty of the period's connections are unmonitored. This row shows zero skipping classes, because there is nothing to skip — on a network with no checkpoint, every path is a direct path. Each of the next three rows shows how much of that number it takes back.

The second row is the measure of the jump server set up alone, and it is surprising: it passes five thousandths of the period. Looking at class count, two of four pass; looking at volume, one thousand two hundred thirty-two connections. One of the two skipping classes is deployment automation, and it alone carries one thousand eight hundred sixty connections — more than every human session passing through the jump server combined. When the jump server is set up, no one is lying — the management team really does pass through it. What does not pass is the automation, and the automation does most of the work.

The third row adds the forward proxy and the share jumps to eighty-one percent. The jump here comes from one class alone carrying seventy percent of the period on its own: the branch network's outbound connection. Eighty-one percent sounds high; the remaining nineteen percent means fifty thousand connections, and none of them is recorded anywhere.

This row has another reading as well. By class count, five of ten pass and five skip: half and half. By volume, eighty-one percent passes. The two ratios come from the same set and do not contradict each other; which unit the measurement is taken in decides the result. Monitoring coverage looks low when reported by class count and high when reported by volume. Neither is enough on its own for a decision: if one of the classes left out of coverage connects rarely but reaches the management shell, its small share of volume does not make it unimportant.

The fourth row closes skip paths with a rule change and the share climbs to eighty-one and a half percent. The payoff for all that effort is 0.8 points. The two lists below separate the reason. The three closed classes carry a volume of one thousand nine hundred connections, and two of them are one-line fixes — an emergency rule opened months ago, a backup flow written directly for volume reasons. The two classes that cannot be closed carry forty-eight thousand three hundred connections, and neither is a rule problem: field endpoints never pass over the network at all, and the proxy cannot carry the time-source query. The checkpoint's coverage is bounded not by the point itself but by the network's physical layout and by the protocol's portability.

The skipping classes share one more trait: none of them is a misconfiguration. All five were born with a reason, and often with a written approval — transfer volume, emergency access needs, automation's own credential, where the endpoints sit, a protocol that cannot be carried. The checkpoint's coverage is therefore not set by the setup decision; it is set by the exceptions that accumulate after setup, and because each exception has its own justification, none of them looks excessive taken one at a time. The only thing that can be measured is the total.

## The Point's Own Load

```js
// run2.mjs — the point's own load, the connections its failure cuts, and the claim it makes provable
import { CONNECTION, LAYOUT, TOTAL, sum, passes, skips, PROVEN, POINT_ACCESS } from './checkpoint.mjs';

const last = LAYOUT['both+closed'];
console.log(`${'point'.padEnd(8)} ${'passing class'.padStart(14)} ${'passing connections'.padStart(20)} ${'point load'.padStart(11)} ` +
  `${'cut on drop'.padStart(15)} ${'zones reached'.padStart(14)}  claim proven`);
for (const n of ['proxy', 'jump']) {
  const g = CONNECTION.filter((b) => b[4] === n && passes(b, last));
  console.log(`${n.padEnd(8)} ${String(g.length).padStart(14)} ${String(sum(g)).padStart(20)} ${String(sum(g) * 2).padStart(11)} ` +
    `${`${g.length} class`.padStart(15)} ${String(POINT_ACCESS[n]).padStart(14)}  ${PROVEN[n === 'proxy' ? 1 : 0]}`);
}
const recorded = CONNECTION.filter((b) => passes(b, last)), unrec = CONNECTION.filter((b) => !passes(b, last));
console.log(`\n${'measure'.padEnd(41)} ${'no point'.padStart(12)} ${'both points set up'.padStart(20)}`);
for (const [name, before, after] of [
  ['connections recorded', 0, sum(recorded)],
  ['connections unrecorded', TOTAL, sum(unrec)],
  ['connections with subject identity proven', 0, sum(recorded.filter((b) => b[4] === 'jump'))],
  ["management's directly reached zones", 6, 1],
  ['connections cut by a single failure', 0, Math.max(...['proxy', 'jump'].map((n) => sum(CONNECTION.filter((b) => b[4] === n && passes(b, last)))))],
]) console.log(`${name.padEnd(41)} ${String(before).padStart(12)} ${String(after).padStart(20)}`);
console.log(`\n${sum(CONNECTION.filter((b) => skips(b, last)))} skipping connections never enter the record; ` +
  `that is ${(sum(unrec) * 100 / TOTAL).toFixed(1)}% of the period`);
```

```
point     passing class  passing connections  point load     cut on drop  zones reached  claim proven
proxy                 4               210502      421004         4 class              1  request-path
jump                  4                 3118        6236         4 class              6  subject-identity

measure                                       no point   both points set up
connections recorded                                 0               213620
connections unrecorded                          261920                48300
connections with subject identity proven             0                 3118
management's directly reached zones                  6                    1
connections cut by a single failure                  0               210502

48300 skipping connections never enter the record; that is 18.4% of the period
```

The upper table puts the two points side by side, and their measures are large in opposite directions. The proxy carries two hundred ten thousand connections and sits under a load of four hundred twenty-one thousand, yet it reaches one zone: the outside zone. The jump server carries three thousand connections, its load is six thousand two hundred thirty-six, and it reaches six zones. Load and value do not sit in the same place. The previous lesson's management-zone row has now come down to a single machine; when that machine fails, four classes are cut, and if it is compromised, six zones are reached. Management's directly reached zones went from six to one — that is the gain, and the same move lined up two hundred five items behind a single machine.

The claim-proven column closes out the previous two lessons. No firewall generation could prove subject identity; the jump server does, because it opens the session itself and authenticates the subject on its own. In return, the proof's scope is three thousand one hundred eighteen connections. Across the rest of the period, subject identity remains unproven.

The bottom table's last two rows give the cost. Before a checkpoint was set up, the number of unrecorded connections was two hundred sixty-one thousand and the connections a single failure would cut was zero; afterward, unrecorded fell to forty-eight thousand and the connections a single failure would cut rose to two hundred ten thousand. The two numbers must be read together: a checkpoint is a visibility gain and an availability debt taken on in the same move. Setting up a second point splits the debt, but it also splits the proof; now there are two separate records and two separate authorized sets on two separate machines.

The point itself is also a new surface, and in two separate ways. First, it becomes an item: the jump server is a machine that reaches six zones, and it carries that access as a rule; the previous lesson's management-zone row is now a single machine's authorized key list. Second, the connection is split in two. The four hundred twenty-one thousand figure in the point-load column is not just a performance line item: for every connection there is now a place in the middle that sees both ends open. Terminating the encrypted flow at this point is the condition for the gain measured in the first lesson, and the same move creates the one place where the flow appears in the open.

That forty-eight thousand connections never enter the record at all is this lesson's open item. These do not arise from misconfiguration but from never passing over the network at all. The question to ask when measuring a checkpoint should not be "is it set up," but "how much of the period actually passed through it" — the answer to the first question is the same in both layouts.

This lesson's items and the previous one's, read together, produce an ordering. Segmentation closes a path, and the path it closes can be counted; a checkpoint does not close a path — it gathers it at a single point, and produces a record at the point it gathers. Neither replaces the other. The management zone's rule written into six zones was not closed by segmentation; the jump server does not close that rule — it lines it up behind a single machine. The number of closed paths did not change, the number of provable claims went up, and a new single point of failure was born. Unless the measurement writes all three columns at once, whether this move is good or bad cannot be said.

## Summary

- The jump server alone passes only 0.5% of the period: 2 of 4 classes pass, and the skipping deployment automation alone carries 1,860 connections — more than every human session combined.
- Adding the forward proxy brings the share to 80.8%; the remaining 19.2% is fifty thousand connections, and none of it enters the record.
- Closing skip paths with a rule change only moves the share to 81.6%: the 3 closed classes carry 1,898 connections, the 2 unclosable classes carry 48,300. The unclosable ones are not a rule problem — field endpoints never pass over the network, and the proxy cannot carry the time-source query.
- Load and value do not sit in the same place: the proxy carries 210,502 connections and reaches 1 zone, the jump server carries 3,118 connections and reaches 6 zones.
- The point makes subject identity provable, but only for 3,118 connections. The cost is two numbers: management's directly reached zones fall from 6 to 1, while the connections a single failure would cut rise from 0 to 210,502.

## Next Step

This lesson's entire gain was gathered into a single record: two hundred thirteen thousand connections are now written somewhere. Being written is not the same as being seen. Keeping a record does not say which class a connection inside that record belongs to; among the period's two hundred sixty thousand lines, which ones are worth looking at has still not been asked. The next lesson's question draws three numbers out of the same set of events: how many events are caught, how many of the caught ones actually have no counterpart, and once the move goes from detection to prevention — that is, once connections start being cut instead of just recorded — how many legitimate connections get cut.
