Как настроить SSL / TLS для MySQL в Ubuntu 16.04

Вступление

MySQL - самая популярная в мире система управления реляционными базами данных с открытым исходным кодом. Современные менеджеры пакетов уменьшили некоторые трения до запуска и работы MySQL, но все еще есть некоторая конфигурация, которую следует выполнить после установки. Одной из самых важных областей, на которых стоит потратить дополнительное время, является безопасность.

По умолчанию MySQL настроен на прием только локальных подключений. Если вам нужно разрешить удаленные подключения, важно сделать это безопасно. В этом руководстве мы покажем, как настроить MySQL в Ubuntu 16.04 для приема удаленных соединений с шифрованием SSL / TLS.

Предпосылки

Чтобы следовать этому руководству, вам потребуются серверы Ubuntu 16.04two. Мы будем использовать один в качестве сервера MySQL, а другой - в качестве клиента. Создайте пользователя без полномочий root с правамиsudo на каждом из этих серверов. Следуйте нашимUbuntu 16.04 initial server setup guide, чтобы привести ваш сервер в соответствующее начальное состояние.

На первом компьютере у вас должен быть установлен и настроенMySQL server. Следуйте нашимMySQL installation guide for Ubuntu 16.04, чтобы установить и настроить программное обеспечение.

На втором компьютере установите пакетMySQL client. Вы можете обновить индекс пакетаapt и установить необходимое программное обеспечение, набрав:

sudo apt-get update
sudo apt-get install mysql-client

Когда ваш сервер и клиент готовы, продолжайте ниже.

Проверьте текущий статус SSL / TLS

Прежде чем мы начнем, мы можем проверить текущий статус SSL / TLS в нашем экземпляреMySQL server.

Войдите в сеанс MySQL, используя пользователя MySQLroot. Мы будем использовать-h, чтобы указать интерфейс локальной петли IPv4, чтобы заставить клиента подключаться по TCP вместо использования локального файла сокета. Это позволит нам проверить статус SSL для соединений TCP:

mysql -u root -p -h 127.0.0.1

Вам будет предложено ввести пароль MySQLroot, который вы выбрали в процессе установки. После этого вы попадете в интерактивный сеанс MySQL.

Показать состояние переменных SSL / TLS, набрав:

SHOW VARIABLES LIKE '%ssl%';
Output+---------------+----------+
| 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 была скомпилирована в сервер, но еще не включена.

Проверьте статус нашего текущего соединения, чтобы подтвердить:

\s
Output--------------
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, когда вы закончите:

exit

Теперь мы можем начать настройку MySQL для SSL для защиты наших соединений.

Генерация сертификатов и ключей SSL / TLS

Чтобы разрешить SSL-соединения с MySQL, нам сначала нужно сгенерировать соответствующие файлы сертификатов и ключей. Утилита под названиемmysql_ssl_rsa_setup предоставляется с MySQL 5.7 и выше, чтобы упростить этот процесс. Ubuntu 16.04 имеет совместимую версию MySQL, поэтому мы можем использовать эту команду для генерации необходимых файлов.

Файлы будут созданы в каталоге данных MySQL, расположенном в/var/lib/mysql. Нам нужно, чтобы процесс MySQL мог читать сгенерированные файлы, поэтому мы передадимmysql как пользователя, которому должны принадлежать сгенерированные файлы:

sudo mysql_ssl_rsa_setup --uid=mysql

Генерация будет производить вывод, который выглядит примерно так:

OutputGenerating 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'
-----

Проверьте сгенерированные файлы, набрав:

sudo find /var/lib/mysql -name '*.pem' -ls
Output   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 (начиная с «сервера») и для клиентов MySQL (начиная с «клиента»). Кроме того, файлыprivate_key.pem иpublic_key.pem используются MySQL для безопасной передачи пароля, когда SSL не используется.

Включить SSL-соединения на MySQL Server

