Files
knowledge-base/projects/dttb/mailcow-dttb.md
dttb 58fd3fa17a mailcow dttb: спам-фикс, SSL, апдейт 2026-05c, BIMI+подпись, Roundcube, сбор почты
- фикс входящего спама: No-SNAT на OpenWrt (видел все письма как 10.0.0.1)
- SSL mail-портов: cert из NPM + cron-синхрон на Proxmox
- апдейт mailcow 2026-01 -> 2026-05c; урок: forward-zone unbound обязателен (RKN режет рекурсию)
- логотип UI, BIMI-SVG (Tiny PS) + хостинг, HTML-подпись
- Roundcube на /rc (bind-mount, public_html)
- внешний сбор почты Яндексом (IMAP/POP3)
- snippets: sync-mailcow-cert.sh, dttb-mail-branding/

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 01:43:19 +03:00

18 KiB
Raw Blame History

date, type, tags
date type tags
2026-03-04 project
dttb
mail

Mailcow dttb.ru (VM 107, 10.0.0.107)

Версия: 2026-05c (обновлено 2026-06-28 с 2026-01 через ./update.sh -f; снапшот отката qm snapshot 107 = pre_update_20260627, удалить после недели стабильной работы). 🚨 УРОК АПДЕЙТА: при апдейте откатывал tracked-правки конфигов и НЕ вернул forward-zone в unbound.conf → почта легла (postfix не резолвил MX/домены отправителей → reject 450 Domain not found на всё входящее). Рекурсивный unbound на этом провайдере НЕ работает (RKN режет доступ к корневым DNS), forward-zone — load-bearing. Восстановлено возвратом forward-zone (см. ниже). На будущих апдейтах unbound.conf forward-zone НЕ удалять / вернуть сразу после. postfix-overrides (main.cf) mailcow восстанавливает сам.

Общая информация

  • Web UI: https://mail.dttb.ru (через NPM proxy host #25, SSL cert #106)
  • Admin: admin / 1qaz!QAZ
  • API key: dttb-mailcow-api-2026 (API_ALLOW_FROM: 172.22.1.1,127.0.0.1,10.0.0.0/24)
  • OS: Ubuntu 24.04, 4 cores, 8GB RAM, 100GB disk
  • SSH: root (ключ claude-code ed25519), cloud-init static IP
  • Клонирован с: VM 106 НИИКН (mail.niikn.com), перенастроен 2026-03-04

Домен и ящики

Подключение

  • SMTP: mail.dttb.ru:587 (STARTTLS) или mail.dttb.ru:465 (SMTPS)
  • IMAP: mail.dttb.ru:993 (SSL)
  • POP3: mail.dttb.ru:995 (SSL)
  • Sieve: mail.dttb.ru:4190

Конфигурация

  • Install dir: /opt/mailcow-dockerized/
  • MAILCOW_HOSTNAME: mail.dttb.ru
  • SKIP_LETS_ENCRYPT: y (SSL через NPM)
  • SKIP_UNBOUND_HEALTHCHECK: y
  • Unbound: ⚠️ ОБЯЗАТЕЛЬНА forward-zone к 8.8.8.8/1.1.1.1 в data/conf/unbound/unbound.conf (в самом конце файла). Рекурсивный резолвинг на этом провайдере НЕ работает (RKN режет корневые DNS) → без forward почта не доставляется (postfix reject 450 Domain not found). Это НЕ band-aid, а необходимость. 2026-06-28 убрал по ошибке → положил почту, вернул. Минус 8.8.8.8: Spamhaus отшивает публичные резолверы, но postscreen_dnsbl_sites завязан на конкретные коды 127.0.0.x → ложных reject не даёт. После рестарта unbound даёт резолв через ~5-10 сек (не паниковать раньше). Проверка: docker exec ...unbound... drill gmail.com @127.0.0.1 (ANSWER:>0).
  • SSL: web (:443) — cert NPM; mail-порты (25/465/587/993/995) — тот же LE-cert из NPM, синхронизируется cron'ом (см. ниже «SSL на mail-портах»)
  • Docker контейнеры: 18 шт (postfix, dovecot, rspamd, nginx, mysql, redis и др.)

OpenWrt проброс портов → 10.0.0.107

Порт Протокол Назначение
25 TCP SMTP (приём почты)
465 TCP SMTPS
587 TCP Submission (отправка)
993 TCP IMAPS
995 TCP POP3S
4190 TCP Sieve

