IPScanner

Integrationen

Forward Auth für nginx, Apache und HAProxy

Ein kleiner Container, den nginx, Nginx Proxy Manager, Apache, HAProxy, Traefik oder Caddy zu jeder Anfrage befragt.

Installation

  1. 1Legen Sie eine Forward-Auth-Website im Dashboard an und kopieren Sie ihre Site-ID.
  2. 2Starten Sie das Gate im Docker-Netzwerk Ihres Proxys mit Ihrem API-Schlüssel und der Site-ID. Veröffentlichen Sie seinen Port nicht.
  3. 3Fügen Sie das Snippet für Ihren Proxy ein.

ghcr.io/ipscanner/forward-auth ist ein statisches Binary für linux/amd64 und linux/arm64, das ohne Root-Rechte und ohne Shell läuft. Binaries für Linux und macOS gibt es auf der Releases-Seite.

Eine neue Website startet im Monitor-Modus: Sie erhält Header, blockiert wird nichts, bis Sie auf Enforce umschalten.

Überblick auf der Seite zu nginx, Apache und HAProxy, Quellcode auf GitHub.

docker-compose.yml
services:
  ipscanner:
    image: ghcr.io/ipscanner/forward-auth:0.1
    restart: unless-stopped
    environment:
      IPSCANNER_API_KEY: ${IPSCANNER_API_KEY}
      SITE_ID: site_...

Proxy-Snippets

  • nginxauth_request

    auth_request fragt /check zu jeder Anfrage. Ein blockierter Besucher sieht die 403-Seite des Gates, ein nicht erreichbares Gate lässt den Traffic durch. nginx löst das Gate beim Start auf, starten Sie es also zuerst.

  • Nginx Proxy Managerauth_request

    Dasselbe im Tab Advanced des Proxy-Hosts, mit dem Gate im Docker-Netzwerk von NPM.

  • TraefikForwardAuth

    Eine ForwardAuth-Middleware in den Labels Ihrer App. Das Traefik-Plugin leistet dasselbe ohne Container.

  • Caddyforward_auth

    forward_auth an /check, mit Übernahme der X-IPScanner-*-Header. Das Caddy-Modul leistet dasselbe ohne Container.

  • HAProxyUPSTREAM_URL

    Proxy-Modus mit UPSTREAM_URL=http://app:80. Die App ist der Backup-Server, der Traffic fließt also weiter, wenn das Gate ausfällt.

  • ApacheUPSTREAM_URL

    Proxy-Modus wie bei HAProxy, mit der App als Hot Standby.

location / {
    auth_request /_ipscanner;
    auth_request_set $ipscanner_status     $upstream_http_x_ipscanner_status;
    auth_request_set $ipscanner_class      $upstream_http_x_ipscanner_class;
    auth_request_set $ipscanner_action     $upstream_http_x_ipscanner_action;
    auth_request_set $ipscanner_network    $upstream_http_x_ipscanner_network_class;
    auth_request_set $ipscanner_anonymized $upstream_http_x_ipscanner_anonymized;
    auth_request_set $ipscanner_risk       $upstream_http_x_ipscanner_risk;
    auth_request_set $ipscanner_country    $upstream_http_x_ipscanner_country;
    auth_request_set $ipscanner_site       $upstream_http_x_ipscanner_site;
    auth_request_set $ipscanner_request_id $upstream_http_x_ipscanner_request_id;
    error_page 403 = @ipscanner_blocked;

    proxy_set_header X-IPScanner-Status        $ipscanner_status;
    proxy_set_header X-IPScanner-Class         $ipscanner_class;
    proxy_set_header X-IPScanner-Action        $ipscanner_action;
    proxy_set_header X-IPScanner-Network-Class $ipscanner_network;
    proxy_set_header X-IPScanner-Anonymized    $ipscanner_anonymized;
    proxy_set_header X-IPScanner-Risk          $ipscanner_risk;
    proxy_set_header X-IPScanner-Country       $ipscanner_country;
    proxy_set_header X-IPScanner-Site          $ipscanner_site;
    proxy_set_header Host                      $host;
    proxy_set_header X-Forwarded-For           $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto         $scheme;
    proxy_pass http://app:80;
}

location = /_ipscanner {
    internal;
    proxy_pass http://ipscanner:8080/check;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Original-URI $request_uri;
    proxy_set_header X-Original-Method $request_method;
    proxy_connect_timeout 1s;
    proxy_read_timeout 5s;
    error_page 500 502 503 504 = @ipscanner_down;
}

location @ipscanner_down {
    return 204;
}

location @ipscanner_blocked {
    internal;
    proxy_method GET;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-IPScanner-Request-Id $ipscanner_request_id;
    rewrite ^ /blocked break;
    proxy_pass http://ipscanner:8080;
}

