集成

适用于 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"
  }'