Initial release of Kaskad

Каскадная маршрутизация русских сайтов через свой набор RU-серверов
с failover, Telegram-ботом и веб-интерфейсом.

- bin/        — failover-script, route/domain helpers, ams/ru bootstrap
- bot/        — Telegram-бот (Python, long-poll)
- webui/      — Flask single-page dashboard
- docs/       — установка, архитектура, API бота и WebUI
- examples/   — шаблоны конфигов
This commit is contained in:
andrey271192
2026-05-02 09:13:10 +03:00
parent 7a2a41510c
commit 209caa81a8
22 changed files with 2802 additions and 0 deletions

80
docs/webui.md Normal file
View File

@@ -0,0 +1,80 @@
# Web UI
Flask-приложение, бежит рядом с TG-ботом (на одном из ам. серверов). Использует **те же** скрипты и тот же `ru-servers.json`, что и бот.
## Возможности
- **Дашборд** — состояние туннелей всех ам. серверов: куда подключены, возраст handshake
- **Force-переключение** на любой RU-сервер одной кнопкой
- **CRUD RU-серверов** — добавление/удаление с веб-формы (бот сам пробрасывает SSH ключи и поднимает WG)
- **CRUD ам. серверов** — то же
- **CRUD доменов** — добавить/удалить с автоматическим резолвом
- **CRUD IP/CIDR** — добавить/удалить любые подсети
- **Просмотр базовых подсетей** — read-only
- **Фильтры по доменам и IP** — для удобства поиска
## API
Все endpoint'ы под `/api/`, все требуют HTTP basic auth.
| Метод | Путь | Тело | Описание |
|---|---|---|---|
| GET | `/api/state` | — | Полное состояние JSON |
| POST | `/api/use` | `{"id":"primary"}` | Force-переключить все ам. на этот RU |
| POST | `/api/server` | `{host,id,user,ssh_port,priority,...}` | Добавить новый RU |
| DELETE | `/api/server/<id>` | — | Удалить RU |
| POST | `/api/ams` | `{host,id,user,ssh_port,xray_iface,...}` | Добавить новый ам. |
| DELETE | `/api/ams/<id>` | — | Удалить ам. |
| POST | `/api/domains` | `{"domains":["vk.com",...]}` | Добавить домены |
| DELETE | `/api/domains` | `{"domains":[...]}` | Удалить домены |
| POST | `/api/domains/refresh` | — | Перерезолвить |
| POST | `/api/ips` | `{"ips":["1.2.3.4/32",...]}` или `{"ips":"text with IPs"}` | Добавить |
| DELETE | `/api/ips` | то же | Удалить |
| POST | `/api/ips/clear` | — | Очистить все доп. IP |
Пример:
```bash
curl -u admin:PASS https://your-host/api/state | jq
curl -u admin:PASS -X POST https://your-host/api/use -d '{"id":"primary"}' -H 'Content-Type: application/json'
```
## Безопасность
- Basic auth обязателен. `KASKAD_WEB_PASS` должен быть длинным и случайным (см. `webui.env.example`)
- По умолчанию слушает на `0.0.0.0:8088`. **Рекомендуется** поставить за HTTPS reverse-proxy (nginx/caddy) с Let's Encrypt
- Если хочется привязать только к localhost — `KASKAD_HOST=127.0.0.1` и пользоваться через SSH-туннель: `ssh -L 8088:localhost:8088 root@ams1`
- Пароли SSH (`password=` при `/server-add`, `/ams-add`) передаются по HTTPS только если веб за reverse-proxy. Без HTTPS не передавай пароли через WebUI — используй ключи (см. `/bot-key`)
## Конфиг (env-переменные)
| Переменная | Дефолт | Описание |
|---|---|---|
| `KASKAD_WEB_USER` | `admin` | Логин для basic auth |
| `KASKAD_WEB_PASS` | (нет) | Пароль; ОБЯЗАТЕЛЬНО задать |
| `LOCAL_HOST` | `ams1` | Имя локального ам. сервера |
| `LOCAL_IP` | `127.0.0.1` | Локальный IP — определяет, какой ам. читать локально без SSH |
| `KASKAD_HOST` | `0.0.0.0` | Адрес для bind |
| `KASKAD_PORT` | `8088` | Порт |
| `KASKAD_SSH_KEY` | `/root/.ssh/id_ed25519` | SSH-ключ для управления другими серверами |
| `KASKAD_SERVERS_JSON` | `/etc/wireguard/ru-servers.json` | Путь к конфигу |
## nginx reverse-proxy (пример)
```nginx
server {
listen 443 ssl http2;
server_name kaskad.example.com;
ssl_certificate /etc/letsencrypt/live/kaskad.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/kaskad.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8088;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 600s; # для долгих /add-domain пачкой
}
}
```
И в WebUI поставить `KASKAD_HOST=127.0.0.1`, не открывать 8088 наружу.