Caputchin
프록시 페이지 게이트

nginx로 프록시 페이지 게이트 설정하기

Markdown으로 보기

이 튜토리얼이 끝나면 게이트는 nginx 뒤의 사이트 앞에서 돌고 있을 것입니다. 통과되지 않은 방문자는 검증으로 보내지고, 검증을 통과하면 쿠키가 설정되며, 이후 요청은 곧장 통과합니다. 먼저 그 전체를 미리보기 모드에서 지켜볼 테니, 배선을 확인하기 전까지는 아무것도 막히지 않습니다. 여기서는 nginx를 씁니다. Traefik, Caddy, Authelia 레시피는 같은 형태를 따릅니다.

1. 미리보기 모드를 켭니다

대시보드에서 팀을 열고 미리보기 모드를 켭니다. 켜진 동안, 게이트 인가자는 챌린지 대 통과 결정을 통계 페이지에 기록하지만 결코 막지 않습니다. 마지막에 끄게 됩니다.

2. 사이트 키에서 게이트를 활성화합니다

사이트 키를 열고 프록시 게이트 페이지로 갑니다. 상태 → 활성화를 켠 뒤 설정합니다:

  • 챌린지 유형: 게임 플레이(기본값) 또는 체크박스로 확인. 게임을 요구하는 사이트 키는 항상 게임을 보여 주고, 페이지에도 그렇게 적힙니다. 게임을 고르려면 재생 가능한 아티팩트를 가진 설치된 게임이 최소 하나 필요합니다.
  • 통과 TTL: 한 번의 풀이가 방문자를 얼마나 오래 통과시키는지(기본값 30분). 짧을수록 재확인이 많아지지만 쿠키가 도난당했을 때의 창은 작아집니다.
  • 실패 모드: 프록시가 Caputchin의 인가자에 닿을 수 없을 때 무엇을 하는지. 실패 시 닫힘(fail closed)은 막습니다(로그인 포털에 더 안전). 실패 시 열림(fail open)은 요청을 통과시킵니다(공개 사이트의 다운타임을 피함).

언어와 테마는 방문자에 맞춤으로 두세요. 그러면 검증은 방문자의 언어로 말하고, 밝음이나 어두움 선호를 따르며, 이 사이트 키의 브랜드를 자동으로 두릅니다. 고급에서는 게이트 쿠키의 이름을 바꾸고, 콜백 경로를 옮기고, 게이트를 특정 경로로 좁힐 수 있습니다. 이 안내는 기본값을 씁니다. 챌린지 맞춤 설정하기를 보세요.

이 페이지는 설정이 이미 채워진, 복사해 바로 쓸 nginx 스니펫도 보여 줍니다. 설정은 바꾼 뒤 엣지에 닿기까지 최대 10초가 걸립니다.

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)에 게이트를 거세요. 인가자 서브요청, 헬스 체크, 아래의 콜백에는 게이트를 걸지 마세요.

5. 쿠키를 설정하는 콜백을 더합니다

검증 페이지는 끝에 오리진의 /__cpt/callback(또는 설정한 콜백 경로)으로 작은 POST를 자동 제출하며, 본문에 cpt_gate(패스)와 to(방문자를 어디로 보낼지)를 담습니다. 쿠키 이름을 바꿨더라도 이 필드의 이름은 cpt_gate입니다. 아주 작은 핸들러가 쿠키를 설정하고 리디렉션합니다. 각 쿠키 속성이 왜 중요한지를 포함한 전체 계약은 리버스 프록시 레시피에 있습니다. 최소한:

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를 기록하고(쿠키가 없었으므로), 풀고 콜백이 돌면 pass_issued를 기록합니다. 새로고침하면 passthrough가 오르는 것을 봐야 합니다. 챌린지가 결코 나타나지 않으면 인가자 블록이 맞지 않는 것이고, 콜백이 400을 내면 to 오리진을 확인하세요.

7. 라이브로 갑니다

숫자가 옳아 보이면 미리보기 모드를 끕니다. 게이트는 이제 강제합니다. 통과되지 않은 방문자는 게임으로 보내지고, 푼 방문자는 그의 패스가 만료될 때까지 돌아다닙니다.

다음으로 갈 곳

이 페이지에서