MySQL является наиболее популярной системой управления реляционными базами данных с открытым исходным кодом в мире. Современные менеджеры пакетов сократили некоторые проблемы установки MySQL, но есть еще некоторые настройки, которые необходимо сделать после установки. Одним из наиболее важных, это провести некоторое дополнительное время на безопасность.
По умолчанию MySQL настроен на прием только локальных соединений. Если вам необходимо разрешить удаленные подключения, важно сделать это надежно. В этом руководстве мы покажем, как настроить MySQL на Ubuntu 16.04, для удаленного соединения с помощью шифрования SSL/TLS.
Для того, чтобы следовать вместе с этим руководством, вам потребуется два сервера Ubuntu 16.04. Мы будем использовать один в качестве сервера MySQL, а другой в качестве клиента. Создайте некорневого пользователя с sudo
привилегиями на каждом из этих серверов. Следуйте нашему руководству по первоначальной настройке сервера Ubuntu 16.04, чтобы получить ваш сервер в соответствующем начальном состоянии.
На первой машине, вы должны иметь установленный и настроенный сервер MySQL. Следуйте нашему руководство по установке MySQL на Ubuntu 16.04 для установки и настройки программного обеспечения.
На второй машине установите пакет клиент MySQL. Вы можете обновить индекс пакетов apt
и установить необходимое программное обеспечение, набрав:
sudo apt-get update sudo apt-get install mysql-client
Когда ваш сервер и клиент готов, продолжайте дальше следовать нашему гиду.
Прежде чем мы начнем, мы можем проверить текущее состояние SSL/TLS на нашем экземпляре MySQL сервера.
Войдите в сеанс MySQL с помощью пользователя root
в MySQL. Мы будем использовать -h
чтобы указать локальный интерфейс обратной петли IPv4 для того , чтобы заставить клиента соединиться с TCP вместо использования локального файла сокета. Это позволит нам проверить состояние SSL для TCP соединений:
mysql -u root -p -h 127.0.0.1
Вам будет предложено ввести MySQL пароль root
, который вы выбрали в процессе установки. После этого вы попадёте в интерактивную сессию MySQL.
Показать состояние переменных SSL/TLS, набрав:
mysql> SHOW VARIABLES LIKE '%ssl%';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_openssl | DISABLED |
| have_ssl | DISABLED |
| ssl_ca | |
| ssl_capath | |
| ssl_cert | |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | |
+---------------+----------+
9 rows in set (0.01 sec)
Переменные have_openssl
и have_ssl
помечены как DISABLED
. Это означает, что функциональность SSL собран в сервере, но еще не включена.
Проверьте состояние нашего текущего соединения, чтобы подтвердить:
mysql> \s
-------------- mysql Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using EditLine wrapper Connection id: 30 Current database: Current user: root@localhost SSL: Not in use Current pager: stdout Using outfile: '' Using delimiter: ; Server version: 5.7.17-0ubuntu0.16.04.1 (Ubuntu) Protocol version: 10 Connection: 127.0.0.1 via TCP/IP Server characterset: latin1 Db characterset: latin1 Client characterset: utf8 Conn. characterset: utf8 TCP port: 3306 Uptime: 3 hours 38 min 44 sec Threads: 1 Questions: 70 Slow queries: 0 Opens: 121 Flush tables: 1 Open tables: 40 Queries per second avg: 0.005 --------------
Как показано выше, указывает на то, что SSL не используется в настоящее время для нашей связи, даже если мы соединены через TCP.
Закройте текущую сессию MySQL, когда вы закончите:
mysql> exit
Теперь мы можем приступить к настройке MySQL для SSL, чтобы обеспечить наши связи.
Чтобы включить SSL соединения с MySQL, нам в первую очередь необходимо сформировать соответствующий сертификат и файлы ключей. Утилита называется mysql_ssl_rsa_setup
снабжена MySQL 5.7 и выше, чтобы упростить этот процесс. Ubuntu 16.04 имеет совместимую версию MySQL, поэтому мы можем использовать эту команду, чтобы создать необходимые файлы.
Файлы будут создаваться в директории данных MySQL, расположенных в /var/lib/mysql
. Нам нужен процесс MySQL, чтобы иметь возможность читать генерируемые файлы, так что мы будем заходить как mysql
в качестве пользователя, который должен владеть сгенерированными файлами:
mysql-server$ 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' -----
Проверьте созданные файлы, набрав:
mysql-server$ sudo find /var/lib/mysql -name '*.pem' -ls
256740 4 -rw-r--r-- 1 mysql mysql 1078 Mar 17 17:24 /var/lib/mysql/server-cert.pem 256735 4 -rw------- 1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/ca-key.pem<^> 256739 4 -rw-r--r-- 1 mysql mysql 451 Mar 17 17:24 /var/lib/mysqlsql/public_key.pem<^> 256741 4 -rw------- 1 mysql mysql 1679 Mar 17 17:24 /var/lib/mysqlsql/client-key.pem<^> 256737 4 -rw-r--r-- 1 mysql mysql 1074 Mar 17 17:24 /var/lib/mysqlsql/ca.pem<^> 256743 4 -rw-r--r-- 1 mysql mysql 1078 Mar 17 17:24 /var/lib/mysqlsql/client-cert.pem<^> 256736 4 -rw------- 1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/private_key.pem<^> 256738 4 -rw------- 1 mysql mysql 1675 Mar 17 17:24 /var/lib/mysqlsql/server-key.pem<^>
В последнем столбце показаны сгенерированные имена файлов. Центральные столбцы, которые показывают “MySQL” указывают, что генерируемые файлы имеют правильного пользователя и группы владельца.
Эти файлы являются ключевыми и сертификат пары для сертификации (начиная с “ca”), процесс сервера MySQL (начиная с “server”), так и для клиентов MySQL (начиная с “client”). Кроме того, файлы private_key.pem
и public_key.pem
используются MySQL для безопасной передачи пароля, если не используется SSL.
Современные версии MySQL будут искать соответствующие файлы сертификатов в пределах каталога данных MySQL при запуске сервера. Из-за этого нам на самом деле не нужно изменить конфигурацию MySQL, чтобы включить SSL.
Мы можем просто перезапустить службу MySQL вместо этого:
sudo systemctl restart mysql
После перезагрузки, откройте новый сеанс MySQL, используя ту же команду, как и раньше. Клиент MySQL автоматически попытается подключиться с помощью SSL, если она поддерживается сервером:
mysql -u root -p -h 127.0.0.1
Давайте посмотрим на ту же информацию, которую мы запрашивали в прошлый раз. Проверьте значения переменных, связанных с SSL:
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
чтения “YES” вместо “ОТКЛ” на этот раз. Кроме того, переменные ssl_ca
, ssl_cert
и ssl_key
были указаны с именами соответствующих сертификатов, которые мы получили.
Затем проверьте параметры соединения снова:
mysql> \s
-------------- . . . SSL: Cipher in use is DHE-RSA-AES256-SHA . . . Connection: 127.0.0.1 via TCP/IP . . . --------------
На этот раз, отображается конкретный SSL, указывая, что SSL используется для того чтобы обеспечить наше соединение.
Выход обратно в оболочку:
mysql> exit
Наш сервер теперь может использовать шифрование, но требуется некоторая дополнительная настройка для обеспечения возможности удаленного доступа и использования безопасного соединения.
Теперь, когда мы имеем доступный SSL на сервере, мы можем приступить к настройке безопасного удаленного доступа. Для этого нам необходимо:
В настоящее время сервер MySQL настроен на прием SSL соединения от клиентов. Тем не менее, он все равно будет разрешить нешифрованные соединения, по требованию клиента.
Мы можем исправить это путем включения опции require_secure_transport
. Это требует, чтобы все соединения должны быть сделаны либо с помощью SSL или с локального сокета Unix. Так как Unix сокеты доступны только внутри самого сервера, единственный вариант подключения открыт для удаленных пользователей будет с помощью SSL.
Чтобы включить эту настройку, откройте файл /etc/mysql/my.cnf
в текстовом редакторе:
sudo nano /etc/mysql/my.cnf
Внутри будет две директивы !includedir
, используемые для источника дополнительных конфигурационных файлов. Нам нужно будет поставить нашу собственную конфигурацию под этими линиями так, чтобы они отменяли любые конфликтующие параметры.
Начните с создания раздела [mysqld]
целевого процесса сервера MySQL. Под этим заголовком раздела, установите require_secure_transport
на ON
:
. . . !includedir /etc/mysql/conf.d/ !includedir /etc/mysql/mysql.conf.d/ [mysqld] # Require clients to connect either using SSL # or through a local socket file require_secure_transport = ON
Эта линия является единственным значением, которое требуется для обеспечения безопасных соединений.
По умолчанию MySQL настроен на прослушивание только для подключений, происходящих на локальном компьютере. Для того, чтобы настроить его для прослушивания удаленных соединений, мы можем установить bind-address
с другим интерфейсом.
Чтобы разрешить MySQL принимать соединения на любой из его интерфейсов, мы можем установить bind-address
на “0.0.0.0”:
. . . !includedir /etc/mysql/conf.d/ !includedir /etc/mysql/mysql.conf.d/ [mysqld] # Require clients to connect either using SSL # or through a local socket file require_secure_transport = ON bind-address = 0.0.0.0
Сохраните и закройте файл, когда вы закончите.
Затем перезапустите MySQL, чтобы применить новые параметры:
sudo systemctl restart mysql
Убедитесь в том, что MySQL прослушивает “0.0.0.0” вместо “127.0.0.1”, набрав:
sudo netstat -plunt
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 4330/mysqld tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1874/sshd tcp6 0 0 :::22 :::* LISTEN 1874/sshd
“0.0.0.0” в приведенном выше выводе указывает на то, что MySQL прослушивает подключения на всех доступных интерфейсов.
Далее, нам необходимо разрешить соединения MySQL через наш брандмауэр. Создайте исключение, набрав:
sudo ufw allow mysql
Rule added Rule added (v6)
Теперь попытки удаленного подключения должны быть в состоянии достигнуть нашим сервером MySQL.
Сервер MySQL теперь слушает удаленные подключения, но у нас в настоящее время нет никаких пользователей, настроенных, которые могут подключаться с внешнего компьютера.
Войдите в MySQL как root
, чтобы начать работу:
mysqlserver$ mysql -u root -p
Внутри, вы можете создать нового удаленного пользователя с помощью команды CREATE USER
. Мы будем использовать IP – адрес машины у нашего клиента в принимающей части спецификации пользователя, чтобы ограничить возможность соединения с этой машиной.
Для некоторых в случае, если опция require_secure_transport
выключена в будущем, мы можем также указать при создании учетной записи, что данный пользователь требует SSL, включив пункт REQUIRE SSL
:
mysql> CREATE USER 'remote_user'@'mysql_client_IP' IDENTIFIED BY 'password' REQUIRE SSL;
Далее, предоставить новые разрешения пользователя к базам данных или таблиц, к которым они должны иметь доступ. Чтобы продемонстрировать это, мы создадим базу данных example
и выдадим разрешение пользователю:
mysql> CREATE DATABASE example; mysql> GRANT ALL ON example.* TO 'remote_user'@'mysql_client_IP';
Затем сбросьте привилегии, чтобы применить все эти настройки:
mysql> FLUSH PRIVILEGES;
Выйдите обратно к оболочке:
mysql> exit
Наш сервер настроен, чтобы разрешить подключения к нашему удаленному пользователю.
На машине клиента MySQL, проверьте, что вы можете подключиться к серверу успешно. Используйте опцию -u
для определения удаленного пользователя и -h
возможность указать IP – адрес сервера в MySQL:
mysql-client$ mysql -u remote_user -p -h mysql_server_IP
После указания пароля, вы будете авторизованы на удаленном сервере.
Убедитесь, что соединение является безопасным:
mysql> \s
-------------- . . . SSL: Cipher in use is DHE-RSA-AES256-SHA . . . Connection: mysql_server_IP via TCP/IP . . . --------------
Выйдите обратно в оболочку:
mysql> exit
Далее, попытка соединиться небезопасно:
mysql-client$ mysql -u remote_user -p -h mysql_server_IP --ssl-mode=disabled
После того, как был запрос на ввод пароля, ваше соединение должно быть отказано:
ERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_server_IP' (using password: YES)
Это показывает, что SSL соединения разрешены, в то время как незашифрованные соединения отказывались.
На данный момент, наш сервер MySQL был настроен, чтобы надежно фиксировать удаленные соединения. Вы можете остановиться здесь, если это отвечает вашим требованиям к безопасности, но есть некоторые дополнительные части, которые мы можем поставить на место, чтобы повысить нашу безопасность и доверие дальше.
В настоящее время наш сервер MySQL настроен с помощью сертификата SSL, подписанного локально сгенерированной центром сертификации (CA). Сертификат сервера и пара ключей достаточно для обеспечения шифрования для входящих соединений.
Тем не менее, мы в настоящее время не использовать доверительные отношения, которые орган сертификат может обеспечить. Распределяя сертификат CA для клиентов, а также сертификат клиента и ключ, обе стороны могут предоставить доказательства того, что их сертификаты были подписаны взаимоприемлемым доверенным центром сертификации. Это может помочь предотвратить фальсифицируемые соединений на вредоносные серверы.
Для реализации этого дополнительной гарантии, нам нужно будет:
Для начала, нам нужно передать в MySQL CA и файлы сертификатов клиента с сервера MySQL и поместить их на машину клиента MySQL.
Начните с создания каталога на клиенте MySQL в домашнем каталоге пользователя, который будет использоваться для подключения. Назовем client-ssl
:
mysql-client$ mkdir ~/client-ssl
Так как сертификат ключа чувствителен, мы должны заблокировать доступ к этому каталогу, так что только текущий пользователь может получить доступ к нему:
mysql-client$ chmod 700 ~/client-ssl
Теперь мы можем скопировать информацию о сертификате в новый каталог.
На машине сервере MySQL, отобразим содержимое сертификата CA, набрав:
mysql-client$ sudo cat /var/lib/mysql/ca.pem
-----BEGIN CERTIFICATE----- . . . -----END CERTIFICATE-----
Скопируйте весь вывод, в том числе линии BEGIN CERTIFICATE
и END CERTIFICATE
в буфер обмена.
На клиенте MySQL , создайте файл с таким же именем внутри нового каталога:
mysql-client$ nano ~/client-ssl/ca.pem
Внутри, вставить скопированное содержимое сертификата из буфера обмена. Сохраните и закройте файл, когда вы закончите.
Затем отобразите сертификат клиента на сервере MySQL :
mysql-client$ sudo cat /var/lib/mysql/client-cert.pem
-----BEGIN CERTIFICATE----- . . . -----END CERTIFICATE-----
Опять же, скопируйте содержимое в буфер обмена. Не забудьте включить первую и последнюю строку.
Откройте файл с тем же именем на клиенте MySQL в пределах директории client-ssl
:
mysql-client$ nano ~/client-ssl/client-cert.pem
Вставить содержимое из буфера обмена. Сохраните и закройте файл.
И, наконец, отобразите содержимое файла ключа клиента на сервере MySQL:
mysql-client$ sudo cat /var/lib/mysql/client-key.pem
-----BEGIN RSA PRIVATE KEY----- . . . -----END RSA PRIVATE KEY-----
Скопируйте отображаемые содержимое, в том числе первую и последнюю строку, в буфер обмена.
На клиенте MySQL, откройте файл с тем же именем в каталоге client-ssl
:
mysql-client$ nano ~/client-ssl/client-key.pem
Вставьте содержимое из буфера обмена. Сохраните и закройте файл.
Теперь клиент машина должна иметь все учетные данные, необходимые для доступа к серверу MySQL. Далее, мы должны изменить нашего удаленного пользователя.
В настоящее время клиент MySQL имеет файлы, доступные, чтобы представить свой сертификат на сервер при подключении. Тем не менее, сервер еще не настроен требовать сертификат клиента от доверенного центра сертификации
Чтобы изменить это, необходимо войти с корневой учетной записи MySQL на сервер MySQL :
mysql-client$ mysql -u root -p
Далее, нам необходимо изменить требования к нашему удаленному пользователю. Вместо пункта REQUIRE SSL
, мы должны применить пункт REQUIRE X509
. Это подразумевает все обеспечения, предоставленного предыдущим требованием, но дополнительно требуется соединенному клиенту представить сертификат, подписанный центром сертификации, которому сервер доверяет MySQL.
Для того, чтобы настроить требования пользователя, используйте команду ALTER USER
:
mysql> ALTER USER 'remote_user'@'mysql_client_IP' REQUIRE X509;
Очистите изменения, чтобы гарантировать, что они применяются немедленно:
mysql> FLUSH PRIVILEGES;
Выйдите обратно в оболочку, когда вы закончите:
mysql> exit
Далее, мы можем проверить, чтобы убедиться, что мы все еще можем подключиться.
Сейчас хорошее время, чтобы проверить обе стороны, когда мы соединяемся.
На клиенте MySQL, сначала попытайтесь подключиться без предоставления клиентских сертификатов:
mysql> mysql -u remote_user -p -h mysql_server_IP
ERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_client_IP' (using password: YES)
Без предоставления сертификата клиента, сервер отклоняет соединение.
Теперь соединитесь при использовании параметров --ssl-ca
, --ssl-cert
и --ssl-key
, чтобы указать на соответствующие файлы внутри каталога ~/client-ssl
:
mysql-client$ mysql -u remote_user -p -h mysql_server_IP --ssl-ca=~/client-ssl/ca.pem --ssl-cert=~/client-ssl/client-cert.pem --ssl-key=~/client-ssl/client-key.pem
Вы должны войти успешно в систему. Выйдите обратно, чтобы восстановить доступ к вашей оболочки:
mysql> exit
Теперь, когда мы подтвердили доступ к серверу, мы можем реализовать небольшое улучшение юзабилити.
Для того, чтобы избежать необходимости указать файлы сертификата каждый раз при подключении к сети, мы можем создать простой файл конфигурации клиента MySQL.
Внутри вашей домашней директории на машине клиенте MySQL, создайте скрытый файл с именем ~/.my.cnf
:
mysql-client$ nano ~/.my.cnf
В верхней части файла, создайте раздел под названием [client]
. Внизу, мы можем установить параметры ssl-ca
, ssl-cert
и ssl-key
, чтобы указать на файлы, которые мы копируем с сервера. Он должен выглядеть следующим образом :
[client] ssl-ca = ~/client-ssl/ca.pem ssl-cert = ~/client-ssl/client-cert.pem ssl-key = ~/client-ssl/client-key.pem
Опция ssl-ca
сообщает клиенту, чтобы убедиться, что сертификат, представленный сервером MySQL подписывается центром сертификации, который мы указали. Это позволяет клиенту верить, что он подключается к доверенному серверу MySQL.
параметры ssl-cert
и ssl-key
указывают на файлы, необходимые для доказательства сервера MySQL, что он тоже имеет сертификат, подписанный тем же органом сертификации. Нам это нужно, если мы хотим, чтобы сервер MySQL убедиться, что клиент был доверенным центром сертификации.
Сохраните и закройте файл, когда вы закончите.
Теперь вы можете подключиться к серверу MySQL, не добавляя опции --ssl-ca
, --ssl-cert
и --ssl-key
к командной строке:
mysql-client$ mysql -u remote_user -p -h mysql_server_ip
Ваш клиент и сервер должны каждому из них будет предоставлять сертификаты при согласовании подключения. Каждая сторона настроена для проверки удалённого сертификата от сертификата CA он имеет локально.
Сервер MySQL должен теперь настроен на требование защищенных соединений для удаленных клиентов. Кроме того, если вы следовали шагfv для проверки соединения с использованием центра сертификации, некоторый уровень доверия устанавливается с обеих сторон.
Спасибо, очень помогло ваше описание. Подробно и по человечески.