Files
admin/.tasks/2026-05-29-00265-harden-books-vds-exposed-ports.md

63 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# harden-books-vds-exposed-ports
## Goal
Закрыть/ограничить публично торчащие host-порты на books VDS (89.253.255.133). Выявлены
во время инцидента `restore-elasticsearch-indices-books-vds` (2026-05-29): ES был снесён
ransom-ботом через открытый `0.0.0.0:9200` в обход traefik+firewalld. Тот же класс дыры
(docker-publish обходит firewalld INPUT-зоны) зияет ещё на ряде stateful-сервисов. Цель —
ни один stateful-сервис не должен быть доступен с публичного IP напрямую; доступ либо через
traefik (под auth), либо по внутренней docker-сети, либо по SSH-туннелю для admin.
## Exposure audit (2026-05-29, `docker ps` + `ss -tlnp`)
| Сервис | Порт наружу | Auth на сервисе | Действие |
|---|---|---|---|
| `elasticsearch` | ~~`0.0.0.0:9200`~~ | ❌ free-ES без auth | ✅ ЗАКРЫТ (Fix #3, инцидент) |
| `mongo` | `0.0.0.0:27017` | ✅ enabled | убрать публикацию (app ходит по docker-сети) |
| `books-db` (mariadb) | `0.0.0.0:3306` | ✅ root+pass | убрать публикацию / SSH-туннель для admin |
| `bookva-db` (mariadb) | `0.0.0.0:33306` | ✅ | убрать публикацию |
| `minio` | `0.0.0.0:9000` | ✅ | оставить только через traefik (minio.kzntsv.site) |
| `bookva-minio` | `0.0.0.0:9001` | ✅ | то же |
| rsync | `:873` | ? проверить | проверить нужен ли наружу |
| imgproxy / imgproxy-nginx / proxy-chain | `:8787/8788/8778` | ? | проверить, internal? |
## Key files / endpoints
- Portainer API `https://portainer.kzntsv.site` (key в `pass books-vds/full-env`), PUT `/api/stacks/<id>?endpointId=1` — паттерн как в Fix #3 (убрать `ports:` блок из compose).
- Stack ids: см. `.wiki/entities/books-vds.md` § Стек (2233). mongo=31, books-db=32, minio=30, ES=33. bookva-* стек(и) — id уточнить через Portainer API list.
- firewalld активен но docker его обходит — закрытие через docker port-publish, НЕ через firewalld rules.
## Decisions log
- 2026-05-29: Не закрывать в emergency-режиме инцидента — БД credentialed (не дыра-нараспашку как free-ES), и публикация может использоваться для внешнего admin (DBeaver/Compass/mc). Нужно сперва проверить по каждому: ходит ли приложение через host-порт или по docker-сети, и нужен ли внешний admin-доступ (тогда SSH-туннель вместо публикации).
## Open questions
- [ ] Каждый сервис: приложение коннектится через `service-name:port` (docker DNS) или через host-порт? Если через docker-сеть → публикацию убрать безопасно.
- [ ] Нужен ли кому-то внешний admin к mongo/mariadb? Если да → SSH local-forward, не публичный порт.
- [ ] rsync:873 — это backup-pipeline или забытый демон? Проверить.
- [ ] imgproxy/proxy-chain порты — реально нужны наружу или artefact?
## Completed steps
- [x] 2026-05-29: exposure audit (таблица выше)
- [x] 2026-05-29: ES :9200 закрыт (в рамках инцидент-фикса)
- [x] 2026-05-29: проверена auth — mongo/mariadb/minio требуют креды (не auth-less)
## Notes
Главный learning из инцидента: auth должна быть **на самом сервисе**, не только в
traefik-мидлваре. firewalld не защищает от docker-publish. См.
`.wiki/concepts/es-destructive-delete-incident-2026-05-26.md` § «Рецидив 2026-05-29».
## Branch
n/a (admin ops)
## Status
ready 2026-05-29
<!-- created-by: vitya@.admin-exec / 2026-05-29 / trigger: exposure-audit во время ES ransom-incident — 5 stateful-сервисов с публичными host-портами -->