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

Безпечне налаштування MariaDB та MySQL на VPS

Безпека · 19.04.2026 · 6 хв читання
Ілюстрація до статті «Безпечне налаштування MariaDB та MySQL на VPS»

База даних — найцінніший актив більшості веб-застосунків. Її компрометація означає витік даних користувачів, паролів і комерційної інформації. Правильна конфігурація MySQL/MariaDB критично важлива.

Первинний захист: mysql_secure_installation

mysql_secure_installation
# Відповідаємо:
# Validate password: Y (увімкнути перевірку складності)
# Remove anonymous users: Y
# Disallow root login remotely: Y
# Remove test database: Y
# Reload privilege tables: Y

Створення користувачів з мінімальними правами

mysql -u root -p

-- Створити користувача лише для однієї БД
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'StrongPass123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON myapp.* TO 'webapp'@'localhost';

-- Лише для читання (для аналітики)
CREATE USER 'analytics'@'localhost' IDENTIFIED BY 'ReadOnlyPass!';
GRANT SELECT ON myapp.* TO 'analytics'@'localhost';

FLUSH PRIVILEGES;
SHOW GRANTS FOR 'webapp'@'localhost';

Налаштування my.cnf для безпеки

# /etc/mysql/mariadb.conf.d/99-security.cnf

[mysqld]
# Прив'язати лише до localhost (заборонити зовнішні підключення)
bind-address = 127.0.0.1

# Вимкнути LOCAL INFILE (захист від LFI-атак)
local-infile = 0

# Приховати версію MariaDB
skip-show-database

# Максимальна кількість помилкових підключень
max_connect_errors = 100

# Логувати повільні запити
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

Шифрування з'єднань (SSL/TLS)

# Перевірити підтримку SSL
mysql -u root -p -e "SHOW VARIABLES LIKE '%ssl%';"

# Вимагати SSL для користувача
ALTER USER 'webapp'@'%' REQUIRE SSL;

# У my.cnf увімкнути SSL
ssl-ca = /etc/mysql/ssl/ca-cert.pem
ssl-cert = /etc/mysql/ssl/server-cert.pem
ssl-key = /etc/mysql/ssl/server-key.pem

Автоматичні резервні копії з шифруванням

cat > /etc/cron.daily/mysql-backup << 'SCRIPT'
#!/bin/bash
DATE=$(date +%Y%m%d)
mysqldump -u root -p'RootPass' --all-databases --single-transaction   | gzip | gpg --batch --passphrase "BackupKey123" -c   > /backup/mysql-$DATE.sql.gz.gpg
find /backup/ -name "mysql-*.sql.gz.gpg" -mtime +30 -delete
SCRIPT
chmod +x /etc/cron.daily/mysql-backup
Принцип мінімальних привілеїв для БД: Кожен застосунок повинен мати власного користувача БД лише з тими правами, які необхідні. Ніколи не використовуйте root-користувача для веб-застосунків.
Перевірте bind-address! За замовчуванням MariaDB в деяких дистрибутивах слухає всі інтерфейси (0.0.0.0). Це відкриває доступ з інтернету. Встановіть bind-address = 127.0.0.1, якщо зовнішній доступ не потрібен.

Часті помилки під час налаштування безпеки

Більшість помилок доступу після hardening пояснюються зміною методу автентифікації або областю дії користувача.

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

Після mysql_secure_installation root на багатьох системах перемикається на автентифікацію через unix_socket — вхід можливий лише локально через sudo mysql, а не через mysql -u root -p з паролем. Перевірте метод автентифікації: SELECT user, plugin FROM mysql.user WHERE user='root';.

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

Служба не запущена, або шлях до сокета в конфігу застосунку не збігається з реальним. Перевірте: systemctl status mariadb і шлях socket у секції [client] файлу my.cnf.

ERROR 1130 (HY000): Host '10.0.0.5' is not allowed to connect to this MySQL server

