Knowledge Base

Публично открытый MySQL-порт 3306

Почему это критично

Категория: Server Hardening · Риск: critical

Почему это критично

Публичный MySQL-порт почти всегда является ошибкой конфигурации. База данных не должна быть частью внешней поверхности сайта. Даже без успешного входа открытый порт привлекает автоматические сканеры, brute-force, попытки эксплуатации старых версий и сбор баннеров.

Для production-сайта нормальная схема выглядит так:

Internet -> Nginx/Reverse Proxy -> Application -> MySQL in private network

MySQL должен быть доступен приложению, backup-задачам и администраторам через защищённый канал, но не любому адресу из интернета.

Быстрая проверка

На сервере:

sudo ss -tulpen | grep ':3306'

Опасный признак:

0.0.0.0:3306
:::3306

Более безопасный вариант:

127.0.0.1:3306
172.18.0.2:3306
10.0.0.5:3306

Немедленное закрытие через UFW

sudo ufw deny 3306/tcp
sudo ufw status numbered

Если нужен доступ с конкретного bastion/VPN IP:

sudo ufw allow from 10.8.0.0/24 to any port 3306 proto tcp
sudo ufw deny 3306/tcp

Исправление Docker Compose

Небезопасно:

services:
  db:
    image: mysql:8
    ports:
      - "3306:3306"

Безопаснее:

services:
  db:
    image: mysql:8
    expose:
      - "3306"
    networks:
      - internal

  app:
    networks:
      - internal

networks:
  internal:
    internal: true

Если приложение и база в одной compose-сети, подключайтесь к host `db:3306`, а не к публичному IP.

Ограничение bind-address

Для MySQL/MariaDB проверьте конфигурацию:

sudo grep -R "bind-address" /etc/mysql/ /etc/my.cnf* 2>/dev/null

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

[mysqld]
bind-address = 127.0.0.1

После изменения:

sudo systemctl restart mysql
sudo ss -tulpen | grep ':3306'

Проверка пользователей MySQL

SELECT user, host FROM mysql.user;

Записи вида `user | %` разрешают вход с любого host, если сетевой путь открыт. Для production лучше задавать конкретный host или использовать локальное/private подключение.

Что сделать после обнаружения

1. Закрыть порт на firewall. 2. Проверить `docker ps`, `ss`, firewall провайдера. 3. Проверить MySQL users и пароли. 4. Просмотреть логи на частые неуспешные входы. 5. Обновить runbook деплоя, чтобы порт 3306 больше не публиковался.