Caputchin
プロキシのページゲート

nginx でプロキシのページゲートを設定する

Markdown で表示

このチュートリアルの終わりには、ゲートは nginx の背後にあるサイトの手前で動いています。通過許可のない訪問者は検証へ送られ、検証を通ると Cookie がセットされ、後のリクエストはまっすぐ通ります。まずは全体を プレビューモード で観察するので、配線を確かめるまで何もブロックされません。ここでは nginx を使います。Traefik、Caddy、Authelia のレシピ は同じ形に従います。

1. プレビューモードをオンにする

ダッシュボードでチームを開き、プレビューモード をオンにします。オンの間、ゲートのオーソライザーはチャレンジ対パススルーの判断を 統計ページ に記録しますが、決してブロックしません。最後にオフにします。

2. サイトキーでゲートを有効にする

サイトキーを開き、プロキシゲート ページへ行きます。ステータス → 有効 をオンにし、次を設定します:

  • チャレンジの種類:ゲームをプレイ(既定)か チェックボックスで確認。ゲームを必須にしているサイトキーは常にゲームを表示し、ページにもそう書かれます。ゲームを選ぶには、リプレイ可能なアーティファクトを持つインストール済みのゲームが最低一つ必要です。
  • 通過許可 TTL:一度の解答が訪問者をどれだけ通過させるか(既定 30 分)。短いほど再チェックが増えますが、Cookie が盗まれた場合の窓は小さくなります。
  • フェイルモード:プロキシが Caputchin のオーソライザーに到達できないときに何をするか。fail-closed はブロック(ログインポータルに安全寄り)、fail-open はリクエストを通す(公開サイトのダウンタイムを避ける)。

言語 と テーマ は 訪問者に合わせる のままにしてください。そうすれば検証は訪問者の言語で話し、明るい・暗いの好みに従い、このサイトキーのブランドを自動でまといます。詳細設定 では、ゲートの Cookie 名を変え、コールバックのパスを移し、ゲートを特定のパスに絞れます。この手順は既定値を使います。チャレンジをカスタマイズする を参照してください。

このページは、設定がすでに埋め込まれた、コピーしてすぐ使える nginx スニペットも表示します。設定は変更後、エッジに届くまで最大で十秒かかります。

3. ゲートをかけるオリジンを許可する

検証は 許可されたオリジン にしか戻りリダイレクトしません。ウィジェットが使うのと同じオリジン許可リストです。ゲートをかけるオリジン、たとえば https://auth.example.com が含まれているか確かめてください。まだなければ、サイトキーの Cap 設定でそれを設定します。

4. オーソライザーとチャレンジのリダイレクトを配線する

二つの location ブロック:内部の オーソライザー サブリクエストと、プロキシが 401 で飛ぶ チャレンジ リダイレクトです。YOUR_SITE_KEY を公開鍵に置き換えます。

# Gate the protected paths.
location / {
  auth_request /_cpt_authz;             # 204 = allow, 401 = challenge
  error_page 401 = @cpt_challenge;
  proxy_intercept_errors on;
  error_page 500 502 503 504 = @cpt_unreachable;
  # ...proxy_pass to your app...
}

location = /_cpt_authz {
  internal;
  auth_request off;
  proxy_pass https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY;
  proxy_pass_request_body off;
  proxy_set_header Content-Length "";
  proxy_set_header Cookie $http_cookie;  # forward the cpt_gate cookie
  proxy_connect_timeout 2s;
  proxy_read_timeout 2s;
}

location @cpt_challenge {
  return 302 https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=$scheme://$host$request_uri;
}

# This is your fail mode. `return 403` blocks when Caputchin is unreachable
# (fail closed); `return 204` lets the request through (fail open).
location @cpt_unreachable {
  return 403;
}

オーソライザーが返すのは 204 か 401 だけなので、タイムアウトを含めそれ以外は Caputchin に到達できない意味で、あなたのフェイルモードが決めます。ダッシュボードからスニペットをコピーすれば、選んだフェイルモードにすでに合っています。

入口パス(ポータルの HTML とログインの POST)にゲートをかけます。オーソライザーのサブリクエスト、ヘルスチェック、下のコールバックには ゲートをかけないで ください。

検証ページは終わりに、オリジンの /__cpt/callback(または設定したコールバックのパス)へ小さな POST を自動送信します。ボディ には cpt_gate(パス)と to(訪問者をどこへ送るか)が入ります。Cookie 名を変えても、このフィールドの名前は cpt_gate のままです。ごく小さなハンドラーが Cookie をセットしてリダイレクトします。各 Cookie 属性がなぜ重要かも含む完全な契約は、リバースプロキシのレシピ にあります。最小限:

app.post("/__cpt/callback", express.urlencoded({ extended: false }), (req, res) => {
  const pass = String(req.body.cpt_gate || "");
  const to = String(req.body.to || "/");
  const target = new URL(to, `https://${req.headers.host}`);
  if (target.host !== req.headers.host) return res.status(400).end(); // same-origin only
  res.setHeader(
    "Set-Cookie",
    `cpt_gate=${pass}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=1800`
  );
  res.redirect(303, target.pathname + target.search);
});

6. プレビューで観察する

ゲート付き URL を読み込みます。プレビューがオンなので、まっすぐ通りますが、統計ページ は challenge_served を記録し(Cookie がなかったため)、解いてコールバックが走ると pass_issued を記録します。再読み込みすると passthrough が上っていくはずです。チャレンジが決して現れないなら、オーソライザーのブロックが当たっていません。コールバックが 400 を返すなら、to のオリジンを確認してください。

7. 本番にする

数字が正しく見えたら、プレビューモード をオフにします。ゲートは今や強制します。通過許可のない訪問者はゲームへ送られ、解いた訪問者はパスが切れるまで歩き回ります。

次にどこへ

このページの内容