Files
admin/.tasks/harden-books-vds-exposed-ports.md
vitya 063910e265 incident(books-vds-es): true RCA — ransom-бот через открытый :9200, не оператор
Рецидив вчерашнего ES-инцидента вскрыл истинную причину. Вчерашняя
гипотеза «оператор в cutover попал на canonical» опровергнута.

Root cause: ES (stack 33) публиковал 0.0.0.0:9200 мимо traefik. Free-ES
7.10 без auth → порт открыт всему интернету. Ransom-бот сносил индексы
by-name (мимо Control #1 destructive_requires_name), оставлял read_me с
BTC-выкупом. accessLog (Control #2) пуст — бот шёл прямо в порт, не через
traefik. firewalld бесполезен (docker-publish обходит INPUT-зоны).

Fix (Control #3): убрана публикация host-порта из stack 33 (Portainer
PUT), дыра закрыта; re-restore epz/products/artmone из daily-2026-05-25.

Отдельный баг: epz-поиск падал у ОБОИХ тенантов — getTenantIdSeller(
config.get("tenant")) через node-config, а tenant не задан ни в
default.json, ни в env-маппинге (TENANT env = мёртвый груз). Добавлен
tenant в overlay default.json (slovo/bookva). products работал —
отдельный код-путь.

accessLog откатан (сторожил не ту дверь).

- wiki concept: correction-блок + секция «Рецидив 2026-05-29» + exposure-audit
- tasks: restore-es reopened+reclosed; new  harden-books-vds-exposed-ports
- NEXT_SESSION handoff

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 09:31:25 +03:00

4.3 KiB
Raw Blame History

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

  • 2026-05-29: exposure audit (таблица выше)
  • 2026-05-29: ES :9200 закрыт (в рамках инцидент-фикса)
  • 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