Настройка безопасности Apache и MySQL на Ubuntu Xenial Server

Posted by

Сегодняшняя заметка есть небольшая шпаргалка для самого себя, как настроить базовую безопасность для сервисов комплекта LAMP на Ubuntu Xenial Server. К примеру обезопасить подключение к MySQL только тем пользователям у которых есть соответствующие SSL сертификаты дабы ни кто попало мог подключиться к систему. Но я не спорю что это не полный список, а лишь малая часть по защите системы. Я в повседневности и в своих проектах использую только самолично настроенное на VPS, а не только сервис в пользование. Я доверяю только себе и своему опыту. Ладно начну пожалуй…

Шаг №1:

ekzorchik@srv-xenial:~$ sudo tasksel install lamp-server

New password for the MySQL "root" user: 712mbddr@

Repeat password for the MySQL "root" user: 712mbddr@

ekzorchik@srv-xenial:~$ sudo apache2 -v

Server version: Apache/2.4.18 (Ubuntu)

ekzorchik@srv-xenial:~$ sudo php --version

PHP 7.0.22-0ubuntu0.16.04.1 (cli) ( NTS )

Copyright (c) 1997-2017 The PHP Group

Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies

with Zend OPcache v7.0.22-0ubuntu0.16.04.1, Copyright (c) 1999-2017, by Zend Technologies

ekzorchik@srv-xenial:~$ mysql --version

mysql Ver 14.14 Distrib 5.7.19, for Linux (x86_64) using EditLine wrapper

Шаг №2:

ekzorchik@srv-xenial:~$ sudo mysql_secure_installation

Enter password for user root: 712mbddr@

  • Press y|Y for Yes, any other key for No: N (если указать y|Y то запуститься сценарий валидации пароля)
  • Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
  • Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
  • Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
  • Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y

Шаг №3:

По умолчанию сервис ожидает подключения к MySQL только локально, если в Ваших проектах нужно чтобы можно было подключаться с удаленных системе, то:

ekzorchik@srv-xenial:~$ ip r | awk '{print $9}'

10.9.9.129

ekzorchik@srv-xenial:~$ sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

#bind-address = 127.0.0.1

bind-address = 0.0.0.0

Шаг №4:

Для настройки шифрования передаваемых данных между этой системой и удаленной нужно использовать шифрование:

ekzorchik@srv-xenial:~$ sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

require_secure_transport = ON

ekzorchik@srv-xenial:~$ sudo mysql_ssl_rsa_setup --uid=mysql

Generating a 2048 bit RSA private key

.................................................................................+++

.........................+++

writing new private key to 'ca-key.pem'

-----

Generating a 2048 bit RSA private key

............+++

.+++

writing new private key to 'server-key.pem'

-----

Generating a 2048 bit RSA private key

....+++

...........................................................................+++

writing new private key to 'client-key.pem'

После проверяю, а создались ли файлы ключей:

ekzorchik@srv-xenial:~$ sudo find /var/lib/mysql -name '*.pem' -ls

Шаг №5:

Копирую клиентские ключи на удаленную систему:

ekzorchik@srv-xenial:~$ sudo scp /var/lib/mysql/ca.pem aollo@10.9.9.254:/home/aollo

ekzorchik@srv-xenial:~$ sudo scp /var/lib/mysql/client-cert.pem aollo@10.9.9.254:/home/aollo

ekzorchik@srv-xenial:~$ sudo scp /var/lib/mysql/client-key.pem aollo@10.9.9.254:/home/aollo

затем на удаленной системе:

aollo@work:~$ mkdir ~/client-ssl

aollo@work:~$ sudo mv client-*.pem ~/client-ssl/

aollo@work:~$ sudo mv ca.pem ~/client-ssl/

ekzorchik@srv-xenial:~$ sudo service mysql restart

ekzorchik@srv-xenial:~$ sudo netstat -tulpn | grep mysqld

tcp 0 0 10.9.9.129:3306 0.0.0.0:* LISTEN 13064/mysqld

(если бы параметр bind_address не был бы изменен, то значилось только 127.0.0.1:3306)

Шаг №6:

Т.к. ранее я запретил удаленное подключение под учетной записью root сервиса mysql на системе (Ubuntu Xenial), то значит нужно создать пользователя и дать ему права под которым можно будет подключиться с удаленной системы:

ekzorchik@srv-xenial:~$ mysql -u root -p712mbddr@

Отобразить текущую политику установки паролей для пользователей mysql:

mysql> show variables like 'validate_password%';

+--------------------------------------+--------+

| Variable_name | Value |

+--------------------------------------+--------+

| validate_password_check_user_name | OFF |

| validate_password_dictionary_file | |

| validate_password_length | 8 |

| validate_password_mixed_case_count | 1 |

| validate_password_number_count | 1 |

| validate_password_policy | MEDIUM |

| validate_password_special_char_count | 1 |

+--------------------------------------+--------+

7 rows in set (0.01 sec)

mysql> use mysql

mysql> create user 'ekzorchik'@'%' identified by 'Aa1234567@!' require x509;

Query OK, 0 rows affected (0.00 sec)

На заметку: а можно принудительно задать уже после, что данный пользователь может подключаться только с использованием SSL или только если у него есть публичный ключ x509:

mysql> alter user 'ekzorchik'@'%' require ssl;

mysql> alter user 'ekzorchik'@'%' require x509

отменить использование SSL:

mysql> alter user 'ekzorchik'@'%';

mysql> grant all privileges on *.* to 'ekzorchik'@'%'; → по сути это еще один администратор, но правильнее указывать на конкретную базу данных собственного администратора.

mysql> flush privileges;

mysql> show variables like '%ssl%';

+---------------+-----------------+

| Variable_name | Value |

+---------------+-----------------+