Користувач створений лише для 'webapp'@'localhost', а підключення йде з іншого сервера чи контейнера. Або створіть користувача з потрібним хостом чи підмережею ('webapp'@'10.0.0.%'), або підключайтеся через SSH-тунель без відкриття порту назовні — це безпечніше, ніж дозволяти віддалений IP напряму.

Методи автентифікації: порівняння

ПлагінЗберігання пароляСумісністьРекомендація
unix_socketПароль не потрібен, перевірка за UID ОСЛише локальні підключенняДля root і адмін-завдань на сервері
mysql_native_passwordSHA1-хешМаксимальна, старі драйвериЛише якщо потрібна сумісність
caching_sha2_passwordSHA-256MySQL 8+, сучасні драйвериЗа замовчуванням для нових застосунків

MariaDB і MySQL використовують різні плагіни за замовчуванням — на MariaDB 10.4+ це зазвичай unix_socket для root, на MySQL 8 — caching_sha2_password для нових користувачів. Під час перенесення дампу між СУБД паролі користувачів іноді доводиться призначати заново.

Коли такий hardening надлишковий або не підходить

Якщо застосунок і база даних розміщені на різних серверах (наприклад, окремий сервер БД для кількох веб-серверів), жорсткий bind-address = 127.0.0.1 із прикладу ламає архітектуру — у цьому випадку замість відкриття порту 3306 назовні налаштуйте приватну мережу між серверами або SSH-тунель, а не публічний доступ за паролем. Легасі-застосунки на старих версіях PHP чи Python можуть не підтримувати caching_sha2_password — якщо після оновлення з'являється помилка сумісності автентифікації, тимчасово створіть користувача на mysql_native_password, а не відкочуйте весь захист сервера.

Як перевірити результат

Перевіряйте не «підключення пройшло», а конкретні параметри безпеки:

# Переконатися, що користувач має лише потрібні права
SHOW GRANTS FOR 'webapp'@'localhost';

# Перевірити, що порт не слухає 0.0.0.0
sudo ss -tlnp | grep 3306

# Перевірити, що SSL реально увімкнений для з'єднання
mysql -u root -p -e "SHOW STATUS LIKE 'Ssl_cipher';"

Команда ss -tlnp | grep 3306 має показати адресу 127.0.0.1:3306, а не 0.0.0.0:3306, якщо зовнішній доступ не потрібен. Порожнє значення Ssl_cipher означає, що з'єднання пройшло без шифрування, навіть якщо сертифікати налаштовані в конфігу, — клієнт теж повинен явно запитувати SSL.

Часті питання

Чи потрібно змінювати порт MySQL за замовчуванням заради безпеки?

Зміна порту сама собою не замінює справжній захист — вона лише трохи ускладнює автоматичне сканування, але не зупиняє цілеспрямовану атаку. Набагато важливіше обмежити bind-address локальним інтерфейсом і тримати доступ закритим файрволом ззовні, а порт при цьому можна лишити стандартним без помітної втрати безпеки.

Чи потрібно взагалі видаляти користувача root, а не просто забороняти йому віддалений доступ?

Ні, видаляти системного користувача root не потрібно і зазвичай неможливо без наслідків — багато службових операцій і утиліт розраховують на його існування. Правильний підхід — заборонити йому віддалене підключення і перевести автентифікацію на локальний сокет, лишивши повний доступ лише під час входу прямо на сервері.

Чи безпечно використовувати одного користувача бази даних для кількох різних застосунків?

Ні, спільний користувач для кількох застосунків ламає принцип мінімальних привілеїв: компрометація одного застосунку одразу відкриває доступ до всіх баз даних решти. Правильніше створити окремого користувача під кожен застосунок із правами лише на потрібну йому базу, як і показано у прикладі з розділенням прав на запис і лише читання.

Що станеться, якщо забути створити нового користувача бази даних після відновлення дампа на іншому сервері?

Дамп бази даних переносить лише структуру і вміст таблиць, а не системних користувачів і їхні права доступу — їх потрібно створювати на новому сервері окремо, вручну або окремим дампом таблиці привілеїв. Без цього кроку застосунок на новому сервері просто не зможе підключитися з тими самими обліковими даними, що й раніше.

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