tlk-sentinel

SSH · nginx · Next.js middleware · reputation · behavioural scoring · live panel

Detect. Ban. Explain.

Most small fleets run fail2ban for SSH, nothing for the application, and hear about an incident from a customer. tlk-sentinel reads your server logs and runs inside your app, so a scanner probing /.env and the same IP hammering your login are one story, not two.

live · simulated traffic

    The community build watches, scores and reports. It never bans.

    It runs the public profile, and the firewall responder starts in dry-run, so a fresh clone touches nothing on your host until you turn both on deliberately. Watch it for a day, confirm the decisions look right, then set TLK_FW_DRYRUN=0.

    01 — Try to sneak one past it

    Encoded twice? Decoded twice.

    Requests are decoded (percent, double-percent and +) before matching, so a payload wrapped in %25 is caught exactly like its plain form. This box runs the same decoder and the same public nginx and web rules, in your browser.

      02 — One agent

      • auth.log
      • access.log
      • Next.js middleware
      • files (sha256)
      enginerules · reputation · anomaly
      • nft / ipsetban, escalating on repeat
      • SQLitequeryable event history
      • live panelSSE dashboard, one-click unban
      • Discordan embed per threat

      03 — What it catches

      SSH

      Brute force, invalid users, root logins

      Threshold windows per IP.

      HTTP

      SQLi, XSS, traversal, probing, floods

      Regex rules on normalized requests: .env, wp-admin, phpmyadmin and friends.

      Tooling

      sqlmap, nikto, nuclei, gobuster, masscan

      User-Agent signatures.

      Unknown attacks

      Scans that match no signature

      A behavioural score from request rate, path diversity, User-Agent churn and the 4xx ratio.

      Known-bad sources

      Tor exits, abusive networks

      Offline CIDR reputation escalates the threat to critical.

      Tampering

      .env, configs, binaries

      A sha256 baseline, re-checked on a timer.

      04 — Two builds, one codebase

      Not a fork. A JSON profile.

      public · community

      Mode
      monitor, reports only
      Auto-ban
      off
      Private rules
      not loaded
      Honeypot, active defense
      off
      Alerts
      stdout

      self · internal

      Mode
      enforce, bans
      Auto-ban
      on, ×4 on repeat offenders
      Private rules
      loaded
      Honeypot, active defense
      on
      Alerts
      stdout + Discord

      npm run dist:public strips the internal profile, private rules and signing key, scans the output for secrets and asserts the public default is still passive. If any check fails the build is rejected, so an enforcing default can never reach a release by accident.

      05 — Live panel

      What happened, on one screen.

      Bound to 127.0.0.1:8787. On any other interface it refuses to bind without TLK_PANEL_TOKEN, and says so. Every write endpoint validates its input: an IP that is not an IP never reaches nft.

      tlk-sentinel dashboard: live threat feed, severity split and ban list

      06 — Inside your app

      The same engine, as middleware.

      Verdicts carry hardened response headers (nosniff, DENY, HSTS, a locked-down Permissions-Policy), so you can apply them to allowed responses as well.

      import { WebGuard } from "@tlk-sentinel/web";
      
      const guard = new WebGuard({
        profilePath: "profiles/public.json",
        rulesPublicDir: "rules/public",
        trustedProxy: true,
      });
      
      export async function middleware(request: Request) {
        const verdict = await guard.inspect(request, { trustProxy: true });
        if (verdict.action === "block") {
          return new Response("blocked", { status: verdict.status, headers: verdict.headers });
        }
      }
      60tests, Node’s built-in runner, no framework
      0runtime dependencies
      3encodings with their own bypass regression tests

      Ban thresholds and escalation, profile gating, reputation and country tables, anomaly cooldown, log tailing across truncation and logrotate, integrity baselines, the SQLite store and firewall input validation. Four integration tests boot the real agent against a live log file. Two more assert that a build with the attribution removed fails its signature check and refuses to enforce. CI runs on Linux and Windows, Node 22 and 24.

      07 — Install

      Node 22.5+. Nothing else.

      The built-in SQLite is why the version matters. Read the threat model before deploying: what it does not catch, and the four ways the tool itself can be turned against you.

      git clone https://github.com/Talkdedsec/tlk-sentinel /opt/tlk-sentinel
      cd /opt/tlk-sentinel
      npm install
      npm run build
      cp .env.example .env
      npm run agent
      sudo cp deploy/tlk-sentinel.service /etc/systemd/system/
      sudo systemctl enable --now tlk-sentinel

      08 — Licence, the short version

      • Run it on your own machines, including your company’s
      • Run it commercially for your own business
      • Read and modify the source for your own installation
      • Send a patch or a vulnerability report with code in it
      • Redistribute, publish or mirror it
      • Sell it, rent it, or ship it inside a paid product
      • Host it as a service for someone else
      • Strip the attribution or the licence text

      The LICENSE governs; this is a summary. Anything in the right-hand column can be bought: talkdedsec@proton.me