Endpunkte

  • /checkForward Auth

    200 mit den X-IPScanner-*-Headern oder 403 mit Sperrseite und X-IPScanner-Request-Id.

  • /blockedForward Auth

    Die 403-Seite für die Request-ID in X-IPScanner-Request-Id, für nginx error_page.

  • /healthzbeide Modi

    200 als JSON: Version, Modus, Website, Backoff, letzter Fehler und die zwischengespeicherte Richtlinie.

/check liest die ursprüngliche Anfrage aus den Headern des Proxys: X-Forwarded-For (oder IP_HEADERS), User-Agent, X-Forwarded-Uri oder X-Original-URI sowie X-Forwarded-Method oder X-Original-Method.

Konfiguration

  • IPSCANNER_API_KEY

    Ihr API-Schlüssel. Ohne Schlüssel passiert jede Anfrage ungeprüft.

  • IPSCANNER_API_KEY_FILE

    Datei mit dem Schlüssel, für Docker-Secrets. Hat Vorrang vor IPSCANNER_API_KEY.

  • SITE_ID

    Site-ID aus dem Dashboard. Modus und Richtlinie kommen dann aus dem Dashboard.

  • MODEStandard monitor

    monitor oder enforce. Mit Website wirkt nur monitor: Die Website bleibt dann im Monitor-Modus.

  • BLOCK_CLASSESStandard malicious_automation

    Ohne Website: im Enforce-Modus blockierte Klassen, durch Komma getrennt, aus malicious_automation, ai_agent, tor, vpn, proxy, hosting, relay oder none.

  • TRUSTED_PROXIESStandard private

    Adressen und CIDR-Bereiche, deren IP- und URI-Headern vertraut wird. private, cloudflare oder none für nur die Peer-Adresse.

  • IP_HEADERSStandard X-Forwarded-For

    Header, die der Reihe nach von einem vertrauenswürdigen Proxy gelesen werden. Hinter Cloudflare: CF-Connecting-IP.

  • TIMEOUT_MSStandard 1500

    Zeitbudget für eine Prüfung in Millisekunden. Bei Zeitüberschreitung passiert die Anfrage.

  • CACHE_TTLStandard 600

    Sekunden, die ein Ergebnis pro Website, IP und User-Agent wiederverwendet wird. Angaben wie 10m gehen auch.

  • CACHE_SIZEStandard 10000

    Ergebnisse im Speicher.

  • POLICY_TTLStandard 30

    Sekunden, die die Richtlinie der Website wiederverwendet wird. Zeitangaben gehen auch.

  • SKIP_PATHSStandard statische Dateien

    Regex auf den Pfad, ohne Groß- und Kleinschreibung. Passende Anfragen werden nicht geprüft; leer prüft jeden Pfad.

  • UPSTREAM_URL

    Schaltet den Proxy-Modus ein: Erlaubte Anfragen gehen an diese URL.

  • LISTENStandard :8080

    Listen-Adresse.

  • HEALTH_PATHStandard /healthz

    Health-Endpunkt.

  • BLOCK_MESSAGEStandard Blocked by IPScanner edge guard.

    Text der 403-Seite.

  • IPSCANNER_API_URLStandard https://ipscanner.io

    Basis-URL der API.

  • DEBUGStandard false

    Protokolliert jede Entscheidung in einer Zeile. Im Proxy-Modus kommen Status-, Class- und Action-Header in die Antworten.

Ungültige Werte stoppen das Gate beim Start mit einer Log-Zeile. Der API-Schlüssel wird nie protokolliert.

Client-IP

  • TRUSTED_PROXIES

    X-Forwarded-For wird nur gelesen, wenn der Peer in dieser Liste steht, und zwar die Kette zurück bis zur ersten Adresse, die kein vertrauenswürdiger Proxy ist. Bei allen anderen gilt die Peer-Adresse.

  • private

    Der Standard. Passt zu einem Proxy, der das Gate über ein Docker- oder privates Netzwerk erreicht. Können andere in diesem Netzwerk das Gate erreichen, tragen Sie stattdessen die Adresse Ihres Proxys ein.

  • :8080

    Veröffentlichen Sie den Port des Gates nicht: Nur Ihr Proxy soll es erreichen.

Gesetzte Header