DNS записи (dttb.ru → Spaceweb)

Тип Имя Значение
A mail 176.62.183.186
MX @ mail.dttb.ru. (приоритет 10)
TXT @ v=spf1 ip4:176.62.183.186 a mx ~all
TXT _dmarc v=DMARC1; p=quarantine; ruf=mailto:admin@dttb.ru
TXT dkim._domainkey v=DKIM1;k=rsa;t=s;s=email;p=... (2048-bit)

Статус проверки (2026-06-18)

Сквозная диагностика «снаружи» (без шелла на VM):

  • Приём: порт 25 открыт из интернета, MX отвечает 250 mail.dttb.ru, в INBOX реальное входящее от it5870@yandex.ru.
  • Отправка: письмо с admin@dttb.ru через :587 доставлено на внешний сервер за секунды → исходящий 25-й порт у Istranet НЕ заблокирован. Письмо DKIM-подписано (d=dttb.ru, s=dkim), SPF/DMARC выровнены.
  • IMAP :993 и SMTP-submission :587 (AUTH LOGIN) работают (admin@dttb.ru / 1qaz!QAZ).
  • ⚠️ PTR отсутствует — единственная дыра доставляемости. Strict-провайдеры (Gmail → спам, Mail.ru → reject) штрафуют письма с IP без reverse DNS.
  • ⚠️ IP = OOO Istranet (netname istranet, RU), не Spaceweb. PTR ставит Istranet (как интернет-провайдер по этому WAN-IP), не регистратор DNS.
  • 🔸 В DNS висит лишний TXT @ "mailru-domain: 09KURdxlbSVmAm4O" — остаток попытки привязать Mail.ru для домена; на Mailcow не влияет, можно убрать.

Брендинг писем — BIMI + подпись (2026-06-28)

Цель: логотип dttb при отправке писем со всех ящиков.

BIMI (лого-аватар у отправителя в инбоксе Apple Mail и др.; Gmail/Yahoo требуют платный VMC ~$1000/год — пока без него):

  • SVG (профиль SVG Tiny PS, конверт без текста — шрифт SG для BIMI не годится): data/web/bimi/dttb.svg на mailcow → публично https://mail.dttb.ru/bimi/dttb.svg (200, image/svg+xml, проверено снаружи). Исходник в snippets/dttb-mail-branding/dttb-bimi.svg.
  • DMARC уже p=quarantine — BIMI-eligible.
  • ОСТАЛОСЬ (DNS, у Олега/в Spaceweb-панели vps.sweb.ru): TXT default._bimi.dttb.ru = v=BIMI1; l=https://mail.dttb.ru/bimi/dttb.svg;. API sweb требует сессию панели (токена в vault нет) — автоматом не добавить.

