fr1: вебхук Маруси — vhost astra.ruzzy.dev и пользователь туннеля marusia-tunnel
- nginx: vhost astra.ruzzy.dev (LE), только POST /marusia/webhook/ → 127.0.0.1:18788, limit_req 1r/s, 64k, без access log, error_log crit (секрет в пути); ссылка zz-, чтобы не перехватить ответ на неизвестный SNI у git - sshd: Match User marusia-tunnel — только remote forward 127.0.0.1:18788; добавлен в AllowUsers - живые конфиги fr1 в stacks/astra-marusia/ вместо nginx-location.example - fr1.md: эффективные настройки sshd проверены под root, отпечатки host-ключей - туннель ещё не поднят, интеграция не завершена (хвост в fr1.md) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3159921a4d
commit
e2bd908198
@@ -22,12 +22,36 @@ StateDirectory. Не подключать этот сервис к админи
|
||||
Повтор webhook с теми же session_id/message_id получает кешированный ответ.
|
||||
Не более двух обращений к модели одновременно, не более 50 разговоров.
|
||||
|
||||
Для завершения нужны: приватный навык в аккаунте VK владельца, его skill_id
|
||||
в env, публичный HTTPS URL с проксированием на rpi (например nginx на fr1
|
||||
и отдельный ограниченный SSH-туннель). Доступа SSH к fr1 у astra на rpi сейчас нет;
|
||||
ключ Gitea — не ключ сервера. Не открывать домашний порт в интернет напрямую.
|
||||
На публичном прокси отключить access log webhook (секрет в URL), ограничить
|
||||
размер тела 64 KiB, POST и частоту запросов; таймаут 5 секунд.
|
||||
## Публичный вход на fr1 (с 2026-10-11)
|
||||
|
||||
Цепочка: VK → `https://astra.ruzzy.dev/marusia/webhook/<секрет>` → nginx на fr1 →
|
||||
`127.0.0.1:18788` (обратный SSH-туннель, поднимает rpi) → rpi `127.0.0.1:8788/webhook/<секрет>`.
|
||||
Домашние порты наружу не открыты, 18788 на fr1 слушает только loopback.
|
||||
|
||||
- `fr1-nginx-astra.ruzzy.dev.conf` → `/etc/nginx/sites-available/astra.ruzzy.dev.conf`,
|
||||
ссылка `sites-enabled/zz-astra.ruzzy.dev.conf`. ⚠️ Префикс `zz-` нужен: на :443 у fr1
|
||||
нет `default_server`, и первый по алфавиту vhost отвечает на неизвестный SNI
|
||||
(`ruzzy.dev`, `fr1.ruzzy.dev`) — без префикса им стал бы этот vhost вместо git.
|
||||
- `fr1-nginx-conf.d-marusia-webhook.conf` → `/etc/nginx/conf.d/marusia-webhook.conf`
|
||||
(зона `limit_req` 1 r/s, burst 5, отказ — 429).
|
||||
- `fr1-sshd-70-marusia-tunnel.conf` → `/etc/ssh/sshd_config.d/70-marusia-tunnel.conf`;
|
||||
плюс `marusia-tunnel` дописан в `AllowUsers` в `00-hardening.conf` — ⚠️ без этого
|
||||
sshd пользователя молча не пустит («Permission denied» без причины на клиенте).
|
||||
- Пользователь fr1 `marusia-tunnel`: nologin, пароль заблокирован, групп нет;
|
||||
`authorized_keys` принадлежит root, ключ с `restrict,port-forwarding,permitlisten="127.0.0.1:18788"`.
|
||||
- Отпечаток host-ключа fr1 (ED25519): `SHA256:M5J9nH+svyA3+beD7ZllUn1tayMMO2cxw/t3Z/kj6KU`.
|
||||
|
||||
⚠️ Секрет — часть пути, поэтому на fr1 для этого location `access_log off`, а
|
||||
`error_log` отдельный и только `crit`: на уровне `error` nginx пишет строку запроса
|
||||
(с секретом) при 502 от упавшего туннеля и при срабатывании `limit_req`.
|
||||
Не поднимать уровень этого лога «для отладки» — секрет окажется на диске.
|
||||
По HTTP `/marusia/` отдаёт 404 без лога и без редиректа.
|
||||
|
||||
Ожидаемые ответы до заполнения skill_id: GET → 403 (nginx), POST с неверным
|
||||
секретом → 404, с верным → 403 (сервис), туннель лежит → 502.
|
||||
|
||||
Ключ Gitea — не ключ сервера; для туннеля отдельный ed25519 на rpi.
|
||||
Не открывать домашний порт в интернет напрямую.
|
||||
Регистрация/проверка: https://platform.vk.com/ и
|
||||
https://skill-tester.marusia.mail.ru/ (актуальность интерфейса проверить при входе).
|
||||
До заполнения skill_id все POST закрыты (403), знание случайного пути обязательно.
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# Публичный вход в разговорный сервис «Астра» для Маруси (stacks/astra-marusia).
|
||||
# Цепочка: VK → nginx → 127.0.0.1:18788 (обратный SSH-туннель от rpi, пользователь marusia-tunnel) → rpi 127.0.0.1:8788.
|
||||
# ⚠️ Секрет — часть пути. Поэтому в location нет access_log, а error_log только crit:
|
||||
# на уровне error nginx пишет строку запроса (с секретом) при 502/limit_req.
|
||||
server {
|
||||
server_name astra.ruzzy.dev;
|
||||
server_tokens off;
|
||||
|
||||
location ^~ /marusia/webhook/ {
|
||||
access_log off;
|
||||
error_log /var/log/nginx/marusia-webhook.error.log crit;
|
||||
|
||||
client_max_body_size 64k;
|
||||
client_body_timeout 5s;
|
||||
|
||||
limit_except POST {
|
||||
deny all;
|
||||
}
|
||||
|
||||
limit_req zone=marusia_webhook burst=5 nodelay;
|
||||
limit_req_status 429;
|
||||
|
||||
proxy_connect_timeout 1s;
|
||||
proxy_send_timeout 5s;
|
||||
proxy_read_timeout 5s;
|
||||
|
||||
# /marusia/webhook/<секрет> → /webhook/<секрет>
|
||||
proxy_pass http://127.0.0.1:18788/webhook/;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 404;
|
||||
}
|
||||
|
||||
listen 443 ssl;
|
||||
ssl_certificate /etc/letsencrypt/live/astra.ruzzy.dev/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/astra.ruzzy.dev/privkey.pem;
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name astra.ruzzy.dev;
|
||||
server_tokens off;
|
||||
|
||||
# по HTTP секрет уже утёк в сеть; хотя бы не пишем его в лог и не редиректим
|
||||
location ^~ /marusia/ {
|
||||
access_log off;
|
||||
return 404;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# Вебхук Маруси (vhost astra.ruzzy.dev): не более 1 запроса/с с адреса
|
||||
limit_req_zone $binary_remote_addr zone=marusia_webhook:1m rate=1r/s;
|
||||
@@ -0,0 +1,16 @@
|
||||
# Только удалённый проброс 127.0.0.1:18788 для туннеля Маруси с rpi (stacks/astra-marusia)
|
||||
Match User marusia-tunnel
|
||||
AuthenticationMethods publickey
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
AllowTcpForwarding remote
|
||||
PermitListen 127.0.0.1:18788
|
||||
PermitOpen none
|
||||
GatewayPorts no
|
||||
AllowAgentForwarding no
|
||||
AllowStreamLocalForwarding no
|
||||
PermitTunnel no
|
||||
X11Forwarding no
|
||||
PermitTTY no
|
||||
PermitUserRC no
|
||||
MaxSessions 0
|
||||
@@ -1,12 +0,0 @@
|
||||
# Include inside the existing HTTPS server block on fr1 AFTER creating an SSH tunnel.
|
||||
# Reverse tunnel must bind only to fr1 127.0.0.1:18788 -> rpi 127.0.0.1:8788.
|
||||
# No public port 8788/18788; VK uses the existing HTTPS listener.
|
||||
location ^~ /marusia/webhook/ {
|
||||
access_log off;
|
||||
client_max_body_size 64k;
|
||||
limit_except POST { deny all; }
|
||||
proxy_connect_timeout 1s;
|
||||
proxy_read_timeout 5s;
|
||||
proxy_pass http://127.0.0.1:18788/webhook/;
|
||||
}
|
||||
# Add a limit_req zone in nginx http{} and apply its limit here before exposure.
|
||||
Reference in New Issue
Block a user