Изоляция instance
Если instance на одном сервере принадлежат разным людям, считайте, что любой из них может быть враждебным. Правило Pano Host: никогда не доверяй instance. Всё, что вы тарифицируете или ограничиваете — трафик, CPU, память, диск, почта, версия, аптайм, — измеряется снаружи.
Защита контейнера
Запускайте каждый контейнер instance:
- от своего непривилегированного id пользователя (
--user) с Docker user namespace remapping (userns-remap, для всего демона); - с
--cap-drop=ALLи--security-opt no-new-privileges; - с профилем seccomp по умолчанию и AppArmor;
- с
--pids-limit, лимитом памяти и лимитом CPU; - с корневой ФС только для чтения: запись разрешена только в
/data, для/tmp— tmpfs; - с лог-драйвером
localи ротацией с ограничением размера.
Никогда не монтируйте в instance сокет Docker или пути хоста, кроме его собственной папки данных в /data. Если владельцы управляют файлами через веб-файловый менеджер, выполняйте эти операции в короткоживущем вспомогательном контейнере от id пользователя instance, а не от root на хосте.
Отдельная сеть для каждого instance
Создайте отдельную bridge-сеть Docker для каждого instance. Подключайте общие сервисы — reverse proxy, сервер БД, почтовый relay — к каждой сети instance, а не собирайте все instance в одной общей сети. Тогда instance не видят друг друга.
Для сотен instance задайте Docker небольшие пулы адресов (default-address-pools, например подсети /27), чтобы поместились все сети.
Пользователи базы данных
Запустите один сервер MariaDB (или MySQL) и дайте каждому instance свою базу. Создайте по два пользователя на instance:
| Пользователь | Кто использует | Примечания |
|---|---|---|
| внутренний | сам Pano Instance | передаётся через переменные PANO_DB_* |
| внешний | владелец, снаружи | необязательный; TLS обязателен, необязательный список разрешённых IP, свой сброс пароля |
Благодаря разделению владелец, сменивший пароль или список IP, никогда не сломает работающий instance. Давайте каждому пользователю права только на его базу и защищайтесь от шумных соседей лимитами на пользователя, например MAX_USER_CONNECTIONS и ограничением времени запросов.
Исходящий трафик
Pano Host фильтрует исходящий трафик каждой сети instance (nftables):
- разрешает DNS к резолверу самого сервера и TCP 80, 443, 465 и 587;
- блокирует TCP 25, чтобы instance не рассылали спам напрямую;
- блокирует адреса облачных метаданных (
169.254.169.254,fd00:ec2::254), другие сети instance и внутренние адреса сервера, кроме собственной БД и почтового relay instance; - открывает дополнительные порты только по просьбе владельца;
- замедляет аномальный исходящий трафик и уведомляет администратора.
Почтовый relay
Раз порт 25 закрыт, instance отправляют почту через ваш relay: SMTP-сервис в каждой сети instance, который передаётся в Pano как PANO_SMTP_*. Дайте каждому instance свои учётные данные relay, чтобы relay считал письма по instance и применял дневной лимит. Владельцы по-прежнему могут указать в Pano свой SMTP-сервер.
Квоты измеряются снаружи
Не спрашивайте instance, сколько он использовал. Измеряйте:
- Диск: Pano Host выдаёт каждому instance разреженный образ диска, смонтированный через loop, как жёсткую квоту. На нём лежат и
/data, и файлы базы данных instance, так что база тоже учитывается. - Трафик: считайте на reverse proxy.
- CPU и память: задайте лимиты Docker и читайте потребление из Docker.
- Почта: считайте на relay.
- Версия и аптайм: берите из jar в
/dataи из состояния контейнера.