Caputchin
プロキシゲート

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

Markdown で表示

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

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

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

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

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

  • 通過許可 TTL:一度の解答が訪問者をどれだけ通過させるか(既定 30 分)。短いほど再チェックが増えますが、Cookie が盗まれた場合の窓は小さくなります。
  • フェイルモード:プロキシが Caputchin のオーソライザーに到達できないときに何をするか。fail-closed はブロック(ログインポータルに安全寄り)、fail-open はリクエストを通す(公開サイトのダウンタイムを避ける)。

このページは、あなたのサイトキーがすでに埋め込まれた、コピーしてすぐ使える 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_pass to your app...
}

location = /_cpt_authz {
  internal;
  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
}

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

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

チャレンジページは終わりに、あなたのオリジンの /__cpt/callback へ小さな POST を自動送信します。ボディ には cpt_gate(パス)と to(訪問者をどこへ送るか)が入ります。ごく小さなハンドラーが 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. 本番にする

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

次にどこへ

このページの内容