| have_openssl | YES |

| have_ssl | YES |

| ssl_ca | ca.pem |

| ssl_capath | |

| ssl_cert | server-cert.pem |

| ssl_cipher | |

| ssl_crl | |

| ssl_crlpath | |

| ssl_key | server-key.pem |

+---------------+-----------------+

9 rows in set (0.00 sec)

На заметку: Если переменные have_openssl и have_ssl помечены как DISABLED. Это означает, что функциональность SSL собран в сервере, но еще не включена, у меня значения YES значит все включено.

Шаг №7:

Отобразить заведенных пользователей в сервисе MySQL:

ekzorchik@srv-xenial:~$ mysql -u root -p712mbddr@

mysql> use mysql;

mysql> select User,Host from mysql.user;

mysql> drop user 'test'@'%'; (или что у Вас написано)

mysql> flush privileges;

Проверить текущее состоянии подключения к сессии можно:

mysql> \s

  • Current user: root@localhost
  • SSL: Not in use
  • Connection: Localhost via UNIX socket

mysql> quit

Bye

На заметку: если в bind-address = указан IP, то можно при создании пользователя использовать символ процента как звездочка при использовании всех комбинации соответствующего октета, так и просто со всех адресов: 'user'@'%'

Шаг №8:

Проверяю, а могу ли я теперь с удаленной системы (Ubuntu Trusty Desktop amd64 Gnome Classic) подключиться к этой где развернут сервис mysql (Ubuntu 16.03, Ubuntu Xenial Server):

aollo@work:~$ sudo apt-get install mysql-client -y

aollo@work:~$ mysql --version

mysql Ver 14.14 Distrib 5.5.57, for debian-linux-gnu (x86_64) using readline 6.3

aollo@work:~$ mysql -u ekzorchik -pAa1234567@! -h 10.9.9.129

ERROR 1045 (28000): Access denied for user 'ekzorchik'@'10.9.9.254' (using password: YES)

А если указать файлы клиентских сертификатов которые я скопировал с серверной части на эту систему:

aollo@work:~$ mysql -u ekzorchik -pAa1234567@! -h 10.9.9.129 --ssl=ca=~/client-ssl/ca.pem --ssl-cert=~/client-ssl/client-cert.pem --ssl-key=~/client-ssl/client-key.pem

mysql> \s

--------------

mysql Ver 14.14 Distrib 5.5.57, for debian-linux-gnu (x86_64) using readline 6.3

Connection id: 11

Current database:

Current user: ekzorchik@10.9.9.254

SSL: Cipher in use is DHE-RSA-AES256-SHA

Current pager: stdout

Using outfile: ''

Using delimiter: ;

Server version: 5.7.19-0ubuntu0.16.04.1 (Ubuntu)

Protocol version: 10

Connection: 10.9.9.129 via TCP/IP

Server characterset: latin1

Db characterset: latin1

Client characterset: utf8

Conn. characterset: utf8

TCP port: 3306

Uptime: 37 min 1 sec

Threads: 2 Questions: 44 Slow queries: 0 Opens: 140 Flush tables: 1 Open tables: 52 Queries per second avg: 0.019

Шаг №9:

Дабы в строке подключения не указывать месторасположение файлов SSL, можно один раз добавить в клиентскую настройку и после подключение уже будет само заниматься что и откуда подставлять:

aollo@work:~$ sudo nano /etc/mysql/my.cnf

[client]

port = 3306

socket = /var/run/mysqld/mysqld.sock

ssl-ca = /home/aollo/client-ssl/ca.pem

ssl-cert = /home/aollo/client-ssl/client-cert.pem

ssl-key = /home/aollo/client-ssl/client-key.pem

aollo@work:~$ mysql -u ekzorchik -pAa1234567@! -h 10.9.9.129

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 24

Server version: 5.7.19-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

Работает. Теперь подключение к сервису MySQL есть только у пользователей у которых есть файлы SSL.

Шаг №10:

После не забывает добавить/включить правило на удаленное подключение к серверу в брандмауэере:

ekzorchik@srv-xenial:~$ sudo ufw allow mysql

ekzorchik@srv-xenial:~$ sudo ufw status

Status: active

To Action From

-- ------ ----

OpenSSH ALLOW Anywhere

3306 ALLOW Anywhere

Шаг №11:

Теперь настройки по безопасности Apache2:

ekzorchik@srv-xenial:~$ sudo rm /etc/apache2/sites-available/000-default.conf

ekzorchik@srv-xenial:~$ sudo rm /etc/apache2/sites-available/default-ssl.conf

ekzorchik@srv-xenial:~$ sudo rm /etc/apache2/sites-enabled/000-default.conf

ekzorchik@srv-xenial:~$ sudo nano /etc/apache2/conf-enabled/security.conf

ServerTokens Prod

ServerSignature Off

TraceEnable Off

ekzorchik@srv-xenial:~$ sudo rm /var/www/html/index.html

ekzorchik@srv-xenial:~$ sudo ufw allow http

Rule added

  • Использовать безопасный доступ к сайту задействовав https префикс, не важно самоподписанный сертификат или купленный лицензионный.
  • Установить ModSecurity для защиты Apache2
  • Установить модуль mod_evasive Для защиты от Ddos атак
  • Поставить брандмауэр ufw с политикой все запрещено кроме разрешенного

Указывать все возможные способы защиты сервисов и приводить их вот здесь я считаю излишним, каждый должен прийти самим что и как ему закрывать и настраивать безопасность, а не действовать по шаблону. Ведь то что опубликовано в интернете не есть 100% защита, а лишь меры на что обратить внимание при защите. Важно все настраивать самим и учиться при этом, как я к примеру. На этом у меня всё, с уважением автор блога Олло Александр aka ekzorchik.