До основного вмісту

Безпека 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, а список користувачів не містить анонімних записів і записів із хостом % для критичних акаунтів — базовий захист налаштовано вірно.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці