Безопасность, SMTP, очередь, DKIM, деплой на Jambotron (75.1–75.3) #1

Merged
Liosha84 merged 1 commits from fix/75-security-smtp into master 2026-11-05 03:45:08 +01:00
Owner

Пункты 75.1–75.3 чек-листа Jambotron v0.2.3: прототип → можно развернуть, не открывая дыр.

Безопасность (75.1)

  • нет открытого релея: на чужой домен — только после AUTH, иначе 550 5.7.1; после входа MAIL FROM — только свой адрес
  • права доступа: раньше любой вошедший читал, отмечал и удалял чужие письма и вложения по номеру — теперь только владелец, чужие → 404
  • имена вложений без ../ (выход из папки), заголовок скачивания безопасный
  • секреты без значений по умолчанию (DB_PASSWORD, JWT_SECRET, ≥ 32 байт), пароль admin123 и /api/simulate/receive — только профиль dev, регистрация закрыта, ящики только в своих доменах
  • docker-compose.prod.yml удалён: открытый релей, Postgres наружу с паролем secret, свой Caddy с docker.sock

Почта (75.2)

  • SMTP: разбор по строкам (пачка команд, строка в двух пакетах), 250 только после сохранения, иначе 451; лимит размера; база и DNS не в сетевом потоке
  • отправка: очередь outbound_queue (V2) с повторами ~22 ч и уведомлением о недоставке; Jakarta Mail, MX по приоритету, режимы off / mx / smarthost (Resend); старый клиент принимал 550 за успех и не проверял сертификат
  • DKIM: подпись utils-mail-dkim, проверка входящих — Apache jDKIM (старая проверяла чужие подписи нашим ключом); ключ после перезапуска читается (раньше — нет)
  • не сделано: TLS, IMAP (выключен), вложения входящих — в README «Не сделано»

Jambotron (75.3)

  • веб-клиент внутри jar, /api относительный; Dockerfile: Angular → Spring Boot → JRE не от root, health
  • docker-compose.jambotron.yml: секреты создаёт secrets-init при первом запуске, наружу только 8080, SMTP внутри, OUTBOUND_MODE=off
  • gradle-wrapper.jar был в .gitignore — сборка (и Dockerfile) не запускалась

Проверено: 26 тестов (SMTP настоящим клиентом и сокетом, GreenMail, DKIM подпись + проверка, очередь); живой прогон на временном Postgres: миграции, вход, письмо в ящик через веб и SMTP, релей отклонён, чужие письма — 404, ключ DKIM после перезапуска. Образ Docker целиком не собирал (на Contabo), фронтенд и jar собираются по отдельности.

— α

🤖 Generated with Claude Code

Пункты 75.1–75.3 чек-листа Jambotron v0.2.3: прототип → можно развернуть, не открывая дыр. **Безопасность (75.1)** - нет открытого релея: на чужой домен — только после `AUTH`, иначе `550 5.7.1`; после входа `MAIL FROM` — только свой адрес - **права доступа:** раньше любой вошедший читал, отмечал и удалял чужие письма и вложения по номеру — теперь только владелец, чужие → 404 - имена вложений без `../` (выход из папки), заголовок скачивания безопасный - секреты без значений по умолчанию (`DB_PASSWORD`, `JWT_SECRET`, ≥ 32 байт), пароль `admin123` и `/api/simulate/receive` — только профиль `dev`, регистрация закрыта, ящики только в своих доменах - `docker-compose.prod.yml` удалён: открытый релей, Postgres наружу с паролем `secret`, свой Caddy с `docker.sock` **Почта (75.2)** - SMTP: разбор по строкам (пачка команд, строка в двух пакетах), `250` только после сохранения, иначе `451`; лимит размера; база и DNS не в сетевом потоке - отправка: очередь `outbound_queue` (V2) с повторами ~22 ч и уведомлением о недоставке; Jakarta Mail, MX по приоритету, режимы `off` / `mx` / `smarthost` (Resend); старый клиент принимал `550` за успех и не проверял сертификат - DKIM: подпись `utils-mail-dkim`, проверка входящих — Apache jDKIM (старая проверяла чужие подписи нашим ключом); ключ после перезапуска читается (раньше — нет) - не сделано: TLS, IMAP (выключен), вложения входящих — в README «Не сделано» **Jambotron (75.3)** - веб-клиент внутри jar, `/api` относительный; Dockerfile: Angular → Spring Boot → JRE не от root, health - `docker-compose.jambotron.yml`: секреты создаёт `secrets-init` при первом запуске, наружу только 8080, SMTP внутри, `OUTBOUND_MODE=off` - `gradle-wrapper.jar` был в `.gitignore` — сборка (и Dockerfile) не запускалась **Проверено:** 26 тестов (SMTP настоящим клиентом и сокетом, GreenMail, DKIM подпись + проверка, очередь); живой прогон на временном Postgres: миграции, вход, письмо в ящик через веб и SMTP, релей отклонён, чужие письма — 404, ключ DKIM после перезапуска. Образ Docker целиком не собирал (на Contabo), фронтенд и jar собираются по отдельности. — α 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Liosha84 added 1 commit 2026-11-05 03:37:46 +01:00
- SMTP-сервер переписан: разбор по строкам, AUTH PLAIN/LOGIN, нет открытого релея,
  MAIL FROM только свой после входа, 250 только после сохранения (иначе 451), лимит размера
- отправка наружу: очередь outbound_queue (V2) с повторами ~22 ч и уведомлением о недоставке;
  Jakarta Mail, режимы off / mx / smarthost, байты письма не меняются (DKIM)
- DKIM: подпись utils-mail-dkim, проверка Apache jDKIM; ключ PKCS#8, старый PKCS#1 читается
- права: письма, папки, вложения — только владельцу (было: любой по номеру); имена вложений без ../
- секреты без значений по умолчанию (DB_PASSWORD, JWT_SECRET), регистрация закрыта,
  admin123 и /api/simulate/receive — только профиль dev
- веб-клиент внутри jar (относительный /api), Dockerfile в 3 этапа, не root, health;
  docker-compose.jambotron.yml: секреты создаются при первом запуске, наружу только 8080
- gradle-wrapper.jar был в .gitignore — сборка не запускалась
- тесты: 26 (SMTP реальным клиентом и сокетом, GreenMail, DKIM подпись+проверка, очередь)

α
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Liosha84 merged commit f744def6ed into master 2026-11-05 03:45:08 +01:00
Sign in to join this conversation.