Сервер выполняет три независимые функции:
Принимает почту от приложений по внутренней сети, подписывает DKIM-ключом evrotrans.net и отправляет наружу. Локальных ящиков нет — транзитный отправитель. Активно работает.
По расписанию заходит по SSH обратно на хост (как admin/user) и запускает обслуживающие скрипты: бэкапы, certbot, рестарт nginx/php/node. Сейчас в простое (задач нет).
Доступ к домашним каталогам пользователей. Фактически не используется (лог пуст).
Плюс инфраструктурные агенты: резервное копирование (Яндекс/Acronis), мониторинг (Zabbix), гостевой агент Yandex Cloud.
| Параметр | Значение |
|---|---|
| Платформа | Yandex Cloud + backup от Яндекс.Облака |
| CPU | 2 vCPU, Intel Xeon (Icelake) |
| RAM | 964 MiB (🟠 в обрез: ~81 MiB free, активный своп ~460 MiB) |
| Swap | 1.5 GiB zram (zram0+zram1) + /swapfile 1 ГБ |
| Диск | 16 GB (/dev/vda), / = 15 GB ext4, занято 74% |
| Внешний IP | 31.44.10.106 (Ставрополь), домен mail.evrotrans.net |
| Uptime | 343 дня |
flowchart TB NET["🌐 Интернет
31.44.10.106 (NAT)"] subgraph HOST["ХОСТ vm-evrotrans-yandex-mailer"] direction TB subgraph IF["Сетевые интерфейсы"] direction TB ETH0["eth0 — 10.128.0.20/24
основной (default, metric 100)
• SSH 48008 (админы)
• FTP 48080
• Yandex Cloud metadata 169.254.169.254
• external-IP, исходящий бэкап"] ETH1["eth1 — 10.150.0.20/24
сервисный/почтовый VPC (metric 200)
• Postfix 25 (только тут!)
сюда ходят app-серверы за почтой"] end subgraph BR["Docker bridges"] direction TB BRIDGE["br-2b94d6a4a048 — 172.18.0.0/16"] PF["postfix
172.18.0.3"] AH["autoheal
172.18.0.2"] DOCKER0["docker0 — 172.17.0.0/16
не используется (linkdown)"] CRON["crontab-контейнер
network_mode=host
(делит стек хоста)"] end end NET --> ETH0 NET --> ETH1 ETH1 -- "порт 25" --> BRIDGE BRIDGE --> PF BRIDGE --> AH class NET ext class ETH0,ETH1,BRIDGE,DOCKER0,IF,BR net class PF,AH mail class CRON svc class DOCKER0 ext classDef mail fill:#241a0c,stroke:#ffb454,color:#dbe4ee classDef svc fill:#10242b,stroke:#3fb6c9,color:#cfeef5 classDef net fill:#11202e,stroke:#4ea1ff,color:#dbe4ee classDef ext fill:#12161c,stroke:#5a6675,color:#cfd8e2
| Интерфейс | Подсеть | Назначение |
|---|---|---|
eth0 | 10.128.0.0/24 | Управление: SSH, FTP, внешний IP (NAT), метаданные Yandex Cloud, исходящий бэкап |
eth1 | 10.150.0.0/24 | Сервисная сеть: только сюда проброшен порт 25 Postfix |
br-2b94d6a4a048 | 172.18.0.0/16 | Внутренняя сеть Docker-стека (postfix ↔ autoheal) |
docker0 | 172.17.0.0/16 | linkdown, не задействован |
DNS: systemd-resolved (127.0.0.53), search-домены ru-central1.internal, auto.internal (Яндекс.Облако).
stable)
flowchart TB
subgraph HOST["ХОСТ vm-evrotrans-yandex-mailer"]
direction LR
PF["postfix
catatnight/postfix (2.11)
:25 → 10.150.0.20
+ OpenDKIM milter :12301
net: bridge .18"]
AH["autoheal
willfarrell/autoheal 1.2.0
следит за health контейнеров,
перезапускает нездоровые
⚠️ docker.sock:rw"]
CRON["crontab
ddan9/crontab
network_mode: host
планировщик (dormant)
→ SSH назад на хост
keys → /root/.ssh · host → /var/host"]
end
AH -. "управляет (docker.sock:rw)" .-> PF
AH -. "управляет (docker.sock:rw)" .-> CRON
class PF mail
class AH svc
class AH warn
class CRON svc
classDef mail fill:#241a0c,stroke:#ffb454,color:#dbe4ee
classDef svc fill:#10242b,stroke:#3fb6c9,color:#cfeef5
classDef warn fill:#2a1416,stroke:#ff5c5c,color:#ffd9d9
Три сервиса, restart: always, у всех no-new-privileges + apparmor=docker-default, privileged: false.
catatnight/postfix (Postfix 2.11.0, ~11 лет 🟠). Порт проброшен только 10.150.0.20:25.mydestination почти пуст — локальной доставки нет (релей).mynetworks=127.0.0.0/8 + SASL-auth (webmaster) — отправляют только аутентифицированные. Open-relay нет ✅.smtpd_milters = inet:localhost:12301 (OpenDKIM в том же контейнере); ключи в postfix/domainkeys/.security_level = may.Следит за контейнерами с healthcheck (интервал 60 с) и перезапускает нездоровые. Для этого монтирует /var/run/docker.sock:rw (управляет Docker'ом хоста).
Образ ddan9/crontab, network_mode: host. Обёртки в crontab/host/ заходят по SSH на localhost:48008:
| Скрипт | Действие |
|---|---|
cron_admin.sh | sshpass ssh r3ddan9@localhost "echo PASS | sudo -S bash -c '<cmd> &'" — команда под root |
cron_user.sh | то же, но как evrotrans без sudo |
*_key.sh | варианты по SSH-ключу (без пароля) |
initialize_keys.sh | генерит ключ контейнера и прогревает known_hosts |
sshpass и echo PASS | sudo -S, пароли — из .env (plaintext) и захардкожены в скриптах. Правильнее — SSH-ключи + sudoers NOPASSWD на конкретные команды. См. AUDIT_REPORT_mailer./home/evrotrans/stable/stable/
├── .env # конфиг и СЕКРЕТЫ (пароли, токены) — см. аудит
├── docker-compose.yml # описание 3 сервисов
├── postfix/
│ ├── config/main.cf
│ └── domainkeys/ # DKIM-ключи evrotrans.net (+ .bak)
├── crontab/
│ ├── config/ # расписания cron ← ПУСТО (dormant)
│ ├── host/ # обёртки SSH-запуска
│ ├── keys/ # SSH-ключи контейнера ← пусто
│ └── logs/cron.log # 9.9 MB спама "wakeup"
├── host/ # ★ БИБЛИОТЕКА ОБСЛУЖИВАЮЩИХ СКРИПТОВ (с web-сервера)
│ ├── cron_backup_catcher_*.sh / cron_home_backuper_*.sh / cron_backup_cleaner_*.sh
│ ├── cron_certbot_renew.sh
│ ├── bash_restart_{php,node,containters}.sh
│ └── .*.bak # ~30 архивных заданий (nginx, mysql, openvpn, api3, gds2 ...)
└── backup/config/
host/ оперируют путями /home/etrans/stable/{web,mysql,nginx,...} и контейнерами (stable_mysql_1, stable-certbot-1), которых на mailer нет — это общая библиотека, скопированная с web-сервера, здесь в основном инертна. config/ пуст, cron логирует только wakeup → автоматизация dormant.vsyvzoajoa, ключ шифрования, SSH-пароль V2LaYJMAc0 к 77.222.52.97) — см. AUDIT_REPORT_mailer §2-bis.
flowchart TB APP["App-серверы евротранса"] PORT["10.150.0.20:25"] PF["[postfix]"] DKIM["OpenDKIM
подпись (evrotrans.net)"] RCPT["🌐 Интернет
почтовые серверы получателей
(Gmail, Yandex, …)"] APP -- "SMTP + SASL-auth (webmaster), внутр. сеть" --> PORT PORT --> PF PF --> DKIM DKIM -- "прямая отправка по MX (relayhost пуст), TLS=may" --> RCPT class APP ext class PORT net class PF,DKIM mail class RCPT ext classDef mail fill:#241a0c,stroke:#ffb454,color:#dbe4ee classDef net fill:#11202e,stroke:#4ea1ff,color:#dbe4ee classDef ext fill:#12161c,stroke:#5a6675,color:#cfd8e2
flowchart TB CRON["[crontab контейнер]"] WRAP["cron_admin.sh / cron_user.sh
sshpass/ssh → localhost:48008"] SSHD["[sshd]"] HOST["скрипты host/
(как r3ddan9 sudo / evrotrans)"] HB["🏠 home_backuper
tar --lzma → openssl aes-256-cbc
(-k w7yNyNnJVx4N) → backup/{config,db,web}
database: mysqldump -p\"vsyvzoajoa\""] BC["📥 backup_catcher
sshpass scp -P 8008
etrans@77.222.52.97:…/backup_*.tar.gz"] CB["🔐 certbot renew
docker exec stable-certbot-1 certbot renew"] RC["♻️ restart_containers
compose down + system prune -af + up --build
(агрессивно!)"] CL["🧹 cleaner
удаление старых дампов/логов"] R77["🌐 бэкап-узел
77.222.52.97:8008"] CRON -- "по расписанию (config/ пусто = dormant)" --> WRAP WRAP --> SSHD SSHD -- "как r3ddan9 (sudo) / evrotrans" --> HOST HOST --> HB HOST --> BC HOST --> CB HOST --> RC HOST --> CL BC -. "scp" .-> R77 class CRON,WRAP svc class CRON warn class SSHD,HOST svc class WRAP warn class HB,BC,CB,CL svc class RC warn class R77 ext classDef svc fill:#10242b,stroke:#3fb6c9,color:#cfeef5 classDef ext fill:#12161c,stroke:#5a6675,color:#cfd8e2 classDef warn fill:#2a1416,stroke:#ff5c5c,color:#ffd9d9
tar(lzma) → AES-256-CBC → файл; «catcher» по scp стягивает архивы с 77.222.52.97:8008. Ключ шифрования зашит в скриптах и равен .env-ключу — шифрование декоративное (ключ рядом с данными).mms → 84.47.172.135:7771 (облако) с eth0.google_guest_agent → 169.254.169.254:80 (метаданные).r3ddan9 ← 94.255.11.90 → 10.128.0.20:48008.Сервер реально отправляет уведомительную почту от webmaster@evrotrans.net. Аутентификационная обвязка домена согласована:
| Механизм | В DNS | Состояние |
|---|---|---|
DKIM default._domainkey | v=DKIM1; k=rsa; p=MIGf… | ✅ совпадает с локальным ключом — подпись валидна |
| SPF | v=spf1 ip4:…31.44.10.106… include:spf.mail.ru ~all | ✅ IP сервера в списке (+ 4 IP парка) |
PTR 31.44.10.106 | evrotrans.net | ✅ совпадает с HELO/myhostname — важно для антиспама |
| DMARC | v=DMARC1; p=none; … | 🟠 p=none — только мониторинг, без принуждения |
| MX домена | 10 emx.mail.ru, beget, 50 mail.evrotrans.net | входящая на mail.ru/beget; этот хост — MX 50 (резерв), по сути исходящий |
p=none (поднять до quarantine/reject после анализа rua-отчётов).deferred с кодом 452-4.2.2 out of storage space (ящики получателей переполнены) и битые адреса (опечатка yndex.ru). Не проблема сервера, но признак устаревших списков рассылки.| Сервис | Порт | Назначение |
|---|---|---|
sshd | 48008 | Доступ админов и канал оркестрации cron-контейнера |
vsftpd | 48080 | FTP к домашним каталогам (не используется) |
zabbix-agent2 | 10050 | Мониторинг |
| Яндекс/Acronis Backup | localhost + 37845 | Резервное копирование, антивирус (mms, aakore, …) |
google-guest-agent | — | Управление ключами/пользователями из метаданных Yandex Cloud |
unattended-upgrades | — | Автообновления безопасности |
| Компонент | Версия | Заметка |
|---|---|---|
| ОС | Ubuntu 20.04.6 LTS | ядро 5.4.0-216 (актуальное) |
| Docker Engine | 24.0.2 | доступно обновление до 28 |
| Docker Compose | v2.18.1 | проект stable, 3/3 running |
| Postfix | 2.11.0 | 🟠 очень старый (образ ~11 лет) |
| autoheal | 1.2.0 | образ ~4 года |
| crontab | ddan9/crontab | кастомный образ, ~3 года |
restart: always.autoheal).mms 57 МБ + dockerd)./var/log/journal 1.2 ГБ без лимита, логи Acronis (файл 152 МБ), cron.log 9.9 МБ.p=quarantine.host/ — общая библиотека web-сервера, на mailer инертна. Убрать/усмирить dormant-контейнер..env и в скриптах, FTP cleartext, zabbix в группе docker, docker.sock в autoheal, NOPASSWD-orphan) подробно разобраны в аудите безопасности.