整合

適用於 nginx、Apache 及 HAProxy 的 Forward Auth

一個小型容器,nginx、Nginx Proxy Manager、Apache、HAProxy、Traefik 或 Caddy 會就每個請求向它查詢。

安裝

  1. 1在控制台中加入 Forward Auth 網站並複製其 Site ID。
  2. 2在代理所在的 Docker 網絡中執行 Gate,並提供 API 金鑰及 Site ID。切勿對外發布其連接埠。
  3. 3加入對應代理的設定片段。

ghcr.io/ipscanner/forward-auth 是適用於 linux/amd64 及 linux/arm64 的靜態二進位檔,以非 root 身分執行,不含 shell。Linux 及 macOS 二進位檔見 Releases 頁面。

新網站預設以 Monitor 模式運行:只加入標頭,在切換到 Enforce 之前不會封鎖任何請求。

概覽見 nginx、Apache 及 HAProxy 頁面,原始碼見 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_...

各代理設定片段

  • nginxauth_request

    auth_request 就每個請求查詢 /check。被封鎖的訪客會看到 Gate 的 403 頁面,Gate 無法連線時流量會放行。nginx 在啟動時解析 Gate 位址,請先啟動 Gate。

  • Nginx Proxy Managerauth_request

    同上,貼到代理主機的 Advanced 分頁中,Gate 須位於 NPM 的 Docker 網絡。

  • TraefikForwardAuth

    在應用程式標籤中定義 ForwardAuth 中介軟件。Traefik 外掛無需容器亦可達到相同效果。

  • Caddyforward_auth

    forward_auth 指向 /check,並複製 X-IPScanner-* 標頭。Caddy 模組無需容器亦可達到相同效果。

  • HAProxyUPSTREAM_URL

    代理模式,設定 UPSTREAM_URL=http://app:80。應用程式作為後備伺服器,Gate 停止時流量照常。

  • ApacheUPSTREAM_URL

    與 HAProxy 相同的代理模式,應用程式作為熱備援。

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;
}

端點

  • /checkForward Auth

    200 並附 X-IPScanner-* 標頭,或 403 並傳回封鎖頁面及 X-IPScanner-Request-Id。

  • /blockedForward Auth

    按 X-IPScanner-Request-Id 中的請求 ID 傳回 403 頁面,供 nginx 的 error_page 使用。

  • /healthz兩種模式

    200 JSON:版本、模式、網站、退避狀態、最近錯誤及快取的策略。

/check 從代理的標頭讀取原始請求:X-Forwarded-For(或 IP_HEADERS)、User-Agent、X-Forwarded-Uri 或 X-Original-URI,以及 X-Forwarded-Method 或 X-Original-Method。

設定

  • IPSCANNER_API_KEY

    您的 API 金鑰。沒有金鑰時,所有請求不經檢查直接放行。

  • IPSCANNER_API_KEY_FILE

    存放金鑰的檔案,用於 Docker secret。優先於 IPSCANNER_API_KEY。

  • SITE_ID

    控制台中的 Site ID。設定後,模式及策略由控制台決定。

  • MODE預設 monitor

    monitor 或 enforce。設定網站後只有 monitor 生效:令網站保持 Monitor 模式。

  • BLOCK_CLASSES預設 malicious_automation

    未設定網站時 Enforce 模式封鎖的類別,以逗號分隔,可選 malicious_automation、ai_agent、tor、vpn、proxy、hosting、relay 或 none。

  • TRUSTED_PROXIES預設 private

    信任其 IP 及 URI 標頭的位址及 CIDR 範圍。可用 private、cloudflare,或以 none 只採用對端位址。

  • IP_HEADERS預設 X-Forwarded-For

    按次序從可信代理讀取的標頭。位於 Cloudflare 之後時使用 CF-Connecting-IP。

  • TIMEOUT_MS預設 1500

    單次檢查的時間預算,單位為毫秒。逾時後請求放行。

  • CACHE_TTL預設 600

    按網站、IP 及 User-Agent 重用一次結果的秒數。亦可寫成 10m 等時長。

  • CACHE_SIZE預設 10000

    記憶體中保存的結果數目。

  • POLICY_TTL預設 30

    網站策略的重用秒數。亦可寫成時長。

  • SKIP_PATHS預設 靜態檔案

    對路徑比對的正規表示式,不分大小寫。符合的請求不作檢查;留空表示檢查所有路徑。

  • UPSTREAM_URL

    啟用代理模式:放行的請求轉發至此 URL。

  • LISTEN預設 :8080

    監聽位址。

  • HEALTH_PATH預設 /healthz

    健康檢查端點。

  • BLOCK_MESSAGE預設 Blocked by IPScanner edge guard.

    403 頁面的文字。

  • IPSCANNER_API_URL預設 https://ipscanner.io

    API 基本 URL。

  • DEBUG預設 false

    為每項決定記錄一行日誌。代理模式下亦會在回應中加入狀態、類別及動作標頭。