Bei 200 von /check, damit Ihr Proxy sie an die App weitergibt, und im Proxy-Modus an der Anfrage an Ihre App. Der Proxy-Modus entfernt eingehende X-IPScanner-*-Header; die Snippets tun das im Proxy.

  • X-IPScanner-Statusok, error, timeout, backoff, skipped

    Ob die Prüfung lief und falls nicht, warum.

  • X-IPScanner-Classhuman, verified_bot, ai_agent, …

    Traffic-Klasse des Besuchers.

  • X-IPScanner-Actionallow, flag, block, would_flag, would_block

    Was mit der Anfrage geschah. Im Monitor-Modus would_flag und would_block.

  • X-IPScanner-Network-Classresidential_clean, hosting, vpn, tor, …

    Netzwerkklasse der Adresse.

  • X-IPScanner-Anonymizedtrue, false

    Das Netzwerk verbirgt, wo der Besucher ist.

  • X-IPScanner-Risk0-100

    Risikowert der Adresse.

  • X-IPScanner-CountryDE

    Land der Adresse.

  • X-IPScanner-Sitesite_...

    Die Site-ID, wenn eine gesetzt ist.

Schlägt eine Prüfung fehl oder wird sie übersprungen, ist nur X-IPScanner-Status gesetzt.

Anfrage an Ihre App
X-IPScanner-Status: ok
X-IPScanner-Class: ai_agent
X-IPScanner-Action: would_block
X-IPScanner-Network-Class: hosting
X-IPScanner-Anonymized: true
X-IPScanner-Risk: 60
X-IPScanner-Country: US
X-IPScanner-Site: site_4fQ8nZ2kLm7xR1vT9cBw

Cache und Fail-open

  • Richtlinie der WebsiteGET /v1/sites/{id}/policy

    Modus und Richtlinie pro Klasse, 30 s im Cache. Scheitert eine Aktualisierung, gilt die letzte gültige Richtlinie bis zu 24 Stunden. Änderungen greifen ohne Neustart.

  • Ergebnis-Cache

    Eine Prüfung pro Besucher (Website, IP, User-Agent) alle 10 Minuten, im Speicher, pro Gate-Instanz.

  • Fail-open

    1,5 s für Ergebnis und Richtlinie zusammen. Bei Zeitüberschreitung oder API-Fehler passiert die Anfrage, und Prüfungen pausieren 30 s, nach 401, 402, 403 oder 429 fünf Minuten.

  • Gate nicht erreichbar

    nginx und NPM lassen nach dem Connect-Timeout von 1 s durch, HAProxy schickt den Traffic sofort an die App, Apache lässt eine Anfrage scheitern und nutzt dann die App. Traefik antwortet mit 500 und Caddy mit 502, starten Sie das Gate daher mit restart: unless-stopped.

  • Immer durchgelassen

    Verifizierte Crawler, OPTIONS-Anfragen, private und Loopback-Adressen sowie Pfade auf der Ausnahmeliste.

  • Blockiert

    Eine 403-Seite mit der Request-ID. Der Monitor-Modus blockiert nie.

  • Free-Plan

    Websites im Free-Plan bleiben im Monitor-Modus.

  • Kosten

    2 Request-Einheiten pro Besucher ohne Cache-Treffer. Wiederholte Anfragen im Cache-Fenster sind kostenlos.

Was gesendet wird

  • POST /v1/edge/checkZählt als 2 Anfragen

    Ein Aufruf pro Besucher ohne Cache-Treffer.

  • Die Richtlinie der Website, wenn eine Site-ID gesetzt ist.

  • X-IPScanner-Source: forward_auth

    Kennzeichnet die Aufrufe in Traffic und Nutzung als Aufrufe dieser Integration.

  • User-Agent: ipscanner-forward-auth/<version>

    Die Version, angezeigt auf der Seite der Website im Dashboard.

Request-Body

  • sitestring

    Die Site-ID, wenn eine gesetzt ist.

  • ipstring

    Die Adresse des Besuchers.

  • user_agentstring

    Der User-Agent des Besuchers.

  • headersobject

    Accept, Accept-Language, Accept-Encoding, Sec-CH-UA* und Sec-Fetch-*, jeweils auf 512 Byte gekürzt.

  • request_idstring

    Die X-Request-Id der Anfrage oder eine neue ID, die auch auf der Sperrseite steht.

Die Edge-Prüfung, die gesendet wird
curl https://ipscanner.io/v1/edge/check \
  -H "Authorization: Bearer $IPSCANNER_API_KEY" \
  -H "X-IPScanner-Source: forward_auth" \
  -H "User-Agent: ipscanner-forward-auth/0.1.0" \
  -H "Content-Type: application/json" \
  -d '{
    "site": "site_4fQ8nZ2kLm7xR1vT9cBw",
    "ip": "203.0.113.7",
    "user_agent": "Mozilla/5.0",
    "headers": {
      "accept-language": "en-US"
    },
    "request_id": "9f2c41b7d03e77f2"
  }'