{item.title}
+{item.body}
+diff --git a/website/app/fail2ban-alternative/page.tsx b/website/app/fail2ban-alternative/page.tsx
new file mode 100644
index 0000000..b84f86a
--- /dev/null
+++ b/website/app/fail2ban-alternative/page.tsx
@@ -0,0 +1,293 @@
+import type { Metadata } from 'next';
+import Link from 'next/link';
+import { ArrowRight, Container, FileSearch, ShieldCheck, Timer } from 'lucide-react';
+import { getSiteUrl } from '@/lib/config';
+import { buildDocsStructuredData, toJsonLd } from '@/lib/structured-data';
+
+const PAGE_PATH = '/fail2ban-alternative';
+
+export const metadata: Metadata = {
+ title: 'Fail2ban Alternative for Containers and Web Attacks',
+ description:
+ 'Looking for a fail2ban alternative? StackdogApp keeps fail2ban-style IP bans for SSH floods and adds shipped detections for web attacks, webshells and PHP2Shell — with Docker container logs discovered automatically.',
+ keywords: [
+ 'fail2ban alternative',
+ 'fail2ban vs',
+ 'fail2ban docker',
+ 'fail2ban containers',
+ 'fail2ban web application',
+ 'StackdogApp'
+ ],
+ alternates: {
+ canonical: PAGE_PATH
+ },
+ openGraph: {
+ title: 'Fail2ban Alternative for Containers and Web Attacks — StackdogApp',
+ description:
+ 'fail2ban-style bans, shipped detections instead of per-error regex, and Docker container logs read like host logs.',
+ url: getSiteUrl() + PAGE_PATH
+ },
+ twitter: {
+ title: 'Fail2ban Alternative for Containers and Web Attacks — StackdogApp',
+ description:
+ 'fail2ban-style bans, shipped detections instead of per-error regex, and Docker container logs read like host logs.'
+ }
+};
+
+const comparisonRows = [
+ [
+ 'Trigger',
+ 'Too many failed logins in a log line — its README describes scanning logs like /var/log/auth.log',
+ 'The same SSH/PAM failures, plus shipped detections: SQL injection probes, path traversal, brute force, webshell access, PHP2Shell attempts'
+ ],
+ [
+ 'Configuration',
+ 'Per error: it reads "any log file of your choosing, for any error you wish" — each one is a jail and a filter you maintain',
+ 'The detections ship with the product. Thresholds are env vars (five offenses in five minutes by default)'
+ ],
+ [
+ 'Log sources',
+ 'Host log files; out of the box sshd and Apache',
+ 'Host logs and Docker container logs, discovered on their own; nginx, Apache and application formats'
+ ],
+ [
+ 'What it correlates',
+ 'One log line at a time',
+ 'Files and requests: a webshell is a file on disk and a request to it — StackdogApp reads both and bans whoever drives the shell'
+ ],
+ [
+ 'Ban mechanics',
+ 'Updates system firewall rules for a configurable time',
+ 'iptables/nftables rules with their own marker, reconciled against the database: a crash strands neither a ban nor a phantom rule. Bans expire and release themselves'
+ ],
+ [
+ 'Safety rails',
+ 'Configured per jail',
+ 'Allowlist, private and local infrastructure never banned, Docker network subnets protected automatically, per-minute cap on new bans'
+ ]
+];
+
+const differences = [
+ {
+ icon: Container,
+ title: 'Containers are first-class',
+ body: 'Your PHP lives in containers, so its logs do too. StackdogApp discovers container logs and reads them like host files — no bind-mounting logs out of containers to satisfy a host-side daemon.'
+ },
+ {
+ icon: FileSearch,
+ title: 'Detections, not regex maintenance',
+ body: 'Every new attack pattern in a fail2ban setup waits for someone to write a filter. StackdogApp ships the patterns — including the PHP2Shell crash step, where the footprint is "in Unknown on line 0", not a payload.'
+ },
+ {
+ icon: Timer,
+ title: 'Unban is part of the design',
+ body: 'Bans expire and release themselves; the firewall and the database are reconciled every pass, so a restart cannot strand a block or leave a stale drop rule behind.'
+ },
+ {
+ icon: ShieldCheck,
+ title: 'One product, not a pile of jails',
+ body: 'SSH floods, web attacks, webshells and PHP version exposure are one pipeline: one alert stream, one ban engine, one place to look when something happened.'
+ }
+];
+
+export default function Fail2BanAlternativePage() {
+ return (
+
+ fail2ban does one pattern well — its own README says so: scan logs, ban IPs with too
+ many failed logins, update firewall rules for a configurable time. StackdogApp keeps
+ that pattern: SSH floods and PAM failures are banned the same way, five offenses in
+ five minutes by default. What changes is everything around it.
+ {item.body}
+ The fail2ban column quotes its own README. Both tools agree on the thing fail2ban
+ writes there itself: firewall rules reduce the rate of attacks, they do not replace
+ good authentication.
+
+ Not a lab benchmark. The ban pipeline runs against real traffic on our own shop:
+ offenses from the detectors, bans with expiry times, tagged DROP rules in the
+ firewall — and every pass reconciles the two so they cannot drift apart. This is what
+ that looked like on the morning of 1 November 2026:
+
+ Eight addresses on the list, eight database blocks — the same eight. That agreement is
+ the reconciliation you can see in the output, and it is the same code path that runs
+ on your box. One deployment is one deployment, though: run it alongside fail2ban for a
+ week before you switch.
+
+ IPv6. fail2ban has matched IPv6 addresses since v0.10; StackdogApp bans IPv4 dotted
+ quads only. If your traffic is v6-heavy, that difference matters.
+
+ Maturity. fail2ban is packaged for most distributions and has run on plain hosts for
+ years. StackdogApp's ban pipeline (tagged iptables/nftables rules, reconciled
+ against its own database every pass) is verified end-to-end in production against
+ real scanners — but it is newer. Run both for a week before you switch.
+
+ Plain SSH on one host. fail2ban does that job and needs nothing else. An
+ "alternative" is for the box that grew containers, web apps and attack
+ patterns no jail reads.
+
+ You outgrew fail2ban. Here is the honest replacement.
+
+ The same bans, minus the filter maintenance
+ {item.title}
+ fail2ban and StackdogApp, compared on what they actually do
+ Verified end-to-end against real scanners
+
+
+ {`$ stackdog firewall list
+Firewall rules (tagged stackdog):
+ -s 103.86.198.162 -j DROP
+ -s 41.242.115.83 -j DROP
+ -s 64.89.163.175 -j DROP
+ …
+Database blocks:
+ 103.86.198.162 until 2026-11-02T16:52:06Z (sniff)
+ 41.242.115.83 until 2026-11-02T16:52:05Z (sniff)
+ 64.89.163.175 until 2026-11-02T16:52:05Z (sniff)
+ …`}
+ Where fail2ban is still the better fit
+
| + {header} + | + ))} +
|---|
| + {cell} + | + ))} +
+ PHP2Shell (CVE-2026-109618, CVE-2026-109619) is two bugs in the PHP interpreter
+ itself, fixed on 22 October 2026 as four releases at once. Paste the output of{' '}
+ php -v below and see whether your build predates them.
+
+ The same entry appears in all four releases, dated 22 October 2026: "avoid state + corruption via bailout". A bailout is the emergency exit PHP takes when a request + hits a fatal error — memory exhaustion is the easy way to force one. Branches older + than 8.2 got no fix. +
+{release}
+fixed
++ It reads only the version string. Debian, Ubuntu and Alpine packages backport fixes + without changing that number, so a "predates the fix" result on a + distribution package means: check your vendor's advisory, not that you are + certainly vulnerable. +
++ It does not patch anything, and it cannot tell whether an attacker has already + succeeded. Upgrading PHP is the fix; everything else buys time. +
+
+ The StackdogApp version check{' '}
+ runs the same comparison for you on every sniff pass — on the host and inside every
+ running container, from package databases and the official images'{' '}
+ PHP_VERSION — and pairs it with a ban layer for clients whose requests
+ trip the crash step.
+