SkyEye

SkyEye: A Self-Hosted Threat Defense System

George Lorentzos, skyeye.software

Abstract. A purely self-hosted defense layer would allow any application to face the public internet without routing its traffic through a third party. Cloud filtering services offer part of the solution, but the main benefits are lost if every request must first pass through someone else's network. We propose a defense that lives on the server itself. A single binary stands in front of the application, inspects each request before the application hears of it, and bans hostile visitors at first contact. Offenders are remembered, and every return costs them more. The system forms its own record of hostile behavior as long as honest traffic flows through it. It requires no external service, no database and no maintenance, and the traffic never leaves the machine it protects.

1. Introduction

Defense on the internet has come to rely almost exclusively on cloud services acting as trusted intermediaries between applications and the people who use them. While the model works well enough for most deployments, it still suffers from the inherent weaknesses of the trust based model. Every request, every credential and every payload must be disclosed to a third party before it reaches the server it was addressed to. The operator pays for this mediation twice, once in subscription fees that scale with traffic, and once in the surrender of the traffic itself. Small operators are priced toward free tiers whose terms can change, and all operators accept that their availability now depends on someone else's outage calendar.

What is needed is a defense based on inspection instead of mediation, allowing any server to protect itself without a trusted third party. In this paper, we propose a perimeter that runs where the application runs. One self-contained executable owns the public ports, terminates the connections, judges every request against what it knows of attack behavior, and forwards to the application only what survives judgment. The application never hears from a banned visitor, and the visitor learns nothing beyond a closed door.


2. Recognition

The oldest signal on the public internet is a request for a path that no honest visitor would ever ask for. Requests for /wp-login.php on a server that has never run WordPress, for /.env, for backup archives and private keys, announce intent as clearly as any signature. We define a first class of judgment over these paths. The system knows the classic attack paths by name, 264 of them at the time of writing, and a request for any of them is a self-declared offense. There is nothing to tune and no model to train, because the request itself is the evidence.

Attackers rarely present an exploit plainly. They wrap it in layer after layer of encoding, expecting each filter along the way to inspect only the surface. The system therefore peels every layer of encoding, in the path and in the query string alike, and judges what is underneath. The disguise fails in both directions, because a payload that decodes into an attack is an attack, and traffic that hides under many layers of encoding has already explained why it is hiding.


3. Memory

Most servers forgive instantly. An attacker may probe thousands of times from the same address and be greeted each time as a stranger. We propose instead that the perimeter keep a record. A first offense costs the visitor seven days of silence. A second offense costs two weeks, a third a month, and the record of offenses is kept for ninety days, so a scanner that plans to wait out its sentence returns to find a longer one. Writing D(n) for the duration of the nth offense and M for the memory of the record, the schedule is

D(2) ≥ 14 days,   D(n) ≥ 30 days for n ≥ 3,   M = 90 days

whichever rule triggered the ban. Since M exceeds every D(n), a persistent attacker never outlives his own record. The consequence is a hard ceiling on contact. In the steady state one address earns one probe per thirty days, twelve probes per year, against an application that answers honest visitors millions of times in the same period.

The record lives in memory, and this is a design decision rather than a limitation. A ban list that survives restarts accumulates mistakes forever and eventually requires its own administration. A ban list that lives in memory makes a restart the escape hatch for any wrongly issued ban, while the ninety day offense record still makes repeat visits expensive. Addresses the operator trusts are placed on an allowlist in the configuration file, and the allowlist is the one list that does persist, because trust granted by a human should not evaporate with a process.

An attacker with many addresses can spread offenses across them, and IPv6 makes addresses cheap. The system therefore bans IPv6 offenders by prefix rather than by address, so rotating within a subnet changes nothing. A single prefix ban covers 264 addresses, roughly 1.8 × 1019, which is the entire space the attacker's provider handed him in one allocation.


4. Proportion

Volume is the bluntest attack and the easiest to misjudge, because in the age of carrier grade NAT one address is not one person. Hundreds of honest users can share a single address, and a limit sized for one person punishes all of them. Consider an address shared by k users, each producing at most r requests per minute. The volume of the address is bounded by

V ≤ kr

and any limit must sit above this bound with room to spare. The system therefore applies two thresholds. Crossing the first brings a polite refusal, a status code and nothing more, which is the correct answer to an enthusiastic client or a misconfigured retry loop. Crossing the second, set far above any plausible honest volume, brings a ban measured in hours, which is the correct answer to a flood. Writing C for the requests of one address inside the window W, the complete rule is

C ≤ L → allow
L < C ≤ H → refuse
C > H → ban

and the interval between L and H is deliberately wide, because refusal is reversible and punishment is not.


5. Scanners

A scanner walking a wordlist produces a signature no honest population can imitate, a stream of requests for paths that do not exist. A legitimate user behind the same address produces missing paths at a rate near zero, while the scanner produces them at a rate near one per request. The system counts these misses per address inside a short window, holding suspicious looking misses to a stricter threshold than plain ones, and bans the address that crosses either.

A patient scanner can slow its walk until it slips under any short window. For this reason a second, much longer window watches the same signal at low frequency. Writing S and N for the suspicious and total misses of one address inside the short window, and S* for its suspicious misses inside the long window, the address is banned when

S ≥ Ts   or   N ≥ Ta   or   S* ≥ T*

The two populations barely overlap. An honest address misses with some small probability p per request, so its expectation is pkr per window with p near zero, while the scanner's p is near one. The thresholds sit in the gap between them. Patience does not defeat the count, it only defers it, and the ban arrives all the same.


6. The Gateway

A defense that owns the public ports must also do the front door work honestly, or it cannot be deployed at all. The system is therefore a complete gateway. It routes by path prefix in the manner of nginx location blocks, with the longest prefix winning. It balances load across several backends and quietly skips a backend that stops answering. It obtains and renews its own certificates through the ACME protocol [2], so encrypted transport requires two lines of configuration and no ritual. WebSockets and event streams pass through untouched and stay open for hours, and every response streams to the visitor the moment it arrives.

The gateway refuses the jobs that would compromise the design. It does not serve files from disk, cache responses or compress them. A defense layer should hold no content worth stealing and no state worth corrupting.


7. Privacy

The traditional cloud model achieves protection by disclosure. The third party can only filter what it can read, so the operator's traffic, and the traffic of every one of the operator's users, is readable by the intermediary as a condition of service. Our model needs no such bargain. Inspection happens on the same machine that was going to receive the traffic anyway, so no new party learns anything. Nothing is phoned home, nothing is aggregated across customers, and the record of offenders is held in the memory of the operator's own process. The public observes only that the server defends itself.


8. Calculations

We consider the chance that an honest address is banned by the volume rule. With the soft threshold L and the hard threshold H set so that

kr < L < H

an address of k honest users never reaches the soft threshold, and the hard threshold sits further away still. The gap between L and H is the margin of grace, inside which the system refuses requests without punishing the address. An honest population must therefore not merely exceed expectation to be banned, it must exceed the hard threshold, which is sized at a multiple of the soft one. The path rule enjoys a stronger property. Since honest software does not request /.env, the false positive rate of a self-declared offense is effectively zero, which is why a first contact ban is safe there and only there.

The economics favor the defender, and the cost can be made precise. Consider a wordlist of N paths probed through A addresses. Each probe of a restricted path costs its address a ban of at least seven days, so in the long run each address delivers at most one probe per seven days, and the walk cannot finish before

T ≥ 7N / A days

One hundred addresses against ten thousand paths need seven hundred days. Escalation makes it worse for the attacker, because from the third offense each address's period stretches to thirty days and the bound tends toward 30N / A, more than eight years. The scanner's business model assumes ten thousand quiet attempts against a server that forgets each one. Against a perimeter that remembers, the walk across the wordlist does not finish, it retires.


9. Conclusion

We have proposed a system for defending internet applications without relying on trust. We started with the observation that hostile traffic declares itself, through the paths it requests, the encodings it hides under and the volumes it produces, and we built the judgment for these declarations into a single binary that stands where the application stands. The defense keeps a memory of its offenders, escalates against persistence, forgives by restart, and mediates the whole conversation with the outside world while disclosing that conversation to no one. The result is a perimeter with the properties operators had before the cloud asked them to choose, ownership of the door, and knowledge of who knocks.


References

  1. [1]S. Nakamoto, "Bitcoin: A Peer-to-Peer Electronic Cash System", 2008.
  2. [2]R. Barnes, J. Hoffman-Andrews, D. McCarney, J. Kasten, "Automatic Certificate Management Environment (ACME)", RFC 8555, 2019.
  3. [3]J. Weil, V. Kuarsingh, C. Donley, C. Liljenstolpe, M. Azinger, "IANA-Reserved IPv4 Prefix for Shared Address Space", RFC 6598, 2012.
  4. [4]R. Fielding, M. Nottingham, J. Reschke, "HTTP Semantics", RFC 9110, 2022.
  5. [5]OWASP Foundation, "OWASP Top Ten", owasp.org.