From 8104be1695b29d72735173c721cc43d067913177 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Wed, 2 Sep 2026 11:55:08 +0500 Subject: [PATCH] =?UTF-8?q?Caddy:=20=D0=B3=D0=BE=D0=BB=D1=8B=D0=B9=20IP=20?= =?UTF-8?q?=D0=BF=D0=BE=20HTTP=20=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B5=20=D1=81=D0=BF=D1=80=D0=B0=D1=88=D0=B8=D0=B2=D0=B0?= =?UTF-8?q?=D0=B5=D1=82=20=D0=BF=D0=B0=D1=80=D0=BE=D0=BB=D1=8C=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D1=80=D1=8B=D1=82=D1=8B=D0=BC=20=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Аудит 02.09: curl http://188.124.37.140/api/v1/me отвечал 401 с Www-Authenticate: Basic realm=GenDesign Pilot. Браузер, открывший голый IP, отправил бы пароль пилота plaintext-ом любому слушающему канал. Замысел блока был верный — «закрыть обход через голый IP тем же auth-гейтом». Исполнение дырявое: basic_auth на plain HTTP это и есть канал утечки пароля. Редирект на канонический HTTPS строже гейта: по HTTP не отдаётся ни контент, ни сам запрос пароля — обход закрыт тем, что отвечать нечему. /health остаётся публичным (liveness). Потребителей у IP:80 нет: все deploy-смоки ходят docker exec → localhost внутри контейнеров (grep по .forgejo/workflows и ops/). Конфиг провалидирован БОЕВЫМ бинарём: docker exec gendesign-caddy-1 caddy validate → Valid configuration. Гейт snippet-mounts зелёный. --- Caddyfile | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/Caddyfile b/Caddyfile index 7f99e71a..684a331a 100644 --- a/Caddyfile +++ b/Caddyfile @@ -50,30 +50,27 @@ # ничего не меняется. В окне: на Selectel CADDY_SITES=apps, на Beget=infra. import caddy/sites/{$CADDY_SITES:*}.caddy -# Plain HTTP by IP — closed by same auth gate (prevent bypass via direct IP / SSH tunnel). -# Caddy issues no TLS here (no hostname). /health remains public. +# Plain HTTP by IP. /health остаётся публичным (liveness). Всё остальное — +# РЕДИРЕКТ на канонический HTTPS, а не проксирование под basic_auth. +# +# ЗДЕСЬ СТОЯЛ auth-гейт с проксированием приложения — «закрыть обход через +# голый IP тем же гейтом». Замысел верный, исполнение — дыра: Basic-challenge +# на plain HTTP означает, что браузер отправит пароль пилота ОТКРЫТЫМ ТЕКСТОМ +# любому, кто слушает канал (аудит 02.09.2026: curl http:///api/v1/me → +# 401 + Www-Authenticate: Basic realm="GenDesign Pilot"). Редирект строже +# гейта: по HTTP не отдаётся ни контент, ни сам запрос пароля, обход через +# IP закрыт тем, что отвечать нечему. Потребителей у IP:80 нет: все +# deploy-смоки ходят docker exec → localhost внутри контейнеров (проверено +# grep-ом по .forgejo/workflows и ops/ 02.09.2026). :80 { - encode zstd gzip - route { - # /health — public, без auth (GHA deploy smoke check, liveness probe). + # /health — public, без auth (liveness probe). handle /health { reverse_proxy backend:8000 } - # Auth gate (same snippet as gendsgn.ru). - import caddy/users.caddy.snippet - - handle /api/* { - reverse_proxy backend:8000 { - header_up X-Authenticated-User {http.auth.user.id} - } - } - handle { - reverse_proxy frontend:3000 { - header_up X-Authenticated-User {http.auth.user.id} - } + redir https://gendsgn.ru{uri} permanent } } }