Современные версии MySQL будут искать соответствующие файлы сертификатов в каталоге данных MySQL при запуске сервера. Из-за этого нам фактически не нужно изменять конфигурацию MySQL для включения SSL.

Вместо этого мы можем просто перезапустить службу MySQL:

sudo systemctl restart mysql

После перезапуска откройте новый сеанс MySQL, используя ту же команду, что и раньше. Клиент MySQL автоматически попытается подключиться с использованием SSL, если это поддерживается сервером:

mysql -u root -p -h 127.0.0.1

Давайте посмотрим на ту же информацию, которую мы запрашивали в прошлый раз. Проверьте значения переменных, связанных с SSL:

SHOW VARIABLES LIKE '%ssl%';
Output+---------------+-----------------+
| 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» вместо «DISABLED». Кроме того, переменныеssl_ca,ssl_cert иssl_key были заполнены именами соответствующих сертификатов, которые мы сгенерировали.

Далее, проверьте детали подключения еще раз:

\s
Output--------------
. . .
SSL:            Cipher in use is DHE-RSA-AES256-SHA
. . .
Connection:      127.0.0.1 via TCP/IP
. . .
--------------

На этот раз отображается конкретный шифр SSL, указывающий, что SSL используется для защиты нашего соединения.

Выход обратно в оболочку:

exit

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

Настройка безопасных подключений для удаленных клиентов

Теперь, когда у нас есть SSL на сервере, мы можем начать настройку безопасного удаленного доступа. Для этого нам необходимо:

  • Требовать SSL для удаленных подключений

  • Привязать к общедоступному интерфейсу

  • Создать пользователя MySQL для удаленных подключений

  • Настройте наши правила брандмауэра, чтобы разрешить внешние подключения

Настройте удаленный доступ с обязательным SSL

В настоящее время сервер MySQL настроен на прием SSL-соединений от клиентов. Тем не менее, он по-прежнему будет разрешать незашифрованные соединения по запросу клиента.

Мы можем исправить это, включив опциюrequire_secure_transport. Это требует, чтобы все соединения были сделаны либо с SSL, либо с локальным сокетом Unix. Поскольку сокеты Unix доступны только изнутри самого сервера, единственным вариантом подключения, открытым для удаленных пользователей, будет SSL.

Чтобы включить этот параметр, откройте файл/etc/mysql/my.cnf в текстовом редакторе:

sudo nano /etc/mysql/my.cnf

Внутри будут две директивы!includedir, используемые для создания дополнительных файлов конфигурации. Нам нужно будет поместить в эти строки нашу собственную конфигурациюbeneath, чтобы они перекрывали любые конфликтующие настройки.

Начните с создания раздела[mysqld], предназначенного для серверного процесса MySQL. Под заголовком этого раздела установитеrequire_secure_transport наON:

/etc/mysql/my.cnf

. . .

!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»:

/etc/mysql/my.cnf

. . .

!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
OutputActive 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
OutputRule added
Rule added (v6)

Попытки удаленного подключения теперь должны быть в состоянии достигнуть нашего сервера MySQL.

Настройте удаленного пользователя MySQL

Сервер MySQL теперь ожидает удаленных подключений, но в настоящее время у нас нет настроенных пользователей, которые могут подключаться с внешнего компьютера.

Войдите в MySQL как пользовательroot, чтобы начать:

mysql -u root -p

Внутри вы можете создать нового удаленного пользователя с помощью командыCREATE USER. Мы будем использовать IP-адрес нашего клиентского компьютера в основной части пользовательской спецификации, чтобы ограничить подключения к этому компьютеру.

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

CREATE USER 'remote_user'@'mysql_client_IP' IDENTIFIED BY 'password' REQUIRE SSL;

Затем предоставьте новым пользователям разрешения на доступ к базам данных или таблицам. Чтобы продемонстрировать это, мы создадим базу данныхexample и предоставим новому пользователю право собственности:

CREATE DATABASE example;
GRANT ALL ON example.* TO 'remote_user'@'mysql_client_IP';

Затем удалите привилегии для немедленного применения этих настроек:

FLUSH PRIVILEGES;

Вернитесь обратно в оболочку, когда закончите:

exit

Наш сервер настроен для разрешения подключений к нашему удаленному пользователю.

Тестирование удаленных подключений

На машинеMySQL client проверьте, можете ли вы успешно подключиться к серверу. Используйте параметр-u, чтобы указать удаленного пользователя, и параметр-h, чтобы указать IP-адрес сервера MySQL:

mysql -u remote_user -p -h mysql_server_IP

После указания пароля вы будете авторизованы на удаленном сервере.

Убедитесь, что ваше соединение защищено:

\s
Output--------------
. . .
SSL:         Cipher in use is DHE-RSA-AES256-SHA
. . .
Connection:      mysql_server_IP via TCP/IP
. . .
--------------

Выход обратно в оболочку:

exit

Затем попытайтесь подключиться небезопасно:

mysql -u remote_user -p -h mysql_server_IP --ssl-mode=disabled

После запроса вашего пароля в вашем соединении должно быть отказано:

OutputERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_server_IP' (using password: YES)

Это то, над чем мы работали. Это показывает, что SSL-соединения разрешены, а незашифрованные соединения отклонены.

На этом этапе наш сервер MySQL был настроен для безопасного приема удаленных подключений. Вы можете остановиться здесь, если это удовлетворяет вашим требованиям безопасности, но есть некоторые дополнительные элементы, которые мы можем использовать для повышения нашей безопасности и дальнейшего доверия.

Настройка проверки для подключений MySQL (необязательно)

В настоящее время наш сервер MySQL настроен с сертификатом SSL, подписанным локально сгенерированным центром сертификации (CA). Сертификата сервера и пары ключей достаточно для обеспечения шифрования входящих соединений.

Однако в настоящее время мы не используем доверительные отношения, которые может предоставить центр сертификации. Распространяя сертификат CA среди клиентов, а также сертификат клиента и ключ, обе стороны могут предоставить доказательство того, что их сертификаты были подписаны доверенным центром сертификации. Это может помочь предотвратить подделку подключений к вредоносным серверам.

Для реализации этой дополнительной дополнительной защиты нам необходимо:

  • Передайте соответствующие файлы SSL на клиентский компьютер

  • Создайте файл конфигурации клиента

  • Изменить наш удаленный пользователь, чтобы требовать доверенного сертификата

Передать клиентские сертификаты на клиентский компьютер

Для начала нам нужно взять файлы MySQL CA и клиентских сертификатов с сервера MySQL и поместить их на клиент MySQL.

Начните с создания каталога наMySQL client в домашнем каталоге пользователя, которого вы будете использовать для подключения. Назовите этоclient-ssl:

mkdir ~/client-ssl

Поскольку ключ сертификата является конфиденциальным, мы должны заблокировать доступ к этому каталогу, чтобы только текущий пользователь мог получить к нему доступ:

chmod 700 ~/client-ssl

Теперь мы можем скопировать информацию о сертификате в новый каталог.

На машинеMySQL server отобразите содержимое сертификата CA, набрав:

sudo cat /var/lib/mysql/ca.pem
Output-----BEGIN CERTIFICATE-----

. . .

-----END CERTIFICATE-----

Скопируйте весь вывод, включая строкиBEGIN CERTIFICATE иEND CERTIFICATE, в буфер обмена.

НаMySQL client создайте файл с тем же именем внутри нового каталога:

nano ~/client-ssl/ca.pem

Внутри вставьте скопированное содержимое сертификата из буфера обмена. Сохраните и закройте файл, когда вы закончите.

Затем отобразите сертификат клиента наMySQL server:

sudo cat /var/lib/mysql/client-cert.pem
Output-----BEGIN CERTIFICATE-----

. . .

-----END CERTIFICATE-----

Снова скопируйте содержимое в буфер обмена. Не забудьте указать первую и последнюю строку.

Откройте файл с тем же именем в папкеMySQL client в каталогеclient-ssl:

