Proof-of-Work-Gate vor jedes Backend. Bots zahlen mit Rechenzeit. Menschen merken kaum etwas.
Drei Instanzen, gleiche Seite dahinter, unterschiedliche Härte. Beim ersten Aufruf löst dein Browser die Challenge, danach proxyt das Gate unsichtbar das Backend (kein Redirect).
Praktisch unsichtbar, aber nicht umsonst. Hält dumme Bots und einfache Scraper ab, ohne dass ein Mensch etwas bemerkt.
Der Werkseinstellung-Modus: Standard-Härte, wie Torwacht ausgeliefert wird. Auf jedem Gerät unmerklich, für Bots schon vierstellig teurer als low.
Spürbar teuer. Für Endpunkte, die wirklich niemand automatisiert abrufen soll. Auf dem Handy einen Moment, für ein Botnetz der Ruin.
Torwacht stellt sich als Reverse Proxy vor deinen Dienst. Jeder Browser bekommt eine kryptografische Aufgabe (SHA-256). Erst die gültige Lösung öffnet das Tor: per HMAC-signiertem Token-Cookie, zustandslos, ohne Datenbank.
Eine Lösung kostet ein Gerät Sekunden. Ein Botnetz mit zehntausend Clients zahlt das Zehntausendfache. Scraping, Credential-Stuffing und Volumen-Angriffe werden ökonomisch absurd.
Difficulty 8–24 (führende Nullbits) per TORWACHT_DIFFICULTY, fein in ×2-Schritten statt groben ×16-Sprüngen, serverseitig erzwungen und HMAC-signiert in der Challenge. Der Client kann sie nicht absenken.
Challenge-, Error- und Impressums-Seiten sind einzeln per Template-Verzeichnis überschreibbar. Eigenes Logo, eigene Texte, eigenes Impressum. Kein Maskottchen, kein Branding-Zwang.
Single-Use-Challenges (IP+UA-gebunden), Replay-Schutz, Rate-Limits auf Challenge- und Verify-Endpunkt, Redirect-Sanitizing, Timing-sichere Vergleiche. govulncheck: keine Befunde.
Eine statische Go-Binary oder docker compose up. Zwei Umgebungsvariablen genügen: Ziel-Backend und Secret. Hell-/Dunkel-Theme folgt dem System des Besuchers.
Alles per Umgebungsvariable. Zwei Pflicht, der Rest optional:
| Variable | Default | Wirkung |
|---|---|---|
| TORWACHT_TARGET | Pflicht | Backend, das geschützt wird (Pflicht) |
| TORWACHT_SECRET | Pflicht | HMAC-Secret für Challenges + Tokens (Pflicht) |
| TORWACHT_LISTEN | :8080 | Listen-Adresse des Gates |
| TORWACHT_DIFFICULTY | 16 | PoW-Härte in Nullbits, 8–24 (Ø 2^n Hashes), serverseitig geclamppt und signiert |
| TORWACHT_TOKEN_TTL | 24h | Gültigkeit des Token-Cookies |
| TORWACHT_RATE_LIMIT | 20 | Challenge-Seiten pro IP pro Minute |
| TORWACHT_VERIFY_RATE_LIMIT | 10 | Verify-Versuche pro IP pro Minute (Brute-Force-Schutz) |
| TORWACHT_CLIENT_IP_HEADER | unset | Autoritativer Client-IP-Header (z.B. X-Real-IP) hinter Front-Ends, die XFF rotieren/anonymisieren |
| TORWACHT_TRUSTED_PROXIES | (alle) | CIDRs, deren X-Forwarded-For honoriert wird |
| TORWACHT_COOKIE_NAME | torwacht_token | Name des Token-Cookies |
| TORWACHT_COOKIE_DOMAIN | unset | Cookie-Domain (z.B. für Subdomain-übergreifende Tokens) |
| TORWACHT_BASE_PATH | /.torwacht | Namespace der Gate-Endpunkte |
| TORWACHT_BYPASS_PATHS | unset | Pfade ohne Gate (z.B. Healthchecks, Webhooks) |
| TORWACHT_SITE_NAME | Torwacht | Name auf der Challenge-Seite |
| TORWACHT_TITLE | auto | Titel der Challenge-Seite |
| TORWACHT_MESSAGE | auto | Eigener Text auf der Challenge-Seite |
| TORWACHT_FOOTER | auto | Fußzeile der Challenge-Seite |
| TORWACHT_IMPRESSUM | unset | URL zum Impressum |
| TORWACHT_TEMPLATE_DIR | unset | Verzeichnis mit eigenen Templates (challenge/error/impressum) |
| TORWACHT_ASSETS_DIR | unset | Verzeichnis mit eigenen Assets (Logo, CSS) |