Подпись с логотипом (snippets/dttb-mail-branding/signature.html, лого-PNG https://mail.dttb.ru/bimi/dttb-logo.png):

  • Готовый HTML-сниппет под вставку в SOGo (Preferences→Mail) и в клиенты (Thunderbird/iPhone).
  • ⚠️ Серверного футера «на всех клиентов» НЕ ставил: вставка тела после DKIM-подписи Rspamd ломает DKIM. Корректный путь — footer-milter ДО Rspamd (отдельный проект, не делал).

Внешний сбор почты (Яндекс и др.) — 2026-06-28

Чтобы внешний сервис (напр. Яндекс) забирал почту из ящика dttb.ru к себе. Настраивается на стороне Яндекса (он подключается к нам), на mailcow ничего не нужно — :993/:995 открыты из интернета, cert валиден, imap/pop3 у всех ящиков dttb включены (attributes.imap_access/pop3_access=1).

Параметры подключения для любого сборщика:

IMAP POP3
Сервер mail.dttb.ru mail.dttb.ru
Порт 993 995
Шифрование SSL SSL
Логин полный адрес (support@dttb.ru) то же

Яндекс: ⚙️Все настройки → «Сбор почты с других ящиков» → адрес+пароль (сервер подхватится). Яндекс-сборщик по умолчанию IMAP (не POP3, как было раньше). IMAP = зеркалит всю структуру папок + статусы, но нельзя выбрать целевую папку. POP3 = только Входящие, зато можно сложить в конкретную папку/метку. Первый сбор за пару минут, далее от неск. раз/час до раза в неск. дней (решает Яндекс). Справка: https://yandex.ru/support/mail/web/preferences/collector.html

Обратное направление (mailcow забирает с Яндекса в ящик dttb): mailcow UI → ящик → Sync jobs, IMAP imap.yandex.ru:993, для Яндекса нужен пароль приложения (не основной).

Roundcube — второй вебмейл (2026-06-28)

Поставлен рядом с SOGo, на https://mail.dttb.ru/rc/ (родной nginx mailcow, без нового поддомена/DNS/NPM — wildcard *.dttb.ru НЕТ). Скин Elastic, заголовок «dttb Mail».

  • Контейнер roundcube-mailcow (roundcube/roundcubemail:latest-fpm-alpine) через docker-compose.override.yml.
  • БД roundcube в mysql-mailcow (юзер roundcube / df8de490bea7641fd34904cc95b29428), схема создаётся образом сама (initdb.sh --update).
  • IMAP ssl://dovecot:993, SMTP tls://postfix:587 (внутр. алиасы сети); cert CN=mail.dttb.ru ≠ имя контейнера → в data/conf/roundcube/extra.php выключена проверка cert (imap/smtp_conn_options verify_peer=false) — трафик внутри docker-бриджа.
  • Файлы вебрута: bind ./data/web/rc/var/www/html (НЕ named-том: у nginx mailcow rootfs read-only, том в /web/rc не примонтировать). nginx видит их через существующий /web. Новый Roundcube 1.6 — вебрут в public_html/, поэтому в nginx alias = /web/rc/public_html/, SCRIPT_FILENAME = /var/www/html/public_html/$rcfile.
  • nginx-локация: data/conf/nginx/site.roundcube.custom (подключается через include site.*.custom в sites-default). ROUNDCUBEMAIL_REQUEST_PATH=/rc/.
  • Вход проверен (admin@dttb.ru → 302 _task=mail). Плагины: archive, zipdownload, managesieve.
  • ⚠️ На апдейтах mailcow override и data/web/rc untracked — переживают; при больших обновлениях Roundcube — docker compose pull roundcube-mailcow && up -d (схема обновится сама).

Логотип UI (2026-06-28)

Кастомный логотип dttb (монограмма) на странице входа/в шапке. Хранится в Redis ключами MAIN_LOGO + MAIN_LOGO_DARK как data:image/png;base64,... (как делает UI → Customize). Поставлен PNG (не SVG: в SVG текст шрифтом SG, который в <img> не доступен → ставится дефолтный). Источник: ~/Downloads/export/dttb-01-monogram.png (ужат 2048→1024, лимит mailcow 1920). Сброс: UI → Customize → Reset, или redis-cli DEL MAIN_LOGO MAIN_LOGO_DARK.

SSL на mail-портах (фикс 2026-06-27)

SKIP_LETS_ENCRYPT=y → ACME-контейнер mailcow ничего не делает. Cert для mail-портов владеет NPM (npm-106, ECDSA LE, авто-продление). При установке (Mar 7) его положили в data/assets/ssl/ вручную и забыли про продление → cert протух 2 июня 2026, клиенты IMAP/SMTP ругались на сертификат. Решение: авто-синхрон cert из NPM в mailcow.

  • Скрипт: /root/sync-mailcow-cert.sh на Proxmox 10.0.0.250 (копия в snippets/sync-mailcow-cert.sh).
  • Берёт pct exec 103 -- cat /data/compose/2/letsencrypt/live/npm-106/{fullchain,privkey}.pem, сравнивает fingerprint с 10.0.0.107:/opt/mailcow-dockerized/data/assets/ssl/cert.pem, при отличии — бэкап + замена + reload postfix/dovecot/nginx.
  • SSH Proxmox→mailcow по ключу /root/.ssh/mailcow_sync.
  • Cron: /etc/cron.d/mailcow-cert-sync — ежедневно 04:30, лог /var/log/mailcow-cert-sync.log.
  • Ручной прогон: /root/sync-mailcow-cert.sh.
  • Cert: ECDSA P-384, LE E-series; пару проверять по pubkey (openssl rsa на нём врёт — даёт пустой modulus).

⚠️ КОРНЕВОЙ ФИКС входящего спама (2026-06-27)

Жалоба: письма на support@dttb.ru (новый ящик) падают в спам, на старые ящики — нет. Корень: на домашнем OpenWrt (10.0.0.1) у LAN-зоны было masq=1. Входящее WAN:25 → DNAT → 10.0.0.107 уходило в LAN-зону и SNAT'илось в 10.0.0.1 → postfix/rspamd видели source = 10.0.0.1 для ВСЕХ внешних писем. Следствие на каждом входящем: RDNS_NONE=2.0 + HFILTER_HOSTNAME_UNKNOWN=8.5 (+10.5), а у строгих отправителей ещё R_SPF_FAIL=8.0 (SPF против 10.0.0.1) → reject (так резались «Welcome to NetBird»). Бьёт по всему серверу; старый ящик спасал только обученный Bayes (ham 3..5), новый support@ тонул. Фикс (UCI, не сырой nft — грабли fw4): на 10.0.0.1 добавлено config nat 'No-SNAT-to-Mailcow' (src=lan, proto=tcp, dest_ip=10.0.0.107, target=ACCEPT) + fw4 reload. Стоит в srcnat до masquerade. Проверено: тест с внешнего 89.111.140.86 → rspamd увидел реальный 89.111.140.86 (не 10.0.0.1). Для отправителей с нормальным PTR/MX/DKIM (Яндекс/Gmail) +10.5 больше не срабатывает. Не трогал глобальный lan masq=1 (на нём может висеть VPN/podkop-маршрутизация) — фикс точечный и обратимый (uci delete firewall.@nat[0]).

  • 🔸 SSH-доступ к VM не работает ни одним ключом (id_rsa «claude-code-matrix-project», id_ed25519, ключ Proxmox). VM клонирована с НИИКН VM 106 → несёт чужой authorized_keys. Управление возможно через web-UI (admin/1qaz!QAZ); для шелла — добавить ключ через Proxmox console.

Вариант «почтовый шлюз через VPS» (оценка 2026-06-18)

Идея: пускать почту через статичный VPS с чистым IP+PTR, чтобы не зависеть от Istranet. Проверил исходящий :25 на всех VPS Олега:

VPS Провайдер Исходящий :25 Вывод
vm-nano 158.255.0.139 (в КБ = «доменный шлюз» umnybot) NL блок для почты НЕ годится
Finland 202.71.12.186 Hostkey EU блок (egress после взлома 04-24) НЕ годится
swtest 89.111.140.86 SpaceWeb RU открыт (достучался до gmail MX) единственный пригодный

⚠️ «Доменный шлюз» из КБ (vm-nano) — это HTTP-reverse-proxy (NPM), к SMTP неприменим, и его провайдер режет 25. ⚠️ swtest на 2026-06-18: диск 100% (9.3/9.8 ГБ), RAM свободно ~367 МБ, PTR нет → перед использованием нужна чистка диска + заявка в SpaceWeb на rDNS. Корень: почта dttb уже работает на приём и отправку с домашнего IP; единственная дыра — PTR. Любой путь (Istranet PTR или VPS-smarthost) всё равно упирается в заявку провайдеру на PTR. VPS-вариант оправдан, только если Istranet откажет в PTR или нужно скрыть домашний IP.

TODO

  • PTR: запросить у OOO Istranet запись 186.183.62.176.in-addr.arpa → mail.dttb.ru (даст FCrDNS, A mail→176.62.183.186 уже есть). Главный пункт для доставляемости. (2026-04-18, проверено 2026-06-18 — всё ещё нет)
  • Добавить rua=mailto:admin@dttb.ru в DMARC для агрегированных отчётов (сейчас только ruf)
  • Восстановить SSH-ключ на VM 107 через Proxmox console

Mailcow HomeLab (VM 107, 10.0.0.107)

  • Web UI: https://mail.dttb.ru (через NPM proxy host #25)
  • Admin: admin / 1qaz!QAZ
  • API key: dttb-mailcow-api-2026
  • Домен: dttb.ru (добавлен), DKIM: selector=dkim, 2048-bit
  • Ящики: admin@dttb.ru, noreply@dttb.ru (пароль: 1qaz!QAZ)
  • SMTP: 10.0.0.107:587, STARTTLS, LOGIN auth
  • Клон с VM 106 НИИКН, MAILCOW_HOSTNAME=mail.dttb.ru
  • SSH: root (ключ claude-code ed25519), cloud-init IP static
  • Unbound: forward-zone к 8.8.8.8/1.1.1.1 (обязательно, иначе DNS fail)
  • SSL: self-signed для mail.dttb.ru, NPM cert ID:106 для HTTPS web
  • OpenWrt проброс: 25,465,587,993,995,4190 → 10.0.0.107
  • DNS (Spaceweb): A mail→176.62.183.186, MX→mail.dttb.ru, SPF, DMARC, DKIM настроены