리버스 프록시 레시피와 콜백 계약
모든 리버스 프록시에는 같은 두 조각이 필요합니다. 요청이 유효한 패스를 지녔는지 Caputchin에 묻는 인가자 확인과, 푼 패스를 cpt_gate 쿠키로 바꾸는, 오리진 위의 콜백입니다. nginx 안내가 끝에서 끝까지의 형태를 보여 줍니다. 이 페이지는 다른 프록시들, 정확한 콜백 계약, 그리고 완전한 Authelia 예시를 줍니다. YOUR_SITE_KEY는 전체에서 공개 키로 바꾸세요.
엔드포인트는 어디서나 같습니다:
- 인가자:
GET https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY, 방문자의Cookie헤더를 전달하여.204는 허용,401은 챌린지를 뜻합니다. - 챌린지: 브라우저를
https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=<원래 URL>로 리디렉션합니다.
인가자가 답하는 것은 204 아니면 401 뿐입니다. 타임아웃을 포함해 그 밖의 무엇이든 Caputchin에 닿을 수 없다는 뜻이고, 그때 무슨 일이 일어날지는 당신의 실패 모드입니다. 요청을 막거나(실패 시 닫힘, 로그인 포털에 더 안전) 통과시키거나(실패 시 열림). 사이트 키에서 설정하면 생성되는 스니펫도 거기에 맞습니다. 인가자 서브요청에는 짧은 타임아웃을 주어, 장애가 판단하는 동안 모든 요청을 붙들지 않게 하세요.
Traefik
인가자에는 forwardAuth 미들웨어를 씁니다. Traefik은 들어오는 Cookie 헤더를 기본으로 전달합니다. 미들웨어에서 401이 오면, 브라우저를 챌린지로 리디렉션합니다(302를 내는 작은 라우트를 가리키는 에러 페이지 미들웨어, 또는 엣지에서 401을 처리).
http:
middlewares:
cpt-gate:
forwardAuth:
address: "https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY"
# The 401 from forwardAuth is your signal to send the browser to:
# https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=<original-url>
routers:
portal:
rule: "Host(`auth.example.com`)"
middlewares: ["cpt-gate"]
service: your-appCaddy
인가자에는 forward_auth를, 401을 리디렉션으로 바꾸는 데는 handle_errors를 씁니다. 이것은 출발점입니다. 지시어 구문은 Caddy 버전에 맞게 조정하세요.
auth.example.com {
forward_auth https://verify.caputchin.com {
uri /v1/gate/authz?site=YOUR_SITE_KEY
copy_headers Cookie
}
handle_errors {
@challenge expression {http.error.status_code} == 401
redir @challenge https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return={scheme}://{host}{uri} 302
}
reverse_proxy your-app:8080
}콜백
호스팅 검증 페이지는 끝에 https://<당신의-오리진>/__cpt/callback으로 POST 폼을 자동 제출하며, 본문에 두 필드, cpt_gate(패스)와 to(방문자를 어디로 보낼지)를 담습니다. 사이트 키에서 콜백 경로를 바꿨다면 대신 그곳으로 제출합니다. 이 한 라우트를 오리진에 더하세요(또는 프록시 위의 전용 location으로). 그것은 반드시:
cpt_gate와to를 POST 본문에서 읽고, URL에서는 결코 읽지 않아야 합니다(URL 안의 패스는 로그와 리퍼러로 샙니다).to가 당신 자신의 오리진 위인지 확인하고, 그 외 무엇이든 거부해야 합니다. 그래야 콜백을 오픈 리디렉션으로 바꿀 수 없습니다.- 아래 속성으로 쿠키를 설정해야 합니다.
to로 (303으로) 리디렉션해야 합니다.
// Any tiny handler on your origin works. Express shown; ~15 lines.
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);
});쿠키 속성이 보안 모델의 전부입니다. 패스는 기기에 묶이지 않으므로, HttpOnly(스크립트 절도를 막음), Secure(HTTPS만), SameSite=Lax, 그리고 짧은 Max-Age(통과 TTL에 맞춤)가 그것을 보호하는 것입니다. 또한 cpt_gate 값을 액세스 로그에 기록하지 말고, 콜백에 Referrer-Policy: no-referrer를 유지해 패스가 리퍼러 헤더에 얹혀 함께 실려 가는 일이 결코 없게 하세요.
프록시별 실패 모드
Caputchin은 실패 모드 결정을 결코 보지 못하므로, 그것은 통계에도 결코 나타나지 않습니다. 인가자에 닿을 수 없을 때 프록시가 로컬에서 내리기 때문입니다.
- nginx:
proxy_intercept_errors on;에 더해error_page 500 502 503 504 = @cpt_unreachable;를 두고, 그 이름 붙은 location을return 403(닫힘) 또는return 204(열림)로 합니다. - Traefik:
forwardAuth미들웨어는 닿을 수 없는 주소에서 오류가 납니다. 그것을403을 돌려주는 서비스로 라우팅하거나(닫힘), 헬스체크 뒤에서 라우터에서 미들웨어를 떼어 냅니다(열림). - Caddy:
handle_errors를5xx매처로 넓혀respond 403(닫힘) 또는respond 204(열림)로 합니다.
프록시별 경로 범위
이 경로만 게이트 적용와 이 경로는 절대 게이트 적용 안 함는 생성되는 구성을 빚습니다. 강제하는 것은 당신의 프록시입니다.
- nginx: 게이트를 거는 경로마다
location ^~ <접두사>하나씩, 제외하는 각 경로 안에는auth_request off;.*.php같은 확장자 패턴은location ~* \.php$가 됩니다. - Traefik:
cpt-gate미들웨어는 규칙이 게이트 대상 경로와 맞는 라우터에만 붙이고, 나머지에는 붙이지 않습니다. - Caddy:
forward_auth를 경로 매처로 감쌉니다. 예컨대@gated path /admin/* /login다음에forward_auth @gated ....
인가자 서브요청과 당신의 콜백 경로에는 결코 게이트를 걸지 마세요.
실전 예시: Authelia
Authelia의 로그인 포털은 위젯을 삽입할 자리도 플러그인 훅도 없는, 컴파일된 단일 페이지 앱이므로, 게이트가 그것을 보호하는 방법입니다. Authelia는 이미 리버스 프록시 뒤에 앉아 있고(그 자신의 ForwardAuth가 그렇게 동작합니다), 그 프록시가 게이트가 가는 곳입니다. Authelia 자체는 전혀 수정되지 않은 채로 남습니다.
게이트를 포털의 vhost(예컨대 auth.example.com)에 놓습니다:
- 포털 HTML과 1차 인증 로그인 엔드포인트(
/api/firstfactor)에 게이트를 겁니다. - Authelia 자신의 ForwardAuth verify 엔드포인트(
/api/verify)를 제외합니다. 프록시는 보호된 각 업스트림 요청마다 이것을 호출합니다. 여기에 게이트를 걸면 Authelia 뒤의 보호된 각 앱이 깨집니다. - 헬스 체크와 챌린지 페이지 자체가 필요로 하는 정적 에셋을 제외합니다.
- 위와 같이
/__cpt/callback라우트(또는 구성한 콜백 경로)를 더합니다.
이 네 항목이 바로 경로 범위 설정이 표현하는 것입니다. /와 /api/firstfactor를 게이트 대상 경로로, /api/verify와 헬스체크를 제외 경로로.
게이트는 봇을 포털에서 떼어 놓습니다. Authelia 내장 Regulation(재시도 한도와 밴)은 통과한 누구에게든 자격 증명 재시도를 여전히 제한하니, 두 층이 겹칩니다. 게이트는 상호작용 포털(로그인과 동의 UI)만 보호합니다. 그것은 비상호작용 토큰 엔드포인트에 게이트를 걸지 않으며, 걸어서도 안 됩니다.
함께 보기
- 프록시 페이지 게이트 설정하기: nginx 안내와 미리보기-모드-먼저 롤아웃.
- 챌린지 맞춤 설정하기: 챌린지 유형, 언어, 테마, 쿠키 이름, 콜백 경로, 경로 범위.
- 개요: 개념과 통과 쿠키.
- 통계: 챌린지 대 통과를 지켜보며 배선을 확인.