К основному содержимому

Безопасность MySQL на VPS: защита от взлома

Безопасность · 19.04.2026 · 4 мин чтения
Иллюстрация к статье «Безопасность MySQL на VPS: защита от взлома»

MySQL с настройками по умолчанию небезопасен. Открытый порт 3306, root без пароля, анонимные пользователи — всё это ворота для злоумышленников, которые сканируют интернет именно на такие признаки автоматическими ботами, а не вручную. Выполните эти шаги сразу после установки, до того как база наполнится реальными данными клиентов.

Базовая защита: mysql_secure_installation

sudo mysql_secure_installation

# Ответьте на вопросы:
# Set root password? YES -- придумайте сложный пароль
# Remove anonymous users? YES
# Disallow root login remotely? YES
# Remove test database? YES
# Reload privilege tables? YES

Запретить прослушивание на внешнем интерфейсе

# /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
bind-address = 127.0.0.1   # Только localhost
# или для IPv6:
bind-address = ::1

sudo systemctl restart mysql

После этой настройки к MySQL нельзя подключиться снаружи даже зная пароль — только с localhost или через SSH-туннель. Это закрывает 3306 порт для интернета без единой строчки firewall-правил.

Создавать отдельного пользователя для каждого приложения

-- Создать пользователя только для одной БД
CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'StrongPassword123!';
CREATE DATABASE myapp_db;
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp'@'localhost';
FLUSH PRIVILEGES;

-- Никогда не давать GRANT OPTION приложениям:
-- GRANT ALL PRIVILEGES ON *.* TO ... -- ЗАПРЕЩЕНО!

SSH-туннель вместо открытого порта

Общие принципы установки MySQL/MariaDB на VPS разобраны в статье MySQL/MariaDB на VPS, а защиту самого SSH-доступа стоит проверить по статье SSH Hardening.

# Подключиться к MySQL через SSH-туннель (без открытия 3306)
ssh -L 3306:127.0.0.1:3306 user@your-vps-ip -N -f

# Теперь можно подключаться локально:
mysql -u myapp -p -h 127.0.0.1 -P 3306

Разбор типичных ошибок и симптомов взлома

  • Host '1.2.3.4' is not allowed to connect to this MySQL server — на самом деле хорошая новость: bind-address или права пользователя работают как задумано и блокируют внешнее подключение.
  • Access denied for user 'root'@'localhost' (using password: YES) после множества неудачных попыток в auth.log — признак брутфорса по паролю root; проверьте /var/log/mysql/error.log на частоту и источник попыток.
  • Появление незнакомых баз данных или таблиц вида readme_to_recover — классический след атаки-вымогателя, при которой скрипт удаляет исходные таблицы и оставляет требование выкупа; восстанавливается только из резервной копии, сделанной до инцидента.
  • Резкий рост general_log без ручного включения — признак того, что кто-то получил доступ и включил логирование для сбора паролей приложений, передаваемых в запросах.

Мониторинг подозрительной активности

# Включить general log (кратковременно для диагностики!)
SET GLOBAL general_log = 'ON';
SET GLOBAL general_log_file = '/var/log/mysql/general.log';

# Найти медленные запросы
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;

# Просмотр текущих подключений
SHOW PROCESSLIST;

Не держите general_log включённым постоянно — он записывает КАЖДЫЙ запрос и быстро заполняет диск, а при высокой нагрузке ощутимо снижает производительность самой СУБД.

Сравнение мер защиты

Мера защитыПриоритетЧто закрывает
mysql_secure_installationКритическийПустой root, анонимные пользователи, тестовая БД
bind-address = 127.0.0.1КритическийПрямой доступ к порту 3306 из интернета
Отдельные пользователи для БДВысокийВзлом одного приложения не даёт доступ к другим базам
SSH-туннельВысокийУдалённое администрирование без открытого порта
Регулярный бэкапСреднийВосстановление после вымогательской атаки или ошибки

Когда этих мер недостаточно

  • Приложение и MySQL разнесены на разные серверы в одном ДЦ — тогда bind-address = 127.0.0.1 не подходит, нужен либо VPN между серверами, либо firewall с белым списком конкретных IP на порт 3306.
  • Несколько разработчиков подключаются к базе с разных рабочих машин — постоянные SSH-туннели для каждого неудобны; здесь уместнее bastion-хост с единой точкой входа и логированием сессий.
  • Нужна репликация master-slave между дата-центрами — трафик реплики обязан идти по TLS-соединению между MySQL-инстансами, простого запрета внешнего интерфейса недостаточно.

Как проверить, что защита работает

# Проверяем, что порт 3306 не виден снаружи
nmap -p 3306 your-vps-ip
# Ожидаем: filtered или closed, не open

# Проверяем, что bind-address применился
mysql -u root -p -e "SHOW VARIABLES LIKE 'bind_address';"

# Проверяем список пользователей и их хосты доступа
mysql -u root -p -e "SELECT user, host FROM mysql.user;"

Если сканирование порта снаружи не находит открытый 3306, а список пользователей не содержит анонимных записей и записей с хостом % для критичных аккаунтов — базовая защита настроена верно.

Статья помогла?
← Назад в базу знаний Задать вопрос поддержке