數值無效時 Gate 會在啟動時停止並記錄一行日誌。API 金鑰從不寫入日誌。

用戶端 IP

  • TRUSTED_PROXIES

    只有對端在此清單內時才會讀取 X-Forwarded-For,並沿鏈回溯至第一個非可信代理的位址。其他對端一律採用對端位址。

  • private

    預設值。適用於經 Docker 網絡或私人網絡連接 Gate 的代理。如該網絡中的其他主機亦能連接 Gate,請改填代理的位址。

  • :8080

    切勿發布 Gate 的連接埠:只應由您的代理連接。

加入的標頭

出現在 /check 的 200 回應上,供代理轉交應用程式;代理模式下則加在傳往應用程式的請求上。代理模式會移除傳入的 X-IPScanner-* 標頭,上述設定片段在代理中作相同處理。

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

    檢查是否已執行,未執行時說明原因。

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

    訪客的流量類別。

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

    請求的處理結果。Monitor 模式下為 would_flag 及 would_block。

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

    位址的網絡類別。

  • X-IPScanner-Anonymizedtrue, false

    該網絡隱藏了訪客的實際位置。

  • X-IPScanner-Risk0-100

    位址的風險分數。

  • X-IPScanner-CountryDE

    位址所屬國家或地區。

  • X-IPScanner-Sitesite_...

    已設定時為 Site ID。

檢查失敗或被略過時,只會設定 X-IPScanner-Status。

傳往應用程式的請求
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

快取與故障放行

  • 模式及按類別的策略,快取 30 秒。更新失敗時,最近一次有效的策略最多沿用 24 小時。修改無需重新載入即可生效。

  • 結果快取

    每位訪客(網站、IP、User-Agent)每 10 分鐘檢查一次,保存在記憶體中,按 Gate 執行個體分別快取。

  • 故障放行

    結果與策略合共 1.5 秒。逾時或 API 出錯時請求放行,檢查暫停 30 秒;遇到 401、402、403 或 429 時暫停 5 分鐘。

  • Gate 停止時

    nginx 及 NPM 在 1 秒連線逾時後放行,HAProxy 即時把流量交給應用程式,Apache 令一個請求失敗後改用應用程式。Traefik 傳回 500,Caddy 傳回 502,因此請以 restart: unless-stopped 執行 Gate。

  • 一律放行

    已驗證的爬蟲、OPTIONS 請求、私人及回送位址,以及略過清單中的路徑。

  • 封鎖

    傳回附請求 ID 的 403 頁面。Monitor 模式從不封鎖。

  • Free 方案

    Free 方案的網站會保持 Monitor 模式。

  • 費用

    每位未命中快取的訪客計 2 個請求單位。快取期內的重複請求不收費。

發送的內容

  • POST /v1/edge/check計為 2 次請求

    每位未命中快取的訪客一次呼叫。

  • 網站策略,已設定 Site ID 時才會請求。

  • X-IPScanner-Source: forward_auth

    在流量及用量中將呼叫標記為此整合發出。

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

    版本號,顯示在控制台的網站頁面上。

請求主體

  • sitestring

    已設定時為 Site ID。

  • ipstring

    訪客位址。

  • user_agentstring

    訪客的 User-Agent。

  • headersobject

    Accept、Accept-Language、Accept-Encoding、Sec-CH-UA* 及 Sec-Fetch-*,各自截短至 512 位元組。

  • request_idstring

    請求的 X-Request-Id 或新產生的 ID,亦會顯示在封鎖頁面上。

它發出的邊緣偵測請求
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"
  }'