---
type: how-to
title: Рецепты обратного прокси и контракт callback
summary: Подключи прокси-барьер на Traefik или Caddy, размести callback, который превращает решённый пропуск в cookie, и закрой Authelia, не трогая её.
---

Каждому обратному прокси нужны те же две части: проверка **авторизатора**, которая спрашивает Caputchin, несёт ли запрос валидный пропуск, и **callback** на твоём источнике, который превращает решённый пропуск в cookie `cpt_gate`. [Прохождение с nginx](/docs/proxy-page-gate/set-up) показывает форму от края до края; эта страница даёт другие прокси, точный контракт callback, и полный пример 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>`.

## Traefik

Используй middleware `forwardAuth` для авторизатора. Traefik пересылает входящий заголовок `Cookie` по умолчанию. При `401` от middleware перенаправь браузер на испытание (middleware страницы ошибки, указывающий на маленький маршрут, который выдаёт `302`, или обработай `401` на своём краю).

```yaml
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-app
```

## Caddy

Используй `forward_auth` для авторизатора и `handle_errors`, чтобы превратить `401` в редирект. Это отправная точка; подстрой синтаксис директив под свою версию Caddy.

```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
}
```

## Callback

Размещённая страница испытания завершается автоотправкой формы `POST` на `https://<твой-источник>/__cpt/callback` с двумя полями в **теле**: `cpt_gate` (пропуском) и `to` (куда отправить посетителя). Добавь этот один маршрут на свой источник (или как отдельный location на прокси). Он должен:

1. Читать `cpt_gate` и `to` из **тела** POST, никогда из URL (пропуск в URL утекает в логи и рефереры).
2. Подтвердить, что `to` на твоём собственном источнике, и отклонить всё остальное, чтобы callback нельзя было превратить в open redirect.
3. Поставить cookie с атрибутами ниже.
4. Перенаправить (`303`) на `to`.

```js
// 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);
});
```

Атрибуты cookie это вся модель безопасности. Поскольку пропуск не привязан к устройству, `HttpOnly` (блокирует кражу скриптом), `Secure` (только HTTPS), `SameSite=Lax`, и короткий `Max-Age` (в тон твоему TTL пропуска) это то, что его защищает. Ещё: не логируй значение `cpt_gate` в своих access-логах, и держи `Referrer-Policy: no-referrer` на callback, чтобы пропуск никогда не ехал попутчиком в заголовке реферера.

## Разобранный пример: Authelia

Портал входа Authelia это скомпилированное одностраничное приложение без места, чтобы встроить виджет, и без хука плагина, так что барьер это способ его защитить. Authelia уже сидит за обратным прокси (так работает её собственный ForwardAuth), и этот прокси и есть место для барьера. Саму Authelia оставляют полностью без изменений.

Поставь барьер на vhost портала (например `auth.example.com`):

- **Закрой** HTML портала и эндпоинт входа первого фактора (`/api/firstfactor`).
- **Исключи** собственный verify-эндпоинт ForwardAuth Authelia (`/api/verify`), который прокси вызывает на каждый защищённый upstream-запрос. Закрыть его сломало бы каждое защищённое приложение за Authelia.
- **Исключи** health-check и статические ассеты, которые нужны самой странице испытания.
- **Добавь** маршрут `/__cpt/callback` как выше.

Барьер держит ботов подальше от портала; встроенная Regulation Authelia (лимит повторов и бан) по-прежнему ограничивает повторы учётных данных для того, кто прошёл, так что два слоя складываются. Барьер защищает только интерактивный портал (UI входа и согласия); он не закрывает, и не должен, неинтерактивные эндпоинты токенов.

## См. также

- [Настрой прокси-барьер](/docs/proxy-page-gate/set-up): прохождение с nginx и раскатка с предпросмотром-сначала.
- [Обзор](/docs/proxy-page-gate/overview): концепция и cookie пропуска.
- [Статистика](/docs/proxy-page-gate/statistics): подтверди подключение, наблюдая испытание против прямого пропуска.