nano ~/client-ssl/client-cert.pem

Вставьте содержимое из буфера обмена. Сохраните и закройте файл.

Наконец, отобразите содержимое файла клиентского ключа наMySQL server:

sudo cat /var/lib/mysql/client-key.pem
Output-----BEGIN RSA PRIVATE KEY-----

. . .

-----END RSA PRIVATE KEY-----

Скопируйте отображаемое содержимое, включая первую и последнюю строку, в буфер обмена.

НаMySQL client откройте файл с тем же именем в каталогеclient-ssl:

nano ~/client-ssl/client-key.pem

Вставьте содержимое из буфера обмена. Сохраните и закройте файл.

Клиентский компьютер должен теперь иметь все учетные данные, необходимые для доступа к серверу MySQL. Далее нам нужно изменить нашего удаленного пользователя.

Требовать сертификат от доверенного центра сертификации для удаленного пользователя

В настоящее время клиент MySQL имеет файлы для представления своего сертификата серверу при подключении. Однако сервер по-прежнему не настроен на требование сертификата клиента от доверенного ЦС.

Чтобы изменить это, снова войдите в корневую учетную запись MySQL наMySQL server:

mysql -u root -p

Далее нам нужно изменить требования к нашему удаленному пользователю. Вместо предложенияREQUIRE SSL нам нужно применить предложениеREQUIRE X509. Это подразумевает всю безопасность, обеспечиваемую предыдущим требованием, но дополнительно требует, чтобы соединяющийся клиент представил сертификат, подписанный центром сертификации, которому доверяет сервер MySQL.

Чтобы настроить требования пользователя, используйте командуALTER USER:

ALTER USER 'remote_user'@'mysql_client_IP' REQUIRE X509;

Очистите изменения, чтобы убедиться, что они применяются немедленно:

FLUSH PRIVILEGES;

Вернитесь обратно в оболочку, когда закончите:

exit

Затем мы можем проверить, чтобы убедиться, что мы все еще можем подключиться.

Проверка сертификата проверки при подключении

Сейчас самое время проверить, можем ли мы проверить обе стороны при подключении.

НаMySQL client сначала попробуйте подключиться без предоставления клиентских сертификатов:

mysql -u remote_user -p -h mysql_server_IP
OutputERROR 1045 (28000): Access denied for user 'remote_user'@'mysql_client_IP' (using password: YES)

Без предоставления сертификата клиента сервер отклоняет соединение.

Теперь подключитесь, используя параметры--ssl-ca,--ssl-cert и--ssl-key, чтобы указать на соответствующие файлы в каталоге~/client-ssl:

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

Вы должны войти в систему успешно. Выйдите из системы, чтобы восстановить доступ к сеансу оболочки:

exit

Теперь, когда мы подтвердили доступ к серверу, мы можем реализовать небольшое улучшение юзабилити.

Создайте файл конфигурации клиента MySQL

Чтобы не указывать файлы сертификатов при каждом подключении, мы можем создать простой файл конфигурации клиента MySQL.

Внутри вашего домашнего каталога на машинеMySQL client создайте скрытый файл с именем~/.my.cnf:

nano ~/.my.cnf

Вверху файла создайте раздел под названием[client]. Ниже мы можем установить параметрыssl-ca,ssl-cert иssl-key, чтобы они указывали на файлы, которые мы скопировали с сервера. Это должно выглядеть так:

~/.my.cnf

[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 -u remote_user -p -h mysql_server_ip

Теперь ваш клиент и сервер должны представлять сертификаты при согласовании соединения. Каждая сторона настроена для проверки удаленного сертификата по сертификату CA, который он имеет локально.

Заключение

Ваш сервер MySQL теперь должен быть настроен так, чтобы требовать защищенные соединения для удаленных клиентов. Кроме того, если вы выполнили шаги для проверки соединений с использованием центра сертификации, обе стороны установят некоторый уровень доверия, что удаленная сторона является законной.

Related